From 164a3a1f0f77cb442d045be0d2c2fe75ef348afc Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 12 Oct 2026 00:58:50 +0200 Subject: [PATCH] Keep connection attempts available for STUN hints and verify signed provenance --- src/routing_layer/sock_match.c | 3 ++- tests/test_nat_detection.c | 9 +++++++-- tests/test_sock_match.c | 8 +++++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/routing_layer/sock_match.c b/src/routing_layer/sock_match.c index 1013179b..f30aef8f 100644 --- a/src/routing_layer/sock_match.c +++ b/src/routing_layer/sock_match.c @@ -12,7 +12,8 @@ uint8_t sock_target_class(uint8_t address_type, uint8_t config_type, const struct address_profile *profile, int public_address, uint64_t now_us) { if (!public_address || config_type == CFG_SERVER_TYPE_PRIVATE || config_type == CFG_SERVER_TYPE_LOCAL) return SOCK_TC_PRIV; - if (address_type == TOPO_ADDR_NAT && profile && profile->mapping == ADDRESS_MAP_DEPENDENT) return SOCK_TC_UNREACH; + if (address_type == TOPO_ADDR_NAT && profile && profile->source == ADDRESS_SOURCE_ETCP && + profile->mapping == ADDRESS_MAP_DEPENDENT) return SOCK_TC_UNREACH; if (!address_profile_fresh(profile, now_us)) return SOCK_TC_PROBE; if (profile->inbound == ADDRESS_IN_OPEN) return SOCK_TC_PUB; if (profile->inbound == ADDRESS_IN_CONTACT) return SOCK_TC_CONTACT; diff --git a/tests/test_nat_detection.c b/tests/test_nat_detection.c index c47ffd23..1c9a6f15 100644 --- a/tests/test_nat_detection.c +++ b/tests/test_nat_detection.c @@ -26,24 +26,29 @@ static void check_snapshot(struct UTUN_INSTANCE *owner, struct ETCP_SOCKET *sock assert(meta && meta->address_profile.evidence_id == socket->address_profile.evidence_id && meta->address_profile.checked_at == socket->address_profile.checked_at && meta->address_profile.mapping == socket->address_profile.mapping && - meta->address_profile.inbound == socket->address_profile.inbound); + meta->address_profile.inbound == socket->address_profile.inbound && + meta->address_profile.source == ADDRESS_SOURCE_ETCP); struct address_profile saved = meta->address_profile; meta->address_profile.checked_at++; assert(topo_node_verify(node) < 0); meta->address_profile = saved; + meta->address_profile.source = ADDRESS_SOURCE_STUN; + assert(topo_node_verify(node) < 0); + meta->address_profile = saved; meta->address_profile.inbound = ADDRESS_IN_CONTACT; assert(topo_node_verify(node) < 0); meta->address_profile = saved; assert(topo_node_verify(node) == 0); sqlite3_stmt *statement = NULL; assert(sqlite3_prepare_v2(owner->topo_sqlite_db, - "SELECT nat_mapping,nat_inbound,nat_evidence,nat_checked FROM node_addresses WHERE node_id=? AND socket_id=?", + "SELECT nat_mapping,nat_inbound,nat_evidence,nat_checked,nat_source FROM node_addresses WHERE node_id=? AND socket_id=?", -1, &statement, NULL) == SQLITE_OK); sqlite3_bind_int64(statement, 1, (sqlite3_int64)owner->node_id); sqlite3_bind_int(statement, 2, socket->sock_id); assert(sqlite3_step(statement) == SQLITE_ROW); assert(sqlite3_column_int(statement, 0) == saved.mapping && sqlite3_column_int(statement, 1) == saved.inbound); assert((uint64_t)sqlite3_column_int64(statement, 2) == saved.evidence_id); assert((uint64_t)sqlite3_column_int64(statement, 3) == saved.checked_at); + assert(sqlite3_column_int(statement, 4) == ADDRESS_SOURCE_ETCP); sqlite3_finalize(statement); } diff --git a/tests/test_sock_match.c b/tests/test_sock_match.c index ecaa07f3..068bb3c2 100644 --- a/tests/test_sock_match.c +++ b/tests/test_sock_match.c @@ -13,7 +13,8 @@ int main(void) { const uint32_t public_ip = htonl(UINT32_C(0xc633640b)); const uint32_t private_ip = htonl(UINT32_C(0x0a400102)); struct address_profile unknown = {0}; - struct address_profile open = {.mapping = ADDRESS_MAP_EIM, .inbound = ADDRESS_IN_OPEN, .evidence_id = 1, .checked_at = now}; + struct address_profile open = {.mapping = ADDRESS_MAP_EIM, .inbound = ADDRESS_IN_OPEN, .source = ADDRESS_SOURCE_ETCP, + .evidence_id = 1, .checked_at = now}; struct address_profile contact = open; contact.inbound = ADDRESS_IN_CONTACT; struct address_profile dependent = open; dependent.mapping = ADDRESS_MAP_DEPENDENT; dependent.inbound = ADDRESS_IN_UNKNOWN; @@ -39,6 +40,11 @@ int main(void) { assert(!sock_match(&local, TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &open, public_ip)); assert(sock_match(&local, TOPO_ADDR_INTERFACE, CFG_SERVER_TYPE_NAT, &dependent, private_ip)); assert(!sock_match(&outgoing, TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &dependent, public_ip)); + dependent.source = ADDRESS_SOURCE_STUN; + assert(sock_match(&outgoing, TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &dependent, public_ip)); + assert(address_profile_valid(&dependent)); + dependent.source = ADDRESS_SOURCE_NONE; + assert(!address_profile_valid(&dependent)); outgoing.now_us = now + ADDRESS_PROFILE_TTL_US + 1; assert(sock_match(&outgoing, TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &open, public_ip)); /* Смена времени/давности снижает уверенность, сохраняя возможность реального handshake. */