diff --git a/doc/nat_detection.txt b/doc/nat_detection.txt index fdaf4abf..8fab5702 100644 --- a/doc/nat_detection.txt +++ b/doc/nat_detection.txt @@ -107,3 +107,40 @@ IP совпали — трансляция IP не обнаружена; отл публичному подключению и сохраняется при последующих совпавших наблюдениях IP. Через SOCKS внешний IP прокси не записывается как собственный адрес. + +Управляющий обмен и ресурсы +-------------------------- + +Команды идут через сервис NAT_DETECTION ETCP-router с подписью и шифрованием. +Используются узлы группы с рабочим маршрутом через READY-соседа; это не требует +прямого UDP-соединения A с C. CHAT-допуск требует полной неудалённой записи участника. +Источник и группа берутся из проверенного заголовка router, а не из next hop. + +Версия управляющего формата — 4. Основное сообщение занимает 117 байт: +10 однобайтовых полей команды/сокетов/этапа/результата, шесть uint64 +(owner, generation, round, token, observer, helper), uint16 timeout_ms +и три адреса по 19 байт (target, primary, observer_address). +RECHECK занимает 23 байта: cmd, command, version, socket_id и адрес 19 байт. +Многобайтовые числа кодируются вручную в big-endian; адреса — route_ping_addr_encode. +Это размеры сообщения после служебного заголовка router. Приём требует точного +размера; старые generation/round/token и чужие делегирования результата отклоняются. + +Детектор работает с шагом 100 мс. Помощник отправляет до трёх проб на этап; +таймаут одной пробы — не меньше секунды и не меньше четырёх RTT наблюдателя. +Общий бюджет обхода — 30 секунд; незавершённый обход может продолжиться после паузы. +Полный результат перепроверяется через 30 минут, неполный — через 30 секунд. +Повтор по неудаче подключения ограничен одним запросом за пять минут на endpoint. +Сохранённый успешный ETCP-профиль не истекает по таймеру; изменение endpoint его сбрасывает. + +История исходящих хранит до 256 IP для каждого локального endpoint (IP:порт). +Она сохраняется в SQLite. Переполнение или ошибка загрузки/записи помечают историю +неполной: UNKNOWN сохраняется до достоверного измерения, OPEN по незнакомому входу +с неполной историей не подтверждается. Кеш наблюдений ограничен 128 записями, +одновременно выполняется не более 64 задач помощи. + +Детектор владеет таймерами, подписками и изолированными probe_only UDP-сокетами. +Эти сокеты не публикуются как рабочие адреса. Их отдельное удаление снимает ссылку +в состоянии родителя, отменяет зависимые пробы и допускает обычный последующий teardown. +Ошибка регистрации любой подписки или начального таймера отменяет весь запуск. +Ядро сохраняет контекст в instance->nat_det; останавливает его до ETCP/router +и обнуляет поле после destroy. Уничтожать ядро из callback детектора нельзя. diff --git a/src/routing_layer/nat_detection.h b/src/routing_layer/nat_detection.h index 3e51e073..98002b96 100644 --- a/src/routing_layer/nat_detection.h +++ b/src/routing_layer/nat_detection.h @@ -49,7 +49,7 @@ enum nat_check_reason { NAT_REASON_ADDRESS_CHANGED, /* Наблюдаемый адрес изменился; прежний профиль сброшен. */ NAT_REASON_CONTACT_HISTORY, /* IP уже был знаком или история неполна: вход не подтверждён как незнакомый. */ NAT_REASON_PROXY, /* Сокет работает через SOCKS: его собственный NAT не измеряется. */ - NAT_REASON_NO_LISTENER, /* Нет публичного TCP-listener для проверки входящих. */ + NAT_REASON_NO_LISTENER, /* Резерв причины в управляющем протоколе; активных TCP-проб сейчас нет. */ NAT_REASON_CANCELLED, /* Проверка отменена. */ NAT_REASON_INVALID_OBSERVATION, /* Наблюдение непригодно, в том числе из-за непубличного source IP. */ NAT_REASON_DEPENDENT_MAPPING, /* Определён strict, входящая доступность осталась неизвестной. */ @@ -74,10 +74,14 @@ struct nat_check_status { }; /* Создать детектор для instance с готовым маршрутизатором и группами; автоматические проверки включены. - * Возвращает контекст или NULL при ошибке; instance должен существовать до destroy(). */ + * Возвращает контекст или NULL при ошибке, снимая частично установленные обработчики. + * Ядро сохраняет результат в instance->nat_det до обработки событий: управляющий RX использует это поле. + * instance должен существовать до destroy(); повторное создание при занятом router-binding запрещено. */ struct NAT_DETECTION *nat_detection_create(struct UTUN_INSTANCE *instance); -/* Остановить проверки, снять обработчики и освободить detector; NULL допустим. Ядро и его рабочие сокеты не освобождаются. */ +/* Остановить проверки, снять обработчики и освободить detector; NULL допустим. + * Вызывать до teardown ETCP/router и вне callbacks детектора; затем обнулить instance->nat_det. + * Ядро и рабочие сокеты не освобождаются; внутренние probe_only-сокеты принадлежат детектору. */ void nat_detection_destroy(struct NAT_DETECTION *detector); /* Сообщить detector об изменении адресов/готовности групп; пересмотр кандидатов отложен и объединяет повторные вызовы. */ @@ -109,7 +113,8 @@ void nat_detection_cancel_for_conn(struct NAT_DETECTION *detector, struct ETCP_C * reverse_done != 0 — обратное подключение тоже исчерпано; только тогда перепроверяется filtered (CONTACT). */ void nat_detection_connection_failed(struct NAT_DETECTION *detector, struct ETCP_CONN *connection, int reverse_done); -/* Удалить состояние socket и отменить связанные задачи; вызвать до освобождения самого сокета. */ +/* Удалить состояние socket и отменить связанные задачи; вызвать до освобождения самого сокета. + * Для внутреннего probe_only также снимает ссылку владельца: последующий destroy не удалит сокет повторно. */ void nat_detection_socket_removed(struct NAT_DETECTION *detector, struct ETCP_SOCKET *socket); /* Учесть исходящую отправку с socket на destination (IP:порт) до передачи пакета транспорту.