Complete NAT wire lifecycle scheduling and diagnostic contracts

This commit is contained in:
evgeny committed 2026-10-24 16:53:10 +02:00
1 parent 857a4cee2f
commit bb13824ad8
2 files changed
+46 -4

No files matched your search

+37
View File
@@ -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 детектора нельзя.
+9 -4
View File
@@ -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:порт) до передачи пакета транспорту.