|
|
|
|
@ -1153,6 +1153,54 @@ static uint64_t candidate_fingerprint(struct nat_socket *state, int ready) {
|
|
|
|
|
return total; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Ограниченное окно сохраняет свежие IP для первого ingress; изменение доступных endpoint обновляет резерв один раз. */ |
|
|
|
|
uint64_t nat_detection_probe_delay(struct NAT_DETECTION *detector) { |
|
|
|
|
if (!detector || detector->stopping) return 0; |
|
|
|
|
uint64_t now = get_time_tb(), delay = 0; |
|
|
|
|
if (detector->reservation_dirty) { |
|
|
|
|
detector->reservation_dirty = 0; |
|
|
|
|
for (struct ETCP_SOCKET *socket = detector->instance->etcp_sockets; socket; socket = socket->next) { |
|
|
|
|
if (socket->is_tcp || socket->probe_only || socket->socks_udp || |
|
|
|
|
socket->type == CFG_SERVER_TYPE_PRIVATE || socket->type == CFG_SERVER_TYPE_LOCAL) continue; |
|
|
|
|
struct nat_socket *state = socket_state(detector, socket, 1); |
|
|
|
|
if (!state) continue; |
|
|
|
|
uint64_t fingerprint = candidate_fingerprint(state, 0); |
|
|
|
|
if (fingerprint != state->reservation_fingerprint) { |
|
|
|
|
state->reservation_fingerprint = fingerprint; |
|
|
|
|
if (fingerprint) state->cold_until = now + NAT_ROUND_TB + 2500; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for (struct nat_socket *state = detector->sockets; state; state = state->next) { |
|
|
|
|
if (state->socket->is_tcp || !state->reservation_fingerprint || state->cold_until <= now || |
|
|
|
|
(!detector->automatic && !state->phase && !state->forced) || |
|
|
|
|
(state->measured_profile.source == ADDRESS_SOURCE_ETCP && state->measured_profile.mapping && state->measured_profile.inbound)) |
|
|
|
|
continue; |
|
|
|
|
if (state->cold_until - now > delay) delay = state->cold_until - now; |
|
|
|
|
} |
|
|
|
|
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; |
|
|
|
|
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; |
|
|
|
|
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()) { |
|
|
|
|
owner = binding->owner; break; |
|
|
|
|
} |
|
|
|
|
if (owner <= detector->instance->node_id) return 1; |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT observation deferred for cold owner priority socket=%s group=%016llx requester=%016llx owner=%016llx", |
|
|
|
|
socket->name, (unsigned long long)group_id, (unsigned long long)peer, (unsigned long long)owner); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Изменения нескольких групп объединяются; известный полный ETCP-профиль не перепроверяется из-за нового соседа. */ |
|
|
|
|
static void topology_wake(void *arg) { |
|
|
|
|
struct NAT_DETECTION *detector = arg; detector->topology_wake = NULL; |
|
|
|
|
@ -1276,7 +1324,7 @@ struct NAT_DETECTION *nat_detection_create(struct UTUN_INSTANCE *instance) {
|
|
|
|
|
} |
|
|
|
|
struct NAT_DETECTION *detector = u_calloc(1, sizeof(*detector)); |
|
|
|
|
if (!detector) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "NAT detector allocation failed"); return NULL; } |
|
|
|
|
detector->instance = instance; detector->automatic = 1; |
|
|
|
|
detector->instance = instance; detector->automatic = 1; detector->reservation_dirty = 1; |
|
|
|
|
if (etcp_router_bind(instance, ETCP_RT_ID_NAT_DETECTION, receive_control)) { u_free(detector); return NULL; } |
|
|
|
|
etcp_add_conn_status_cbk(instance, connection_status, detector); |
|
|
|
|
etcp_add_socket_cbk(instance, socket_changed, detector, ETCP_SOCKET_EVENT_ADDR_CHANGED); |
|
|
|
|
@ -1345,6 +1393,7 @@ void nat_detection_set_allow_local(struct NAT_DETECTION *detector, int allow) {
|
|
|
|
|
void nat_detection_set_automatic(struct NAT_DETECTION *detector, int automatic) { |
|
|
|
|
if (!detector) return; |
|
|
|
|
detector->automatic = !!automatic; |
|
|
|
|
detector->reservation_dirty = 1; |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_NAT, "NAT automatic endpoint measurements %s", automatic ? "enabled" : "disabled"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|