diff --git a/src/routing_layer/nat_detection.c b/src/routing_layer/nat_detection.c index 6b9cc306..96c0bd38 100644 --- a/src/routing_layer/nat_detection.c +++ b/src/routing_layer/nat_detection.c @@ -1181,15 +1181,25 @@ uint64_t nat_detection_probe_delay(struct NAT_DETECTION *detector) { return delay > 10000 ? 10000 : delay; } -int nat_detection_observe_allowed(struct NAT_DETECTION *detector, struct ETCP_SOCKET *socket, - const uint8_t peer_key[32], const uint8_t *tag, size_t length) { - if (!detector || !socket || socket->probe_only || !tag || length != ROUTE_OBSERVE_TAG_SIZE || memcmp(tag, "NAT3UDP!", 8)) return 1; +int nat_detection_ping_allowed(struct NAT_DETECTION *detector, struct ETCP_SOCKET *socket, + const uint8_t peer_key[32], const struct sockaddr_storage *source, + uint8_t flags, const uint8_t *tag, size_t length) { + if (!detector || !socket || socket->probe_only || (flags & ETCP_PING_FLAG_ADDRESS_CHECK)) return 1; nat_detection_probe_delay(detector); struct nat_socket *state = socket_state(detector, socket, 0); if (!state || !state->reservation_fingerprint || state->cold_until <= get_time_tb() || (!detector->automatic && !state->phase && !state->forced) || (state->measured_profile.source == ADDRESS_SOURCE_ETCP && state->measured_profile.mapping && state->measured_profile.inbound)) return 1; - uint64_t peer = sc_derive_node_id_from_pubkey(peer_key), group_id = read64(tag + 25), round = read64(tag + 17), owner = peer; + uint64_t peer = sc_derive_node_id_from_pubkey(peer_key); + if (!(flags & ETCP_PING_FLAG_OBSERVE)) { + history_load(state); + if (contacted(state, source)) return 1; + DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT background PING reply deferred socket=%s peer=%016llx source=%s", + socket->name, (unsigned long long)peer, sockaddr_storage_to_str(source).str); + return 0; + } + if (!tag || length != ROUTE_OBSERVE_TAG_SIZE || memcmp(tag, "NAT3UDP!", 8)) return 1; + uint64_t group_id = read64(tag + 25), round = read64(tag + 17), owner = peer; if (state->phase && state->group_id == group_id && state->round == round && (state->helper == peer || state->observer == peer)) return 1; for (struct nat_binding *binding = detector->bindings; binding; binding = binding->next) if (binding->group_id == group_id && binding->round == round && binding->helper == peer && binding->expires > get_time_tb()) { diff --git a/src/routing_layer/nat_detection.h b/src/routing_layer/nat_detection.h index b2387ce7..59733262 100644 --- a/src/routing_layer/nat_detection.h +++ b/src/routing_layer/nat_detection.h @@ -43,8 +43,9 @@ void nat_detection_cancel_group(struct NAT_DETECTION *detector, uint64_t group_i /* Короткий приоритет начального измерения перед фоновыми UDP-пробами достижимости; задержка в timebase. */ uint64_t nat_detection_probe_delay(struct NAT_DETECTION *detector); /* Холодные измерения сериализуются по node_id; делегированные пробы более раннего owner пропускаются. */ -int nat_detection_observe_allowed(struct NAT_DETECTION *detector, struct ETCP_SOCKET *socket, - const uint8_t peer_key[32], const uint8_t *tag, size_t length); +int nat_detection_ping_allowed(struct NAT_DETECTION *detector, struct ETCP_SOCKET *socket, + const uint8_t peer_key[32], const struct sockaddr_storage *source, + uint8_t flags, const uint8_t *tag, size_t length); void nat_detection_link_ready(struct NAT_DETECTION *detector, struct ETCP_LINK *link); void nat_detection_cancel_for_conn(struct NAT_DETECTION *detector, struct ETCP_CONN *connection); void nat_detection_socket_removed(struct NAT_DETECTION *detector, struct ETCP_SOCKET *socket); diff --git a/src/transport_layer/etcp_connections.c b/src/transport_layer/etcp_connections.c index 3f46de74..202ba4ea 100644 --- a/src/transport_layer/etcp_connections.c +++ b/src/transport_layer/etcp_connections.c @@ -1796,8 +1796,8 @@ static int handle_ping(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, const if ((flags & ETCP_PING_FLAG_OBSERVE) && (flags & ETCP_PING_FLAG_ADDRESS_CHECK)) { DEBUG_WARN(DEBUG_CATEGORY_NAT, "UDP probe has incompatible flags=%02x", flags); return 7; } + if (!nat_detection_ping_allowed(e_sock->instance->nat_det, e_sock, decrypted_pubkey, addr, flags, udata, ulen)) return 0; if ((flags & ETCP_PING_FLAG_OBSERVE) && e_sock->instance->nat_det) { - if (!nat_detection_observe_allowed(e_sock->instance->nat_det, e_sock, decrypted_pubkey, udata, ulen)) return 0; nat_detection_record_observation(e_sock->instance->nat_det, e_sock, decrypted_pubkey, addr, udata, ulen); } if ((flags & ETCP_PING_FLAG_ADDRESS_CHECK) && e_sock->instance->nat_det)