Browse Source

Plan interface STUN profiles as fallback for unavailable ETCP probes

master
evgeny 15 hours ago
parent
commit
8b8b73983b
  1. 215
      doc/nat_detection.txt
  2. 12
      doc/tasks.md

215
doc/nat_detection.txt

@ -144,78 +144,143 @@ tests/stream_netns --nat-only: 16 настоящих uTun с 10 NAT, прове
профилей и точного собственного внешнего адреса. --nat-check включает эту фазу профилей и точного собственного внешнего адреса. --nat-check включает эту фазу
до обычных JOIN/Merkle/BGP/streaming. Главный network namespace не меняется. до обычных JOIN/Merkle/BGP/streaming. Главный network namespace не меняется.
Объединение со STUN: проект доработки после rebase 2026-10-12 Резервное определение типа NAT через STUN: план 2026-10-12
----------------------------------------------------------- -------------------------------------------------------
Сейчас stun_nat — дополнительная локальная диагностика другого UDP-порта. Уточнение пользователя: STUN группирует рабочие сокеты по одинаковым IP/netif,
Она возвращает mapped адреса, MATCH/EIM/ADM/APDM и EIF/ADF/APDF, но не меняет создаёт аналогичный UDP-сокет с другим портом и определяет тип NAT для группы.
address_profile или NODEINFO. Это корректная граница текущего модуля: общий Когда ETCP не может выполнить проверку из-за нехватки узлов, используется STUN.
интерфейс и одинаковый SO_MARK/FIB не означают одинаковое состояние двух портов. Это заменяет прежнее предложение использовать STUN непосредственно на ETCP fd.
В ходе rebase тест переведён на address_profile, probe_only исключён из сканирования. Далее описан план; работающая резервная интеграция ещё не реализована.
Сборка и полный основной набор из 145 тестов прошли.
1. Реестр уникальных путей
Варианты:
1. Оставить независимый порт: показывать STUN рядом с профилем ETCP, с точным Ключ группы — (address family, фактический local IP, netif_index), без порта,
тестовым endpoint и временем. Полезно для диагностики расхождений, но ни имени и socket ID. Несколько рабочих портов одного IP/netif дают одну группу.
внешний порт, ни классификация не становятся фактами рабочего сокета. Одинаковый IP на разных netif и разные IP одного netif — разные группы.
2. Для участия STUN в рабочем профиле использовать фактический ETCP UDP fd. netif=0 сохраняет смысл автоматической маршрутизации, не приравнивается
Рекомендуемый вариант для объединённого детектора; требует доработок ниже. произвольно к явно привязанному интерфейсу. Wildcard не становится отдельным IP:
сначала нужен фактический адрес пути. Неопределённый путь получает UNKNOWN.
Владение и алгоритм варианта 2:
- NAT_DETECTION остаётся единственным планировщиком раундов и владельцем Сканировать native UDP, исключать probe_only, SOCKS5 и only_local. TCP listener
address_profile/nat_addr/публикации. STUN выполняет транзакции и отдаёт сохраняет отдельную проверку STCP: UDP-результат ему не присваивается.
наблюдения; самостоятельно не назначает профиль и не закрывает ETCP fd. Начать с IPv4, уже поддержанного stun_nat; IPv6 требует отдельного этапа:
- Каждое наблюдение содержит actual local IP:port, socket ID, generation, XOR-MAPPED IPv6, IPv6 server/config/DNS и scope/interface, без переноса IPv4-фактов.
round, endpoint наблюдателя, observed endpoint, monotonic time и причину.
Имя сокета — только метка для человека. Диагностика другого порта хранится Выбрать представителя группы, скопировать фактические bind IP/device/mark/FIB.
отдельно и не проходит проверку принадлежности рабочему endpoint. Порты исходных сокетов не копировать; проба владеет собственным fd/reader.
- В прямом UDP read_callback распознавать ответы STUN до ETCP decrypt: Разные mark/FIB/device внутри одного ключа означают неоднозначный путь:
формат/cookie, активная 96-битная транзакция, ожидаемый source, receiving группа получает UNKNOWN/incompatible_route_policy с логом, а не случайный
socket/generation/round. Единственный читатель fd остаётся у транспорта; результат первого сокета. Ключ IP/netif при этом не усложняется.
STUN не добавляет второго uasync-reader. Отправки проходят общий учёт контактов.
- Раунд выбирает доступные ETCP или настроенные STUN-наблюдатели. Разные 2. Измерение и кэш STUN
имена серверов не заменяют разные реальные IP. Для обычного STUN нужны
независимые IP; расширенные пробы требуют фактически доступных alternate IP/port. Одна активная проба и один результат на группу, независимо от числа её сокетов.
- До mapping-проб выполнять чистые ingress/CHANGE-пробы, затем наблюдения Тестовый порт случайный, отличается от рабочих портов. В пределах жизни ядра
на разных назначениях, затем повтор исходного наблюдения. Обе проверки не переиспользовать ранее измеренные порты на этом IP/netif; при исчерпании
используют общую историю всех UDP-отправок, а не отдельную STUN history. не выполнять заведомо загрязнённое входящее испытание, вернуть явную причину.
Загрязнение теста или отсутствие независимого адреса даёт частичный результат. Самостоятельно закрывать только пробный fd, отменять его DNS и таймеры.
- Обычный Binding дополняет наблюдения. MATCH сам по себе не назначает EIM;
стабильное расхождение назначений даёт DEPENDENT. RFC5780 EIM соответствует STUN запускается при появлении группы, при наличии enabled и настроенных серверов.
EIM либо UNCHANGED при отсутствии трансляции, ADM/APDM — DEPENDENT. Разные имена серверов с одинаковым IP не считаются независимыми наблюдателями.
- Положительный чистый ingress может подтвердить OPEN. ADF/APDF сохранять На чистом тестовом порту сначала проверять filtering, потом mapping и стабильность
в диагностике; CONTACT_REQUIRED публиковать после подтверждённого перехода исходного наблюдения. Переносить в кэш только завершённые пригодные свойства;
до/после контакта на неизменном endpoint. Таймаут CHANGE без доказательства потери, ошибки, отсутствие RFC5780 и сомнительный CHANGE дают UNKNOWN/причину.
работы альтернативной отправки не отличает фильтрацию от поведения сервера.
- У STUN нет проверки ключа ETCP; FINGERPRINT — CRC, не аутентификация. В результате хранить ключ группы, её generation, случайный evidence ID,
Расхождение с действующими аутентифицированными фактами требует повторного test IP:port, фактические серверы, mapped адреса, mapping/filtering, причины,
раунда и лога обоих наблюдений, а не перезаписи по принципу «последний ответ». время измерения monotonic и Unix microseconds. TTL=300с, refresh=180с,
Таймаут дополнительной проверки не сбрасывает ещё действующий профиль. повтор неполной проверки через 30с; темп новых транзакций остаётся ограниченным.
- Свежесть проверяется по локальному monotonic времени. checked_at/evidence_id Применение готового кэша к новому сокету не обновляет время измерения.
формирует владелец при применении результата, в единой транзакции публикации.
Смена endpoint/маршрута, generation, закрытие, reload и stop отменяют все пробы. 3. Выбор результата NAT_DETECTION
TCP и SOCKS5 не наследуют native UDP-факты; существующая listener-проверка остаётся.
NAT_DETECTION остаётся единственным владельцем эффективного socket profile,
Порядок реализации: (1) общий контракт наблюдения и жизненного цикла, nat_addr и публикации NODEINFO. STUN предоставляет кэш по ключу группы,
(2) STUN-транзакции через рабочий UDP и безопасный demux, уведомляет о завершении/инвалидации; сам не меняет профили рабочих сокетов.
(3) единое расписание/история контактов и применение результатов, Реестр групп не держит указателей на рабочие сокеты: потребитель проверяет
(4) локальные тесты и RFC5780-серверы в существующем изолированном стенде. собственные socket generation и актуальную принадлежность группе перед применением.
Обязательные новые тесты: разные NAT-свойства тестового и рабочего портов; Хранить отдельно собственный результат ETCP и выбранный эффективный профиль.
ETCP DATA/INIT во время STUN; чужие/поздние ID и reused socket generation; Добавить profile source: NONE / ETCP / STUN, в том числе в подпись, wire,
контакт к alternate IP через INIT/ACK/keepalive перед CHANGE; отсутствие RFC5780, SQLite и диагностические API. STUN означает резервную оценку по интерфейсу,
молчаливое игнорирование CHANGE, потери и недоступные альтернативы; ETCP — измерение рабочего endpoint. Подписывает публикацию только сам узел.
расхождения STUN/ETCP, TTL, reload, смена маршрута без смены IP, shutdown/leaks;
реальные EIM/EIF, EIM/ADF, EIM/APDF, ADM/APDM на netns NAT с RTT/jitter/loss. Приоритет: действующий измеренный ETCP -> пригодный STUN при невозможности
ETCP из-за отсутствия наблюдателя/независимого помощника -> UNKNOWN.
В текущей независимой диагностике до объединения остаются ограничения: Для STUN использовать реальные NO_OBSERVER/NO_HELPER, не общее число узлов:
source_snapshot обнуляет исходный порт и не сохраняет generation; сканирование третий узел может быть offline, несовместимым или иметь тот же IP наблюдателя.
не замечает пересоздание рабочего сокета с тем же именем/IP/настройками; После исчерпания замены таких помощников разрешать резервное применение.
неизменившийся источник не обновляется без явного recheck; свежий тест исключает Пока STUN не готов, оставить UNKNOWN или ещё действующий профиль ETCP.
только непосредственно предыдущий порт, а не всю возможную историю NAT этого tuple.
Эти результаты нельзя автоматически использовать как актуальные рабочие факты. Частичный, но измеренный ETCP не заменять целиком STUN: DEPENDENT с неизвестным
ingress является полезным результатом. В первой версии не смешивать facets
Нормативные протоколы: https://www.rfc-editor.org/rfc/rfc8489 (Binding, transaction ID), разных источников. Неудача нового раунда не стирает ещё действующий ETCP.
https://www.rfc-editor.org/rfc/rfc5780#section-4.3 (mapping), #section-4.4 (filtering), Появление подходящего помощника ускоряет повтор ETCP; его успешный результат
#section-4.5 (порядок и зависимость от прежнего состояния). Приведённая схема заменяет резервный без ожидания TTL. Не сбрасывать ETCP при завершении STUN.
владения и согласования результатов — проект интеграции uTun, а не требование RFC.
4. Преобразование и использование типа
RFC5780 EIM -> EIM; отсутствие трансляции в согласованном измерении -> UNCHANGED;
ADM/APDM и устойчивое расхождение обычных серверов -> DEPENDENT.
EIF -> OPEN; ADF/APDF -> CONTACT_REQUIRED; неизвестный facet остаётся UNKNOWN.
Это преобразование применяется с source=STUN и описывает резервную оценку.
Обычный MATCH остаётся неполной диагностикой, сам по себе не назначает EIM.
Для полного определения типа необходимы доступные серверы с RFC5780.
Тип STUN помогает выбирать прямые/reverse попытки, но не доказывает их успех.
Различное поведение NAT для рабочих и тестовых портов допустимо: источник
оценки виден в логах и метаданных, реальные факты ETCP имеют приоритет.
Не запрещать LAN/hairpin или закрывать работающую связь по резервной оценке.
NCD не объявляет рабочий endpoint недоступным только на основании STUN.
mapped IP:port тестового сокета никогда не копировать в nat_addr рабочего.
Не подставлять туда рабочий local port: NAT может изменить его независимо.
Общий внешний адрес рабочего сокета публиковать только с самостоятельным
подтверждением его EIM/endpoint средствами ETCP. При наличии одного наблюдателя
его адрес остаётся наблюдением для данного назначения, не общим NAT-адресом.
5. Жизненный цикл и диагностика
Добавление/удаление дубликата не повторяет STUN для неизменившейся группы.
Исчезновение последнего рабочего сокета удаляет группу и отменяет пробу.
Смена IP/interface/параметров маршрутизации инвалидирует соответствующий кэш;
смена маршрута без смены IP и явный recheck запускают новое измерение.
Generation относится к пути и раунду STUN, а не к имени представителя.
Поздние ответы не применяются к пересозданной группе. Reload/stop отменяют всё
до освобождения config/сокетов; порядок уничтожения не вызывает публикацию.
INFO: создание/удаление группы, начало/результат пробы, выбор source, возврат
к ETCP. DEBUG: объединённые дубликаты, transaction/generation/время/причины.
WARN/ERROR: неподходящие помощники, неоднозначный путь, timeout/ошибка/несогласованность.
В статусе доступны эффективный профиль, оба результата и причина выбора STUN.
Этапы реализации: (1) группировка и API STUN по ключу IP/netif,
(2) generation/TTL/обновление и завершение проб,
(3) source в модели/подписи/wire/SQLite/статусе,
(4) выбор резерва и возврат к ETCP, независимое хранение внешних адресов,
(5) локальные и изолированные сетевые тесты. Изменять ETCP UDP demux не требуется.
План тестов
-----------
- Два порта одного IP/netif: одна проба, применение резерва обоим сокетам.
Разные IP/netif: отдельные пробы; разные mark/FIB внутри группы: явный UNKNOWN.
- Смена представителя и удаление одного дубликата не теряют результат; удаление
последнего, новая группа и поздний ответ проверяют владение и generation.
- Нет узлов / один наблюдатель / все помощники за одним IP: STUN fallback.
Живой независимый помощник: ETCP; появление/исчезновение, TTL и обе очередности
завершения проверяют приоритет. Частичный ETCP не затирается полным STUN.
- RFC5780 EIM/EIF, EIM/ADF, EIM/APDF, ADM/APDM; обычный MATCH; недоступные
альтернативы, ignored CHANGE, DNS, потери, нестабильность и ограничение повторов.
- NAT по-разному обрабатывает тестовый и рабочий порты: резерв помечен STUN,
реальный ETCP его заменяет; тестовый mapped port не попадает в NODEINFO/NCD.
- Смена маршрута без смены IP, refresh, reload, stop, callbacks и утечки.
Общий evidence/time кэша не омолаживается при новом socket или NODEINFO.
- В tests/stream_netns разместить RFC5780-серверы с двумя IP/двумя портами,
сценарий двух uTun, затем добавить третьего. Проверить переключение источника
типа при RTT/jitter/loss; всю сетевую настройку выполнять в отдельных namespace.
Основания: https://www.rfc-editor.org/rfc/rfc5780#section-4.1 (выбор тестового порта
и ограниченность переноса результата), #section-4.3/#section-4.4 (классы).
Приоритет и применение резерва — согласованный проект uTun, не гарантия RFC.

12
doc/tasks.md

@ -4,12 +4,12 @@
## Текущие задачи ## Текущие задачи
[ ] **STUN: объединённый детектор рабочего endpoint** — план и варианты в [ ] **STUN: резервное определение типа NAT по IP/netif** — уточнённый план
`doc/nat_detection.txt`, раздел после rebase 12.10.2026. Текущий STUN измеряет 12.10.2026 в `doc/nat_detection.txt`. Одна группа и отдельный тестовый UDP-порт
другой порт, его результат нельзя переносить в ETCP/NODEINFO. Нужны единый на уникальный IP/netif, общий кэш с generation/TTL. При NO_OBSERVER/NO_HELPER
владелец профиля, STUN через рабочий UDP fd, общая история контактов и отмена применять пригодную оценку STUN с явным source; измеренный ETCP приоритетен.
по socket generation. Дополнительно проверить молчаливое игнорирование CHANGE, mapped адрес тестового сокета не переносить на рабочий. Проверить дубликаты,
повторное использование тестовых портов, давность и смену маршрута без смены IP. переход STUN -> ETCP, различия по портам и жизненный цикл; namespace-стенд.
[ ] **check.sh: изоляция сетевых integration-тестов** — после основного набора [ ] **check.sh: изоляция сетевых integration-тестов** — после основного набора
автоматически запускает check-proxy/burst/load при доступном sudo. Скрипты автоматически запускает check-proxy/burst/load при доступном sudo. Скрипты

Loading…
Cancel
Save