tests: verify TCP IP-only detection across real NAT gateways
This commit is contained in:
1 parent
62aee9f01c
commit
b588f8e9f4
2 files changed
+22
-14
No files matched your search
@@ -50,10 +50,12 @@ JOIN/стриминг в этом режиме не запускаются.
|
||||
до первого исходящего контакта рабочего сокета с помощником.
|
||||
|
||||
Проверяются отдельно mapping и inbound каждого UDP endpoint, точный собственный
|
||||
внешний IP:port, отсутствие ложного STRICT без помощника и корректность TCP listener.
|
||||
внешний IP:port и отсутствие ложного STRICT без помощника.
|
||||
Ожидания: public — UNCHANGED/OPEN, cone — EIM/OPEN, restricted — EIM/CONTACT_REQUIRED,
|
||||
strict — DEPENDENT без универсального внешнего адреса. TCP за NAT без port forwarding
|
||||
остаётся UNKNOWN/no_listener. Результаты: `nat-profiles.json`, `nat-result.json`;
|
||||
strict — DEPENDENT без универсального внешнего адреса. Для TCP один настоящий TCP-пир
|
||||
сообщает внешний IP: public — UNCHANGED/UNKNOWN, за NAT — UNKNOWN/UNKNOWN с source=ETCP.
|
||||
Во всех TCP-наблюдениях внешний порт 0, раундов с помощником нет; тип NAT и вход не проверяются.
|
||||
Результаты: `nat-profiles.json`, `nat-result.json`;
|
||||
обычная телеметрия также включает `address_profiles`, контакты и причину неполного измерения.
|
||||
|
||||
Полная baseline-проверка длится 120 секунд после старта доставки, плюс калибровка и JOIN. Она покрывает оборот 16-битного timestamp и несколько циклов проб. Короткая проверка:
|
||||
|
||||
@@ -18,12 +18,12 @@ def check_profiles(scenario):
|
||||
for agent in agents.values():
|
||||
agent.rpc("nat_auto", enabled=1)
|
||||
|
||||
def connect(source, target):
|
||||
pair = (source.name, target.name)
|
||||
def connect(source, target, protocol=transport):
|
||||
pair = (source.name, target.name, protocol)
|
||||
if pair in connected:
|
||||
return
|
||||
snapshot = agents[target.name].rpc("snapshot")["snapshot"]
|
||||
agents[source.name].rpc("nat_link", snapshot=snapshot, socket=transport)
|
||||
agents[source.name].rpc("nat_link", snapshot=snapshot, socket=protocol)
|
||||
target_id = agents[target.name].identity
|
||||
source_id = agents[source.name].identity
|
||||
scenario.wait(f"nat-link-{source.name}-{target.name}",
|
||||
@@ -83,16 +83,19 @@ def check_profiles(scenario):
|
||||
protocols = ["tcp"] if scenario.args.tcp_only else ["udp", "tcp"] if scenario.args.tcp else ["udp"]
|
||||
observed = {}
|
||||
for protocol in protocols:
|
||||
if protocol == "tcp" and owner.nat:
|
||||
# Приватный TCP listener не имеет обнаруженного публичного endpoint.
|
||||
agents[owner.name].rpc("nat_check", socket="tcp", observer=agents[observer.name].identity)
|
||||
data = scenario.wait(f"nat-private-tcp-{owner.name}", lambda statistics:
|
||||
profile(statistics[owner.name], "tcp")["reason"] == "no_listener", 5)
|
||||
if protocol == "tcp":
|
||||
# Только один действующий TCP-пир, без испытания входящих и без сравнения портов.
|
||||
connect(owner, observer, "tcp")
|
||||
data = scenario.wait(f"nat-tcp-ip-{owner.name}", lambda statistics:
|
||||
profile(statistics[owner.name], "tcp")["source"] == "ETCP" and
|
||||
bool(profile(statistics[owner.name], "tcp")["external"]), 10)
|
||||
actual = profile(data[owner.name], "tcp")
|
||||
expected = ("UNKNOWN", "UNKNOWN")
|
||||
expected = ("UNKNOWN" if owner.nat else "UNCHANGED", "UNKNOWN")
|
||||
if actual["rounds"] or int(actual["helper"]):
|
||||
raise RuntimeError(f"{owner.name}: TCP IP detection unexpectedly used a helper round: {actual}")
|
||||
else:
|
||||
actual = measure(owner, observer, protocol)
|
||||
if protocol == "tcp" or not owner.nat:
|
||||
if not owner.nat:
|
||||
expected = ("UNCHANGED", "OPEN")
|
||||
else:
|
||||
gateway = next(item for item in NATS if item.name == owner.nat)
|
||||
@@ -100,7 +103,10 @@ def check_profiles(scenario):
|
||||
"strict": ("DEPENDENT", "UNKNOWN")}[gateway.mode]
|
||||
if (actual["mapping"], actual["inbound"]) != expected:
|
||||
raise RuntimeError(f"{owner.name}/{protocol}: expected {expected}, detector returned {actual}")
|
||||
if expected[0] == "EIM":
|
||||
if protocol == "tcp":
|
||||
ip = next(item for item in NATS if item.name == owner.nat).ip if owner.nat else owner.ip
|
||||
external = f"{ip}:0"
|
||||
elif expected[0] == "EIM":
|
||||
gateway = next(item for item in NATS if item.name == owner.nat)
|
||||
external = f"{gateway.ip}:{owner.mapped_port}"
|
||||
elif expected[0] == "UNCHANGED":
|
||||
|
||||
Reference in new issue
Block a user