|
|
|
|
@ -144,78 +144,143 @@ tests/stream_netns --nat-only: 16 настоящих uTun с 10 NAT, прове
|
|
|
|
|
профилей и точного собственного внешнего адреса. --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. |
|
|
|
|
Резервное определение типа NAT через STUN: план 2026-10-12 |
|
|
|
|
------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
Уточнение пользователя: STUN группирует рабочие сокеты по одинаковым IP/netif, |
|
|
|
|
создаёт аналогичный UDP-сокет с другим портом и определяет тип NAT для группы. |
|
|
|
|
Когда ETCP не может выполнить проверку из-за нехватки узлов, используется STUN. |
|
|
|
|
Это заменяет прежнее предложение использовать STUN непосредственно на ETCP fd. |
|
|
|
|
Далее описан план; работающая резервная интеграция ещё не реализована. |
|
|
|
|
|
|
|
|
|
1. Реестр уникальных путей |
|
|
|
|
|
|
|
|
|
Ключ группы — (address family, фактический local IP, netif_index), без порта, |
|
|
|
|
имени и socket ID. Несколько рабочих портов одного IP/netif дают одну группу. |
|
|
|
|
Одинаковый IP на разных netif и разные IP одного netif — разные группы. |
|
|
|
|
netif=0 сохраняет смысл автоматической маршрутизации, не приравнивается |
|
|
|
|
произвольно к явно привязанному интерфейсу. Wildcard не становится отдельным IP: |
|
|
|
|
сначала нужен фактический адрес пути. Неопределённый путь получает UNKNOWN. |
|
|
|
|
|
|
|
|
|
Сканировать native UDP, исключать probe_only, SOCKS5 и only_local. TCP listener |
|
|
|
|
сохраняет отдельную проверку STCP: UDP-результат ему не присваивается. |
|
|
|
|
Начать с IPv4, уже поддержанного stun_nat; IPv6 требует отдельного этапа: |
|
|
|
|
XOR-MAPPED IPv6, IPv6 server/config/DNS и scope/interface, без переноса IPv4-фактов. |
|
|
|
|
|
|
|
|
|
Выбрать представителя группы, скопировать фактические bind IP/device/mark/FIB. |
|
|
|
|
Порты исходных сокетов не копировать; проба владеет собственным fd/reader. |
|
|
|
|
Разные mark/FIB/device внутри одного ключа означают неоднозначный путь: |
|
|
|
|
группа получает UNKNOWN/incompatible_route_policy с логом, а не случайный |
|
|
|
|
результат первого сокета. Ключ IP/netif при этом не усложняется. |
|
|
|
|
|
|
|
|
|
2. Измерение и кэш STUN |
|
|
|
|
|
|
|
|
|
Одна активная проба и один результат на группу, независимо от числа её сокетов. |
|
|
|
|
Тестовый порт случайный, отличается от рабочих портов. В пределах жизни ядра |
|
|
|
|
не переиспользовать ранее измеренные порты на этом IP/netif; при исчерпании |
|
|
|
|
не выполнять заведомо загрязнённое входящее испытание, вернуть явную причину. |
|
|
|
|
Самостоятельно закрывать только пробный fd, отменять его DNS и таймеры. |
|
|
|
|
|
|
|
|
|
STUN запускается при появлении группы, при наличии enabled и настроенных серверов. |
|
|
|
|
Разные имена серверов с одинаковым IP не считаются независимыми наблюдателями. |
|
|
|
|
На чистом тестовом порту сначала проверять filtering, потом mapping и стабильность |
|
|
|
|
исходного наблюдения. Переносить в кэш только завершённые пригодные свойства; |
|
|
|
|
потери, ошибки, отсутствие RFC5780 и сомнительный CHANGE дают UNKNOWN/причину. |
|
|
|
|
|
|
|
|
|
В результате хранить ключ группы, её generation, случайный evidence ID, |
|
|
|
|
test IP:port, фактические серверы, mapped адреса, mapping/filtering, причины, |
|
|
|
|
время измерения monotonic и Unix microseconds. TTL=300с, refresh=180с, |
|
|
|
|
повтор неполной проверки через 30с; темп новых транзакций остаётся ограниченным. |
|
|
|
|
Применение готового кэша к новому сокету не обновляет время измерения. |
|
|
|
|
|
|
|
|
|
3. Выбор результата NAT_DETECTION |
|
|
|
|
|
|
|
|
|
NAT_DETECTION остаётся единственным владельцем эффективного socket profile, |
|
|
|
|
nat_addr и публикации NODEINFO. STUN предоставляет кэш по ключу группы, |
|
|
|
|
уведомляет о завершении/инвалидации; сам не меняет профили рабочих сокетов. |
|
|
|
|
Реестр групп не держит указателей на рабочие сокеты: потребитель проверяет |
|
|
|
|
собственные socket generation и актуальную принадлежность группе перед применением. |
|
|
|
|
|
|
|
|
|
Хранить отдельно собственный результат ETCP и выбранный эффективный профиль. |
|
|
|
|
Добавить profile source: NONE / ETCP / STUN, в том числе в подпись, wire, |
|
|
|
|
SQLite и диагностические API. STUN означает резервную оценку по интерфейсу, |
|
|
|
|
ETCP — измерение рабочего endpoint. Подписывает публикацию только сам узел. |
|
|
|
|
|
|
|
|
|
Приоритет: действующий измеренный ETCP -> пригодный STUN при невозможности |
|
|
|
|
ETCP из-за отсутствия наблюдателя/независимого помощника -> UNKNOWN. |
|
|
|
|
Для STUN использовать реальные NO_OBSERVER/NO_HELPER, не общее число узлов: |
|
|
|
|
третий узел может быть offline, несовместимым или иметь тот же IP наблюдателя. |
|
|
|
|
После исчерпания замены таких помощников разрешать резервное применение. |
|
|
|
|
Пока STUN не готов, оставить UNKNOWN или ещё действующий профиль ETCP. |
|
|
|
|
|
|
|
|
|
Частичный, но измеренный ETCP не заменять целиком STUN: DEPENDENT с неизвестным |
|
|
|
|
ingress является полезным результатом. В первой версии не смешивать facets |
|
|
|
|
разных источников. Неудача нового раунда не стирает ещё действующий ETCP. |
|
|
|
|
Появление подходящего помощника ускоряет повтор ETCP; его успешный результат |
|
|
|
|
заменяет резервный без ожидания TTL. Не сбрасывать ETCP при завершении STUN. |
|
|
|
|
|
|
|
|
|
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. |
|
|
|
|
|