From 37e897d0d26ee9ebb15170b5a6b42cc4b3c35b02 Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 12 Oct 2026 00:09:13 +0200 Subject: [PATCH] Plan unified STUN and ETCP endpoint measurements --- doc/nat_detection.txt | 76 +++++++++++++++++++++++++++++++++++++++++++ doc/tasks.md | 13 ++++++++ 2 files changed, 89 insertions(+) diff --git a/doc/nat_detection.txt b/doc/nat_detection.txt index f16995d1..2df1f3f3 100644 --- a/doc/nat_detection.txt +++ b/doc/nat_detection.txt @@ -143,3 +143,79 @@ test_sock_match: независимость политики от фактов, tests/stream_netns --nat-only: 16 настоящих uTun с 10 NAT, проверка всех UDP/TCP профилей и точного собственного внешнего адреса. --nat-check включает эту фазу до обычных JOIN/Merkle/BGP/streaming. Главный network namespace не меняется. + +Объединение со STUN: проект доработки после rebase 2026-10-12 +----------------------------------------------------------- + +Сейчас stun_nat — дополнительная локальная диагностика другого UDP-порта. +Она возвращает mapped адреса, MATCH/EIM/ADM/APDM и EIF/ADF/APDF, но не меняет +address_profile или NODEINFO. Это корректная граница текущего модуля: общий +интерфейс и одинаковый SO_MARK/FIB не означают одинаковое состояние двух портов. +В ходе rebase тест переведён на address_profile, probe_only исключён из сканирования. +Сборка и полный основной набор из 145 тестов прошли. + +Варианты: + 1. Оставить независимый порт: показывать STUN рядом с профилем ETCP, с точным + тестовым endpoint и временем. Полезно для диагностики расхождений, но ни + внешний порт, ни классификация не становятся фактами рабочего сокета. + 2. Для участия STUN в рабочем профиле использовать фактический ETCP UDP fd. + Рекомендуемый вариант для объединённого детектора; требует доработок ниже. + +Владение и алгоритм варианта 2: + - NAT_DETECTION остаётся единственным планировщиком раундов и владельцем + address_profile/nat_addr/публикации. STUN выполняет транзакции и отдаёт + наблюдения; самостоятельно не назначает профиль и не закрывает ETCP fd. + - Каждое наблюдение содержит actual local IP:port, socket ID, generation, + round, endpoint наблюдателя, observed endpoint, monotonic time и причину. + Имя сокета — только метка для человека. Диагностика другого порта хранится + отдельно и не проходит проверку принадлежности рабочему endpoint. + - В прямом UDP read_callback распознавать ответы STUN до ETCP decrypt: + формат/cookie, активная 96-битная транзакция, ожидаемый source, receiving + socket/generation/round. Единственный читатель fd остаётся у транспорта; + STUN не добавляет второго uasync-reader. Отправки проходят общий учёт контактов. + - Раунд выбирает доступные ETCP или настроенные STUN-наблюдатели. Разные + имена серверов не заменяют разные реальные IP. Для обычного STUN нужны + независимые IP; расширенные пробы требуют фактически доступных alternate IP/port. + - До mapping-проб выполнять чистые ingress/CHANGE-пробы, затем наблюдения + на разных назначениях, затем повтор исходного наблюдения. Обе проверки + используют общую историю всех UDP-отправок, а не отдельную STUN history. + Загрязнение теста или отсутствие независимого адреса даёт частичный результат. + - Обычный Binding дополняет наблюдения. MATCH сам по себе не назначает EIM; + стабильное расхождение назначений даёт DEPENDENT. RFC5780 EIM соответствует + EIM либо UNCHANGED при отсутствии трансляции, ADM/APDM — DEPENDENT. + - Положительный чистый ingress может подтвердить OPEN. ADF/APDF сохранять + в диагностике; CONTACT_REQUIRED публиковать после подтверждённого перехода + до/после контакта на неизменном endpoint. Таймаут CHANGE без доказательства + работы альтернативной отправки не отличает фильтрацию от поведения сервера. + - У STUN нет проверки ключа ETCP; FINGERPRINT — CRC, не аутентификация. + Расхождение с действующими аутентифицированными фактами требует повторного + раунда и лога обоих наблюдений, а не перезаписи по принципу «последний ответ». + Таймаут дополнительной проверки не сбрасывает ещё действующий профиль. + - Свежесть проверяется по локальному monotonic времени. checked_at/evidence_id + формирует владелец при применении результата, в единой транзакции публикации. + Смена endpoint/маршрута, generation, закрытие, reload и stop отменяют все пробы. + TCP и SOCKS5 не наследуют native UDP-факты; существующая listener-проверка остаётся. + +Порядок реализации: (1) общий контракт наблюдения и жизненного цикла, +(2) STUN-транзакции через рабочий UDP и безопасный demux, +(3) единое расписание/история контактов и применение результатов, +(4) локальные тесты и RFC5780-серверы в существующем изолированном стенде. + +Обязательные новые тесты: разные NAT-свойства тестового и рабочего портов; +ETCP DATA/INIT во время STUN; чужие/поздние ID и reused socket generation; +контакт к alternate IP через INIT/ACK/keepalive перед CHANGE; отсутствие RFC5780, +молчаливое игнорирование CHANGE, потери и недоступные альтернативы; +расхождения STUN/ETCP, TTL, reload, смена маршрута без смены IP, shutdown/leaks; +реальные EIM/EIF, EIM/ADF, EIM/APDF, ADM/APDM на netns NAT с RTT/jitter/loss. + +В текущей независимой диагностике до объединения остаются ограничения: +source_snapshot обнуляет исходный порт и не сохраняет generation; сканирование +не замечает пересоздание рабочего сокета с тем же именем/IP/настройками; +неизменившийся источник не обновляется без явного recheck; свежий тест исключает +только непосредственно предыдущий порт, а не всю возможную историю NAT этого tuple. +Эти результаты нельзя автоматически использовать как актуальные рабочие факты. + +Нормативные протоколы: https://www.rfc-editor.org/rfc/rfc8489 (Binding, transaction ID), +https://www.rfc-editor.org/rfc/rfc5780#section-4.3 (mapping), #section-4.4 (filtering), +#section-4.5 (порядок и зависимость от прежнего состояния). Приведённая схема +владения и согласования результатов — проект интеграции uTun, а не требование RFC. diff --git a/doc/tasks.md b/doc/tasks.md index f802a355..e7f0efd1 100644 --- a/doc/tasks.md +++ b/doc/tasks.md @@ -4,6 +4,19 @@ ## Текущие задачи +[ ] **STUN: объединённый детектор рабочего endpoint** — план и варианты в + `doc/nat_detection.txt`, раздел после rebase 12.10.2026. Текущий STUN измеряет + другой порт, его результат нельзя переносить в ETCP/NODEINFO. Нужны единый + владелец профиля, STUN через рабочий UDP fd, общая история контактов и отмена + по socket generation. Дополнительно проверить молчаливое игнорирование CHANGE, + повторное использование тестовых портов, давность и смену маршрута без смены IP. + +[ ] **check.sh: изоляция сетевых integration-тестов** — после основного набора + автоматически запускает check-proxy/burst/load при доступном sudo. Скрипты + меняют rp_filter, таблицу 100 и iptables главного namespace; cleanup выставляет + rp_filter=1 вместо сохранённого значения. Перенести тесты в отдельный namespace + и проверять неизменность родительской сети, как в tests/stream_netns. + [ ] **Стриминг: реализация по stream.txt** — 10.10.2026: ТЗ и этапы: doc/stream.txt, разделы 15–16. Основа данных реализована в src/stream: подписанные FEC-блоки 1300 байт, общий буфер 32 МБ, относительные timestamp-метрики,