diff --git a/src/routing_layer/nat_detection.c b/src/routing_layer/nat_detection.c index eb96ab03..77f4fb1f 100644 --- a/src/routing_layer/nat_detection.c +++ b/src/routing_layer/nat_detection.c @@ -1514,6 +1514,15 @@ 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; + if (automatic && !detector->automatic) { + uint64_t now = get_time_tb(); + for (struct nat_socket *state = detector->sockets; state; state = state->next) { + if (state->phase || state->cycling || + (state->measured_profile.source == ADDRESS_SOURCE_ETCP && state->measured_profile.mapping && state->measured_profile.inbound)) + continue; + state->cold_until = now + NAT_ROUND_TB + 2500; state->due = now + 2500; + } + } detector->automatic = !!automatic; detector->reservation_dirty = 1; DEBUG_INFO(DEBUG_CATEGORY_NAT, "NAT automatic endpoint measurements %s", automatic ? "enabled" : "disabled"); diff --git a/tests/stream_netns/nat_scenario.py b/tests/stream_netns/nat_scenario.py index 18c2f606..c13b86fc 100644 --- a/tests/stream_netns/nat_scenario.py +++ b/tests/stream_netns/nat_scenario.py @@ -62,6 +62,7 @@ def check_profiles(scenario): verified = {} for owner in public + [node for node in NODES if node.nat]: observer = second if owner.name == first.name else first + agents[owner.name].rpc("nat_auto", enabled=1) if not scenario.args.tcp_only: contacts = set(profile(agents[owner.name].rpc("stats"), "udp")["contacts"]) helper = next((node for node in public if node.name not in {owner.name, observer.name} and node.ip not in contacts), None) @@ -103,6 +104,7 @@ def check_profiles(scenario): print(f"NAT {owner.name}/{protocol}: {actual['mapping']} / {actual['inbound']}" f" external={actual['external'] or '-'} reason={actual['reason']}", flush=True) verified[owner.name] = observed + agents[owner.name].rpc("nat_auto", enabled=0) (scenario.network.directory / "nat-profiles.json").write_text(json.dumps(verified, indent=2) + "\n") # Повтор на использовавшемся порту сохраняет mapping, но не обновляет OPEN