diff --git a/doc/nat_detection.txt b/doc/nat_detection.txt index ce97051d..a7190846 100644 --- a/doc/nat_detection.txt +++ b/doc/nat_detection.txt @@ -1,14 +1,17 @@ Детектор свойств endpoint ======================== -Владелец рабочего сокета единственный вычисляет и публикует его профиль. +Владелец рабочего сокета единственный выбирает и публикует его профиль. Помощники возвращают наблюдения и выполняют прямые испытания. Профиль относится к протоколу, семейству, фактическому локальному IP:port и поколению сокета. PUBLIC/NAT/PRIVATE/LOCAL — политика конфигурации, а не результат измерения. +source=ETCP означает измерение рабочего endpoint; source=STUN — резервную оценку +по его IP/netif через другой порт. Измеренный ETCP имеет приоритет до истечения TTL. Модель: src/routing_layer/address_profile.h. mapping: UNKNOWN, UNCHANGED, EIM, DEPENDENT. inbound: UNKNOWN, OPEN, CONTACT_REQUIRED. + source: NONE, ETCP, STUN. evidence_id: случайный 64-битный ID завершённого раунда владельца. checked_at: время измерения владельца, Unix microseconds. generation: случайный 64-битный ID жизненного цикла локального endpoint. @@ -144,14 +147,14 @@ tests/stream_netns --nat-only: 16 настоящих uTun с 10 NAT, прове профилей и точного собственного внешнего адреса. --nat-check включает эту фазу до обычных JOIN/Merkle/BGP/streaming. Главный network namespace не меняется. -Резервное определение типа NAT через STUN: план 2026-10-12 -------------------------------------------------------- +Резервное определение типа NAT через STUN: реализация IPv4 2026-10-12 +------------------------------------------------------------------ Уточнение пользователя: STUN группирует рабочие сокеты по одинаковым IP/netif, создаёт аналогичный UDP-сокет с другим портом и определяет тип NAT для группы. Когда ETCP не может выполнить проверку из-за нехватки узлов, используется STUN. Это заменяет прежнее предложение использовать STUN непосредственно на ETCP fd. -Далее описан план; работающая резервная интеграция ещё не реализована. +Резервная схема реализована для native IPv4 UDP. IPv6 остаётся отдельным этапом. 1. Реестр уникальных путей @@ -197,7 +200,8 @@ tests/stream_netns --nat-only: 16 настоящих uTun с 10 NAT, прове NAT_DETECTION остаётся единственным владельцем эффективного socket profile, nat_addr и публикации NODEINFO. STUN предоставляет кэш по ключу группы, - уведомляет о завершении/инвалидации; сам не меняет профили рабочих сокетов. + NAT_DETECTION проверяет его готовность/инвалидацию раз в секунду; сам STUN + не меняет профили рабочих сокетов. Реестр групп не держит указателей на рабочие сокеты: потребитель проверяет собственные socket generation и актуальную принадлежность группе перед применением. diff --git a/doc/stun_nat.md b/doc/stun_nat.md index e19b5b35..98a35e95 100644 --- a/doc/stun_nat.md +++ b/doc/stun_nat.md @@ -1,11 +1,15 @@ # Независимая STUN-диагностика NAT -Модуль `src/transport_layer/stun_nat.c/h` измеряет NAT на сетевых интерфейсах существующих IPv4 UDP-сокетов. -Для каждого исходного сокета создаётся собственный неблокирующий UDP-сокет с тем же локальным IP, +Модуль `src/transport_layer/stun_nat.c/h` измеряет NAT на уникальных путях существующих IPv4 UDP-сокетов. +Ключ группы — семейство, фактический IP и netif; имена и рабочие порты не участвуют. +Для каждой группы создаётся один собственный неблокирующий UDP-сокет с тем же локальным IP, привязкой к устройству и Linux SO_MARK / FreeBSD FIB. Тестовый порт выбирается случайно из 49152–65535. Модуль сам регистрирует чтение в uasync, принимает STUN и закрывает свой сокет после измерения. -Исходный ETCP fd, его порт, обработчики, NAT-поля, NODEINFO и существующий `nat_detection` не изменяются. -Результат описывает тестовый порт; поведение NAT на порту ETCP может отличаться. +STUN не меняет исходный ETCP fd, его порт и обработчики. NAT_DETECTION использует его +оценку типа при NO_OBSERVER/NO_HELPER, помечает source=STUN и публикует подписанный профиль. +Действующий результат source=ETCP имеет приоритет, включая частичный. Мapped endpoint +тестового порта не переносится в nat_addr или NODEINFO рабочего сокета. +Поведение NAT на рабочем порту может отличаться; source показывает происхождение оценки. ## Конфигурация @@ -29,11 +33,16 @@ IPv6, SOCKS UDP и `only_local` пропускаются с явным стат `stun_nat_get_result(instance, "имя исходного сокета", &result)` копирует локальный снимок: +Имя сначала разрешается в текущий рабочий сокет, затем в группу. API ядра +`stun_nat_get_socket_result(instance, socket, &result)` дополнительно проверяет +текущие IP/netif и параметры маршрутизации. Несколько рабочих портов получают общий снимок. + - `local` — тестовый IP:port; `servers[2]` и `mapped[2]` — реальные серверы и наблюдавшиеся внешние адреса; - `translated`: -1 неизвестно, 0 трансляция не наблюдалась, 1 внешний адрес отличается; - `mapping`: UNKNOWN, MATCH, DEPENDENT, EIM, ADM, APDM; - `filtering`: UNKNOWN, EIF, ADF, APDF; - причины неполного результата, статус, время измерения и обнаруженная поддержка RFC 5780. +- ключ группы, generation, evidence_id, measured_at_us, количество рабочих сокетов и признак refresh. Обычный STUN даёт MATCH при одинаковых адресах и DEPENDENT при разных. MATCH не доказывает EIM, а обычные Binding-ответы не позволяют определить filtering. Первоначальный сервер опрашивается повторно: @@ -68,8 +77,14 @@ transaction ID, границы/выравнивание атрибутов, XOR- Ядро запускает модуль при `utun_core_start`; остановка уничтожает его до сетевых ресурсов и config. Перезагрузка конфига отменяет старые DNS/таймеры и создаёт новый модуль. -Раз в три секунды выполняется локальная сверка исходных сокетов: новые/изменённые проверяются, -исчезнувшие удаляются. Неизменившиеся сокеты повторно не опрашиваются. +Раз в три секунды выполняется локальная сверка групп: новые/изменённые проверяются, +группа удаляется после исчезновения последнего рабочего сокета. Смена имени/представителя +или удаление дубликата не теряет кэш. Несовпадение mark/FIB/device внутри одного ключа +даёт UNKNOWN с причиной incompatible routing policy. +TTL результата 300 секунд, refresh 180 секунд; неполные/неудачные проверки повторяются через 30 секунд. +Во время штатного refresh доступен прежний результат до TTL; его возраст не обновляется. +Использованные тестовые порты не переиспользуются в течение жизни ядра, включая reload STUN. +История портов освобождается только при окончательном destroy ядра. `stun_nat_recheck(instance)` явно повторяет измерение на новых портах, в том числе после смены маршрута без смены IP. Публичные операции выполняются в uasync-потоке экземпляра.