From d70d6cb66a0cb42727dd73dee402d9a02197192b Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 17 Oct 2026 16:56:21 +0200 Subject: [PATCH] tests: ignore stale helper probes and document local source rejection --- doc/nat_detection.txt | 14 ++++++++++++-- tests/test_nat_detection_faults.c | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/doc/nat_detection.txt b/doc/nat_detection.txt index 1d41b70e..a58ad18a 100644 --- a/doc/nat_detection.txt +++ b/doc/nat_detection.txt @@ -31,8 +31,13 @@ S — рабочий сокет владельца A; B — наблюдател OBSERVE принимается по UDP, фактический source IP:port возвращается через подписанный зашифрованный router-отчёт OBSERVATION. Прямой PONG не требуется. +Получатель проверяет публичность source IP: локальный/немаршрутизируемый +источник не подходит для интернет-проверки. OBSERVATION возвращает отказ, +наблюдение не сохраняется; владелец переходит к следующему кандидату. Отдельный короткий UDP-обмен с B поддерживает mapping и контролирует входящий путь. Его отсутствие запрещает отрицательный вывод о filtering, но не стирает mapping. +Обычное LAN-наблюдение INIT_RESPONSE сохраняется в линке и не сбрасывает +интернет-профиль сокета. Локальный путь управления сам по себе допустим. У source-сокета C один отдельный probe_only UDP-сокет помощника. Он не входит в NODEINFO/NCD и не открывает фильтр собственного рабочего endpoint C. @@ -47,7 +52,10 @@ UDP-раунд 3. C отправляет начальную серию входящих проб, без автоматического UDP-ответа. Затем через B измеряет mapping своего отдельного сокета; отчёт также идёт через router. Начальная серия могла уже подтвердить OPEN. -4. Незнакомость проверяет получатель S по фактическому source IP. IP B, +4. Публичность и незнакомость проверяет получатель S по фактическому source IP. + Локальный/немаршрутизируемый source немедленно исключает помощника из этой попытки. + Проверка идентичности, round и token предшествует отказу; чужой или поздний + пакет не может переключить кандидата. IP B, собственный внешний IP S (hairpin) и прежний исходящий контакт не подходят: A запрашивает другого помощника. Объявленный IP и Node ID не заменяют проверку. 5. Если начального входа нет, C выполняет полную серию PRE до исходящего @@ -145,7 +153,9 @@ test_nat_detection: несколько endpoint, одинаковые IP узл TCP listener, транзитная CHAT-группа, recheck и teardown. test_nat_detection_faults (Linux): реальные UDP/router-пакеты, потерянные PONG, PRE/POST, поздний PRE после контакта, посторонняя отправка, пропавший отчёт, -разные/нестабильные mapping, совпавший IP B, hairpin и перебор IP наблюдателя. +разные/нестабильные mapping, совпавший IP B, hairpin и перебор IP наблюдателя; +локальные source OBSERVE/ingress, переход к другому помощнику, чужой token +и сохранение интернет-профиля после наблюдения LAN. Только часы тестового poll ускоряются; сокеты, шифрование и протокол настоящие. tests/stream_netns/run.py --nat-only: 16 ядер, 6 настоящих NAT-шлюзов, EIM open/filtered/strict. Главный network namespace проверяется на неизменность. diff --git a/tests/test_nat_detection_faults.c b/tests/test_nat_detection_faults.c index c487cb18..b2c8a641 100644 --- a/tests/test_nat_detection_faults.c +++ b/tests/test_nat_detection_faults.c @@ -145,7 +145,7 @@ void __wrap_nat_detection_receive_ingress(struct NAT_DETECTION *detector, struct assert(after.phase == before.phase && after.helper_reselections == before.helper_reselections); __real_nat_detection_receive_ingress(detector, socket, key, source, tag, length); assert(!nat_detection_get_status(detector, socket, &after)); - if (before.phase) { + if (before.phase && before.helper == fault.alias->node_id) { assert(!after.phase && after.helper_reselections == before.helper_reselections + 1); assert(after.reason == NAT_REASON_NO_HELPER); fault.injected++; }