From f02603f8ac5b2b3d9ea4df56c7e1669bb2b05b1b Mon Sep 17 00:00:00 2001 From: Evgeny Date: Thu, 23 Apr 2026 22:44:43 +0300 Subject: [PATCH] Add socket type (public/nat/private) to handshake and skip private nodes in NAT detection --- src/etcp_connections.c | 29 ++++++++++++++++++----------- src/etcp_connections.h | 1 + src/route_bgp.c | 10 +++++++++- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/etcp_connections.c b/src/etcp_connections.c index 6786b6ac..12825a31 100644 --- a/src/etcp_connections.c +++ b/src/etcp_connections.c @@ -100,6 +100,7 @@ static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset) { dgram->data[offset++] = link->local_link_id; dgram->data[offset++] = link->conn ? link->conn->sock_id : 0; dgram->data[offset++] = link->conn ? link->conn->only_local : 0; + dgram->data[offset++] = link->conn ? link->conn->type : CFG_SERVER_TYPE_UNKNOWN; // padding int s = rand() % (link->handshake_maxsize - link->handshake_minsize) + link->handshake_minsize; @@ -1211,11 +1212,12 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { uint8_t mtu[2]; uint8_t keepalive[2]; uint8_t recovery[2]; - uint8_t link_id; - uint8_t remote_socket_id; - uint8_t only_local; - uint8_t pubkey[SC_PUBKEY_SIZE]; - } *ack_hdr=(void*)&pkt->data[0]; + uint8_t link_id; + uint8_t remote_socket_id; + uint8_t only_local; + uint8_t type; + uint8_t pubkey[SC_PUBKEY_SIZE]; + } *ack_hdr=(void*)&pkt->data[0]; uint64_t peer_id = be64toh(*(uint64_t*)ack_hdr->id); if (ack_hdr->code == ETCP_PING) { uint64_t nonce = be64toh(*(uint64_t*)(pkt->data + 9)); @@ -1358,6 +1360,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { link->remote_link_id = ack_hdr->link_id; link->remote_socket_id = ack_hdr->remote_socket_id; link->remote_only_local = ack_hdr->only_local; + link->remote_type = ack_hdr->type; // For CHANNEL_INIT (0x04): if link already initialized - no reset, otherwise reset // For INIT_REQUEST (0x02): always reset @@ -1385,6 +1388,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { link->remote_link_id = ack_hdr->link_id; link->remote_socket_id = ack_hdr->remote_socket_id; link->remote_only_local = ack_hdr->only_local; + link->remote_type = ack_hdr->type; // For new links: check session_id to avoid false reinit if (conn->session_id != session_id) { @@ -1408,11 +1412,12 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { uint8_t session_id[4]; uint8_t mtu[2]; uint8_t link_id; - uint8_t remote_socket_id; - uint8_t only_local; - uint8_t peer_ipv4[4]; - uint8_t peer_port[2]; - } *ack_repl_hdr=(void*)&pkt->data[0]; + uint8_t remote_socket_id; + uint8_t only_local; + uint8_t type; + uint8_t peer_ipv4[4]; + uint8_t peer_port[2]; + } *ack_repl_hdr=(void*)&pkt->data[0]; // Set response code: 0x03 (with reset) or 0x05 (without reset) // response with init (0x03) only if reinit was actually done on server side @@ -1431,6 +1436,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { ack_repl_hdr->link_id = link->local_link_id; ack_repl_hdr->remote_socket_id = ack_hdr->remote_socket_id; ack_repl_hdr->only_local = e_sock->only_local; + ack_repl_hdr->type = e_sock->type; // Add client's IP:port (so client behind NAT can know its external address) if (addr.ss_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in*)&addr; @@ -1537,9 +1543,10 @@ process_decrypted: link->remote_link_id = pkt->data[offset++]; link->remote_socket_id = pkt->data[offset++]; link->remote_only_local = pkt->data[offset++]; + link->remote_type = pkt->data[offset++]; // Parse NAT IP:port from response (new format includes 4+2 bytes) - if (pkt_len >= 23) { + if (pkt_len >= 24) { uint32_t new_nat_ip; memcpy(&new_nat_ip, &pkt->data[offset], 4); offset += 4; diff --git a/src/etcp_connections.h b/src/etcp_connections.h index e371fc98..23afede6 100644 --- a/src/etcp_connections.h +++ b/src/etcp_connections.h @@ -120,6 +120,7 @@ struct ETCP_LINK { uint8_t remote_link_id; // id этого линка на peer (устанавливается в момент initialized) uint8_t remote_socket_id; // socket id peer uint8_t remote_only_local; // only_local flag from peer + uint8_t remote_type; // CFG_SERVER_TYPE_* (type of peer's socket) uint8_t nat_type; // NAT_TYPE_* (detected for this client link) uint8_t recv_keepalive; // 1 - up, 0 - down (принимаются ли пакеты) uint8_t remote_keepalive; // 1 - up, 0 - down (удаленная сторона сообщает - принимаются ли у нее пакеты) diff --git a/src/route_bgp.c b/src/route_bgp.c index 6af2e93d..8b299ace 100644 --- a/src/route_bgp.c +++ b/src/route_bgp.c @@ -586,7 +586,10 @@ static struct ETCP_CONN* route_bgp_find_third_node(struct ROUTE_BGP* bgp, struct struct ll_entry* e = bgp->senders_list->head; while (e) { struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data; - if (item && item->conn && item->conn != exclude && item->conn->links && item->conn->links->remote_only_local==0) return item->conn; + if (item && item->conn && item->conn != exclude && item->conn->links && item->conn->links->remote_only_local==0) { + // Skip nodes with private socket type - they can't help with NAT detection + if (item->conn->links->remote_type != CFG_SERVER_TYPE_PRIVATE) return item->conn; + } e = e->next; } return NULL; @@ -609,6 +612,11 @@ static void route_bgp_extract_nat_addr(struct ETCP_CONN* conn, uint32_t* nat_ip, void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* link) {// проверяем тип нат для линка link if (!bgp || !link || !link->conn || !link->etcp) return; if (link->nat_check_status == NAT_CHECK_IN_PROGRESS) return; + // Skip NAT check for private sockets - they are not reachable from outside + if (link->conn->type == CFG_SERVER_TYPE_PRIVATE) { + DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "skip nat check for private socket link"); + return; + } // Find third node to send ping through struct ETCP_CONN* third_conn = route_bgp_find_third_node(bgp, link->etcp); if (!third_conn) {