Browse Source

Document grouped control, isolated helper ports and ingress correlation

stream-multiview
evgeny 1 week ago
parent
commit
2ba011d3fd
  1. 47
      doc/nat_detection.txt
  2. 9
      src/routing_layer/nat_detection.c

47
doc/nat_detection.txt

@ -23,23 +23,29 @@ DEPENDENT означает различие mapping на испытанных н
UDP-раунд UDP-раунд
--------- ---------
1. Владелец A выбирает живого наблюдателя B с доступным native UDP endpoint. 1. Владелец A рассматривает узлы всех активных UTUN/CHAT-групп и выбирает одну группу
с маршрутами к наблюдателю B и отдельному помощнику C. Следующие хопы управления
должны быть READY. Прямые ETCP/UDP-линки к B/C не обязательны; B нужен доступный UDP endpoint.
Через проверяемый сокет S выполняет OBSERVE. Ответ содержит фактический Через проверяемый сокет S выполняет OBSERVE. Ответ содержит фактический
source IP:port, наблюдаемый B, и исходный тег S/generation/round. source IP:port, наблюдаемый B, и исходный тег S/generation/round/group.
2. Через уже установленный ETCP к B запрашивает поиск помощника C. 2. A выбирает C по подписанному NODEINFO выбранной группы. Его рабочий UDP-сокет
B выбирает C из своих работающих UDP-пиров и возвращает его ключ и endpoint. задаёт интерфейс/семейство; C использует два отдельных probe_only порта,
Собственный подтверждённый NAT-профиль B/C не требуется: иначе bootstrap чтобы помощь другому узлу не открывала фильтр его собственного рабочего endpoint.
зависел бы от уже завершённой детекции. Пригодность подтверждают реальные пробы. C может находиться за NAT, независимо от политики PUBLIC/NAT и собственного профиля.
3. Если внешний IP C совпадает с IP B, A исключает C и командует B искать 3. Управление RUN/RESULT идёт A -> B -> C через router в одной группе с подписью
следующего помощника. Совпадающие Node ID и разные порты одного IP не дают и шифрованием. C сначала отправляет ADDRESS_CHECK с primary-порта к endpoint A,
реально наблюдавшемуся B. Аутентичный ingress на S до исходящего контакта подтверждает OPEN.
PONG возвращает наблюдаемый внешний endpoint C. При отсутствии PONG C узнаёт mapping
своего primary-порта через B, после чего выполняется контролируемый PRE из трёх проб.
4. Если внешний IP C совпадает с IP B или S ранее контактировал с C, A пробует
другие пары и группы. Совпадающие Node ID и разные порты одного IP не дают
независимого IP-наблюдения. При отсутствии второго IP результат неполный. независимого IP-наблюдения. При отсутствии второго IP результат неполный.
4. Для входящего испытания выбирается C, с IP которого S ранее не контактировал. При выборе пары сначала сохраняется возможность свежего помощника; ранее контактировавшая
Все команды C идут A -> B -> C. До первого испытания A не шлёт UDP к C. пара используется для mapping после исчерпания свежих. Отчёт о PONG не заменяет ingress на S.
C отправляет три аутентифицированные ADDRESS_CHECK к endpoint из наблюдения B. 5. После первого испытания S выполняет OBSERVE к primary C. При различии mapping
A регистрирует фактический ingress на S; один отчёт о PONG не заменяет ingress. с B уже известен DEPENDENT. Иначе C отдельно измеряет внешний endpoint второго порта
5. После завершения первого испытания S выполняет OBSERVE к основному порту C, через A; если фильтр A мешает — через B. S выполняет OBSERVE к этому endpoint.
затем к другому UDP-порту того же помощника. Вспомогательный порт принадлежит Оба порта C скрыты из NODEINFO и исключены из NCD. Проверяемый S не меняется.
наблюдателю, скрыт из NODEINFO и исключён из NCD. Проверяемый S не меняется.
6. Если первый ingress отсутствовал, C здоров и mapping к C совпал с mapping к B, 6. Если первый ingress отсутствовал, C здоров и mapping к C совпал с mapping к B,
после исходящего контакта выполняется второе входящее испытание от того же C. после исходящего контакта выполняется второе входящее испытание от того же C.
Контролируемый переход до/после контакта даёт CONTACT_REQUIRED. Контролируемый переход до/после контакта даёт CONTACT_REQUIRED.
@ -100,14 +106,17 @@ listener удалённого клиента. SOCKS5 UDP не классифиц
как контекст другого типа. Произвольный выбор первого IPv4/TCP-сокета запрещён. как контекст другого типа. Произвольный выбор первого IPv4/TCP-сокета запрещён.
Broker принимает RUN только для записанного им UDP-наблюдения данного владельца. Broker принимает RUN только для записанного им UDP-наблюдения данного владельца.
Размер wire, версия, enum, границы списка исключений и ненулевые поколения/раунды Участники и ключи берутся из подписанного реестра выбранной группы. SOURCE читается
проверяются до обработки. Числа новых сообщений — BE, IP — сетевые байты. из проверенного router-заголовка, не из ETCP next hop. Управление занимает 136 байт,
owner_key и helper_key имеют разные поля и никогда не меняют значение по роли. не содержит списков исключений и копий ключей. Размер, версия, enum и ненулевые
group/generation/round/token проверяются до обработки. Числа BE, IP — сетевые байты.
На смене адреса, закрытии сокета, reset/DELETE транспорта и остановке ядра На смене адреса, закрытии сокета, reset/DELETE транспорта и остановке ядра
отменяются собственные раунды и связанные helper jobs. Поздние ответы не отменяются собственные раунды и связанные helper jobs. Поздние ответы не
применяются к новому socket generation даже при повторном ID и IP:port. применяются к новому socket generation даже при повторном ID и IP:port.
Детектор останавливается до разборки групп, сокетов и соединений. Удаление выбранной группы отменяет её раунды, jobs и наблюдения до закрытия router-каналов;
другие группы и последний успешный профиль сохраняются. Детектор останавливается
до разборки групп, сокетов и соединений.
Публикация и NCD Публикация и NCD
--------------- ---------------

9
src/routing_layer/nat_detection.c

@ -1,6 +1,6 @@
/* NAT-детектор владельца endpoint. Один раунд на рабочий сокет: /* Владелец выбирает пару из всех групп; управление A->B->C идёт через router.
* S->B observation, B->C ingress(S), S->C/C-alt observations, S->B repeat. * S->B observation, C->S controlled ingress, S->C/C-alt observations, S->B repeat.
* Команды к C проходят через B: контроль не открывает фильтр S->C. */ * Два отдельных порта C и короткий приоритет холодного owner сохраняют независимость ingress. */
#include "nat_detection.h" #include "nat_detection.h"
#include <stdio.h> #include <stdio.h>
@ -735,6 +735,9 @@ static void helper_remove(struct nat_probe *probe) {
static void helper_finish(struct nat_probe *probe, uint8_t reason) { static void helper_finish(struct nat_probe *probe, uint8_t reason) {
probe->message.command = NAT_RESULT; probe->message.reason = reason; probe->message.command = NAT_RESULT; probe->message.reason = reason;
if (reason) DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT helper failed group=%016llx owner=%016llx round=%016llx step=%u reason=%s",
(unsigned long long)probe->group_id, (unsigned long long)read64(probe->message.owner),
(unsigned long long)read64(probe->message.round), probe->message.step, nat_check_reason_name(reason));
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT helper done owner=%016llx round=%016llx step=%u sent=%u received=%u errors=%u reason=%s", DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT helper done owner=%016llx round=%016llx step=%u sent=%u received=%u errors=%u reason=%s",
(unsigned long long)read64(probe->message.owner), (unsigned long long)read64(probe->message.round), (unsigned long long)read64(probe->message.owner), (unsigned long long)read64(probe->message.round),
probe->message.step, probe->message.sent, probe->message.received, probe->message.errors, nat_check_reason_name(reason)); probe->message.step, probe->message.sent, probe->message.received, probe->message.errors, nat_check_reason_name(reason));

Loading…
Cancel
Save