diff --git a/doc/nat_detection.txt b/doc/nat_detection.txt index a61013a5..857b08d3 100644 --- a/doc/nat_detection.txt +++ b/doc/nat_detection.txt @@ -86,6 +86,16 @@ facet не превращается в ложный STRICT. Потери, оши Свойства разных источников не объединяются в один ETCP-профиль. Смена адреса отменяет старый раунд, сбрасывает профиль и назначает скорую проверку. Таймеры используют monotonic timebase. +После таймаута NCD перепроверка назначается только для реально отправленных native UDP INIT +к OPEN endpoint из текущего подписанного NODEINFO. CONTACT допускает такой повод после +исчерпания цикла CM вместе с reverse, а UNKNOWN/приватный адрес и SOCKS5 его не дают. +Активный раунд не перезапускается; повторные ошибки объединяются, минимум пять минут +между такими перепроверками одного рабочего сокета. Последний успех сохраняется. +Если выбранная группа ещё доставляет управление пиру, ему передаётся подписанный +зашифрованный RECHECK размером 23 байта (команда/версия/socket ID/endpoint). +Пир проверяет членство отправителя и совпадение endpoint со своим текущим сокетом; +тот же лимит действует на удалённые запросы. ID раунда и время в NODEINFO не возвращаются. + TCP и прокси ------------- @@ -114,6 +124,7 @@ group/generation/round/token проверяются до обработки. Ч На смене адреса, закрытии сокета, reset/DELETE транспорта и остановке ядра отменяются собственные раунды и связанные helper jobs. Поздние ответы не применяются к новому socket generation даже при повторном ID и IP:port. +Между попытками разных пар локальный статус cycling отличает паузу от завершения измерения. Удаление выбранной группы отменяет её раунды, jobs и наблюдения до закрытия router-каналов; другие группы и последний успешный профиль сохраняются. Детектор останавливается до разборки групп, сокетов и соединений. @@ -150,7 +161,7 @@ test_nat_detection: разные socket ID, два рабочих UDP endpoint, замена помощника с тем же IP, повтор по старому контакту, подпись/SQLite профиля, закрытие S посреди раунда и повторный ID/порт. Утечки/таймеры/сокеты проверяются. test_sock_match: независимость политики от фактов, UNKNOWN, CONTACT, давность, -частные адреса и разрешённая попытка hairpin. +частные адреса и разрешённая попытка hairpin; профили не протухают по времени. tests/stream_netns --nat-only: 16 настоящих uTun с 10 NAT, проверка всех UDP/TCP профилей и точного собственного внешнего адреса. --nat-check включает эту фазу diff --git a/src/routing_layer/nat_detection.c b/src/routing_layer/nat_detection.c index 303a922b..1bbddbe4 100644 --- a/src/routing_layer/nat_detection.c +++ b/src/routing_layer/nat_detection.c @@ -1055,7 +1055,9 @@ static void receive_control(struct ETCP_CONN *from, struct ll_entry *entry) { struct ETCP_SOCKET *socket = find_socket(detector, request.socket_id, 0); struct sockaddr_storage address = {0}; if (request.cmd != ETCP_RT_ID_NAT_DETECTION || request.command != NAT_RECHECK || request.version != NAT_WIRE_VERSION || - !socket || socket->is_tcp || socket->probe_only || socket->socks_udp || route_ping_addr_decode(&address, request.address) || + !socket || socket->is_tcp || socket->probe_only || socket->socks_udp || + socket->type == CFG_SERVER_TYPE_LOCAL || socket->type == CFG_SERVER_TYPE_PRIVATE || + route_ping_addr_decode(request.address, &address) || (!route_ping_addr_equal(&address, &socket->local_addr, 1) && !route_ping_addr_equal(&address, &socket->nat_addr, 1))) { DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT failure recheck rejected group=%016llx peer=%016llx socket=%u: stale/invalid endpoint", (unsigned long long)group_id, (unsigned long long)sender, request.socket_id); return;