diff --git a/src/config_parser.c b/src/config_parser.c index 28ae9f50..68d8a416 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -441,6 +441,10 @@ static int parse_server(const char *key, const char *value, struct CFG_SERVER *s if (srv->loss_rate > 100) srv->loss_rate = 100; return 0; } + if (strcmp(key, "only_local") == 0) { + srv->only_local = atoi(value) ? 1 : 0; + return 0; + } return 0; } diff --git a/src/config_parser.h b/src/config_parser.h index c606110c..7c700142 100644 --- a/src/config_parser.h +++ b/src/config_parser.h @@ -37,6 +37,7 @@ struct CFG_SERVER { uint8_t type; // public/nat/private int mtu; int loss_rate; // packet loss rate in percent (0-100), default 0 + uint8_t only_local; // 1 = only local connections, no forwarding }; struct CFG_CLIENT_LINK { diff --git a/src/etcp_connections.c b/src/etcp_connections.c index ef899210..8f0c491d 100644 --- a/src/etcp_connections.c +++ b/src/etcp_connections.c @@ -92,6 +92,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; // padding int s = rand() % (link->handshake_maxsize - link->handshake_minsize) + link->handshake_minsize; @@ -449,6 +450,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S uint8_t type = server->type; int mtu = server->mtu ? server->mtu : instance->config->global.mtu; int loss_rate = server->loss_rate; + uint8_t only_local = server->only_local; char* name = server->name; struct ETCP_SOCKET* e_sock = u_calloc(1, sizeof(struct ETCP_SOCKET)); @@ -556,6 +558,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S e_sock->nat_type = type; // initial type from config, updated after NAT detection e_sock->mtu = mtu; e_sock->loss_rate = loss_rate; + e_sock->only_local = only_local; DEBUG_INFO(DEBUG_CATEGORY_BGP, "Add Socket type=%d", type); e_sock->next = instance->etcp_sockets; instance->etcp_sockets = e_sock; @@ -1166,6 +1169,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { 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]; uint64_t peer_id = be64toh(*(uint64_t*)ack_hdr->id); @@ -1292,6 +1296,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { // Link exists - reuse it for recovery 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; // For CHANNEL_INIT (0x04): if link already initialized - no reset, otherwise reset // For INIT_REQUEST (0x02): always reset @@ -1315,6 +1320,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { if (!link) { if (new_conn) etcp_connection_close(conn); errorcode=66; DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "etcp_connections_read_callback: failed to create link for connection"); goto ec_fr; }// облом 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; // For new links: INIT_REQUEST (0x02) causes reset, CHANNEL_INIT (0x04) does not if (ack_hdr->code == ETCP_INIT_REQUEST || new_conn) { @@ -1337,6 +1343,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { 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]; @@ -1355,6 +1362,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { ack_repl_hdr->mtu[1]=link->mtu_local; 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; // 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; @@ -1450,6 +1458,7 @@ process_decrypted: link->mtu = link->mtu_local < link->mtu_remote ? link->mtu_local : link->mtu_remote; link->remote_link_id = pkt->data[offset++]; link->remote_socket_id = pkt->data[offset++]; + link->remote_only_local = pkt->data[offset++]; // Parse NAT IP:port from response (new format includes 4+2 bytes) if (pkt_len >= 19) { diff --git a/src/etcp_connections.h b/src/etcp_connections.h index c701aebd..1030b6ab 100644 --- a/src/etcp_connections.h +++ b/src/etcp_connections.h @@ -72,6 +72,7 @@ struct ETCP_SOCKET { uint8_t nat_type; // NAT_TYPE_* (detected by server) uint32_t local_defaultroute_ip; // auto-detected IPv4 for public servers (network byte order) uint8_t local_defaultroute_ip6[16]; // auto-detected IPv6 for public servers + uint8_t only_local; // 1 = only local connections, no forwarding }; // NAT check status @@ -116,6 +117,7 @@ struct ETCP_LINK { uint8_t local_link_id; // id моего линка 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 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 f246aca0..f187f283 100644 --- a/src/route_bgp.c +++ b/src/route_bgp.c @@ -572,7 +572,7 @@ 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) return item->conn; + if (item && item->conn && item->conn != exclude && item->conn->links && item->conn->links->remote_only_local==0) return item->conn; e = e->next; } return NULL;