Files
utun2/nat.txt
T
Evgeny b466d14fe4 Добавлено поле interface_addr в ETCP_SOCKET и interface_ip/port в BGP_NAT_CHECK_REQ
- platform_compat: get_interface_ip_by_index() для получения IP по ifindex
- ETCP_SOCKET: interface_addr заполняется из конфига/interface/default route
- BGP_NAT_CHECK_REQ: добавлены interface_ip/interface_port (network byte order)
- route_bgp_send_nat_check_req: отправляет interface_addr линка
- route_bgp_handle_nat_check_req: принимает interface данные в sockaddr-заглушку
2026-04-22 18:16:49 +03:00

220 lines
11 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Диаграмма вызовов функций при определении типа NAT (NAT detection)
=====================================================================
=== ИНИЦИАЛИЗАЦИЯ BGP ===
route_bgp_init(instance)
└── etcp_set_new_conn_cbk(instance, route_bgp_etcp_conn_cbk, NULL)
└── При создании нового ETCP_CONN:
route_bgp_etcp_conn_cbk(conn, arg)
├── etcp_conn_set_up_cbk(conn, route_bgp_on_conn_up, bgp)
└── etcp_conn_set_down_cbk(conn, route_bgp_on_conn_down, bgp)
=== УСТАНОВКА СОЕДИНЕНИЯ (сервер получает INIT_REQUEST) ===
etcp_connections_read_callback_socket(sock, arg)
└── Получает ETCP_INIT_REQUEST
├── etcp_connection_create(instance, name) [если новый peer]
│ └── Вызывает instance->etcp_new_conn_cbk [route_bgp_etcp_conn_cbk]
├── etcp_link_new(etcp, e_sock, remote_addr, is_server=1)
├── Отправляет ETCP_INIT_RESPONSE (с NAT info)
├── link->initialized = 1
└── etcp_conn_ready(link->etcp)
└── conn->ready_cbk
└── etcp_on_up(etcp)
└── etcp->up_cbk = route_bgp_on_conn_up(etcp, bgp)
=== УСТАНОВКА СОЕДИНЕНИЯ (клиент получает INIT_RESPONSE) ===
etcp_connections_read_callback_socket(sock, arg)
└── Получает ETCP_INIT_RESPONSE
├── Сохраняет NAT address: link->nat_ip, link->nat_port
├── link->initialized = 1
└── etcp_conn_ready(link->etcp)
└── etcp_on_up(etcp)
└── etcp->up_cbk = route_bgp_on_conn_up(etcp, bgp)
=== ЗАПУСК ПРОВЕРКИ NAT (при поднятии соединения) ===
route_bgp_on_conn_up(etcp, arg)
└── route_bgp_new_conn(conn)
├── route_bgp_add_to_senders(bgp, conn)
└── Сканирует ВСЕ линки ВСЕХ соединений:
if (link->initialized && link->conn && link->nat_check_status < NAT_CHECK_IN_PROGRESS)
└── route_bgp_start_link_nat_check(bgp, link)
├── if (nat_check_status == IN_PROGRESS) return
├── route_bgp_find_third_node(bgp, exclude=link->etcp)
│ └── Ищет другой ETCP_CONN в senders_list
├── Определяет target_ip/target_port:
│ ├── Если link->nat_ip != 0: использует nat_ip/nat_port
│ └── Иначе: использует link->remote_addr
├── Проверяет is_local_subnet(target_ip) [если запрещено - skip]
├── route_bgp_extract_nat_addr(conn, &nat_ip, &nat_port)
│ └── Ищет первый линк с nat_ip != 0
├── Создает nat_check_arg { link, nat_ip, nat_port }
└── route_ping_send_req_addr(bgp, third_conn, target_ip, target_port,
count=3, interval=500ms, timeout=1000ms,
wait_timeout=5000ms,
cb=nat_link_check_cb, arg=nat_check_arg,
pubkey=peer_pubkey)
=== ОТПРАВКА ЗАПРОСА НА ПИНГ (через third node) ===
route_ping_send_req_addr(bgp, to_conn, target_ip, target_port, ...)
├── Создает BGP_PING_REQUEST { cmd, subcmd=PING_REQ, request_id, count, interval, timeout, target_ipv4, target_port, pubkey }
├── etcp_send(to_conn, entry) [отправляет запрос third node]
├── Создает route_ping_pending { request_id, callback=nat_link_check_cb, arg, timeout_timer }
└── Добавляет в bgp->ping_pending
=== ОБРАБОТКА PING_REQ (на third node) ===
route_bgp_receive_cbk(data, len, from_conn, bgp)
└── ROUTE_SUBCMD_PING_REQ
└── route_ping_handle_req(bgp, from_conn, data, len)
├── Создает route_ping_series_ctx { reply_conn, request_id, target_addr, pubkey, local_sock, count_total }
├── Находит первый IPv4 ETCP_SOCKET -> local_sock
└── etcp_send_ping_to_socket(instance, local_sock, pubkey, &target_addr,
timeout_ms, route_ping_single_cb, ctx, NULL, 0)
└── Отправляет ETCP пинг на target_addr
=== ОТВЕТ НА ПИНГ (целевой узел) ===
etcp_connections_read_callback_socket()
└── Получает ETCP пинг -> отправляет pong
=== ПОЛУЧЕНИЕ ОТВЕТА НА ПИНГ (third node) ===
route_ping_single_cb(success, rtt, arg, nonce, resp_data, resp_data_len)
├── Обновляет статистику: count_sent++, count_ok++, sum_rtt += rtt
├── Если count_sent < count_total:
│ └── etcp_send_ping_to_socket(...) [следующий пинг]
└── Иначе:
└── route_ping_series_finish(ctx)
├── Вычисляет avg_rtt
└── Создает BGP_PING_RESPONSE { cmd, subcmd=PING_RESP, request_id, count_sent, count_ok, avg_rtt }
└── etcp_send(reply_conn, entry) [отправляет результат инициатору]
=== ПОЛУЧЕНИЕ PING_RESP (на инициаторе) ===
route_bgp_receive_cbk(data, len, from_conn, bgp)
└── ROUTE_SUBCMD_PING_RESP
└── route_ping_handle_resp(bgp, from_conn, data, len)
├── Ищет route_ping_pending по request_id
├── Отменяет timeout_timer
└── Вызывает callback: nat_link_check_cb(success, avg_rtt, count_sent, count_ok, arg)
=== CALLBACK ПРОВЕРКИ NAT ===
nat_link_check_cb(success, avg_rtt, count_sent, count_ok, arg)
├── Определяет nat_type = success ? NAT_TYPE_OPEN : NAT_TYPE_RESTRICTED
├── link->nat_type = nat_type
├── link->nat_check_status = success ? NAT_CHECK_OPEN : NAT_CHECK_RESTRICTED
└── route_bgp_send_nat_info(link->etcp, socket_id, nat_ip, nat_port, nat_type)
├── Создает BGP_NAT_INFO { cmd, subcmd=NAT_INFO, socket_id, nat_ip[4], nat_port, nat_type }
└── etcp_send(conn, entry) [отправляет результат клиенту]
=== ПРИЕМ NAT_INFO (на клиенте) ===
route_bgp_receive_cbk(data, len, from_conn, bgp)
└── ROUTE_SUBCMD_NAT_INFO
└── route_bgp_handle_nat_info(bgp, from_conn, data, len)
├── Ищет линки по remote_socket_id
├── Устанавливает link->nat_type = info->nat_type
└── Логирует результат NAT detection
=== ЗАПРОС НА ПРОВЕРКУ NAT (NAT_CHECK_REQ - новый механизм) ===
route_bgp_send_nat_check_req(conn, socket_id)
├── Создает BGP_NAT_CHECK_REQ { cmd, subcmd=NAT_CHECK_REQ, socket_id, interface_ip, interface_port }
│ ├── Ищет линк с remote_socket_id == socket_id
│ └── Берет interface_addr из линка -> interface_ip/interface_port
└── etcp_send(conn, entry)
route_bgp_handle_nat_check_req(bgp, from_conn, data, len)
├── Принимает BGP_NAT_CHECK_REQ
├── Сохраняет interface_ip/interface_port в struct sockaddr_storage dummy
├── Ищет линк с remote_socket_id == req->socket_id
└── Если линк найден и не в процессе проверки:
└── route_bgp_start_link_nat_check(bgp, target_link)
[далее по стандартному flow]
=== СВЯЗЬ СТРУКТУР ===
struct ETCP_SOCKET
├── local_addr [адрес бинда из конфига]
├── interface_addr [IP интерфейса + порт: интерфейс/default route/конфиг]
└── ...
struct ETCP_LINK
├── remote_addr [адрес удаленного узла]
├── nat_ip [NAT IP, полученный из INIT_RESPONSE]
├── nat_port [NAT port, полученный из INIT_RESPONSE]
├── nat_type [OPEN/RESTRICTED, результат проверки]
├── nat_check_status [NONE/WAITING/IN_PROGRESS/OPEN/RESTRICTED]
├── initialized [0/1, флаг завершения handshake]
└── ...
struct ETCP_CONN
├── links [список ETCP_LINK]
├── up_cbk [route_bgp_on_conn_up]
├── down_cbk [route_bgp_on_conn_down]
├── ready_cbk [вызывается при etcp_conn_ready]
├── initialized [0/1, флаг готовности]
├── links_up [0/1, есть ли активные линки]
└── ...
=== СТАТУСЫ NAT CHECK ===
NAT_CHECK_NONE = 0 [не проверялся]
NAT_CHECK_WAITING = 1 [ожидает]
NAT_CHECK_IN_PROGRESS = 2 [проверка запущена]
NAT_CHECK_OPEN = 3 [результат: OPEN]
NAT_CHECK_RESTRICTED = 4 [результат: RESTRICTED]
NAT_TYPE_UNKNOWN = 0
NAT_TYPE_OPEN = 1
NAT_TYPE_RESTRICTED = 2
NAT_VERIFIED_UNKNOWN = 4
NAT_VERIFIED_OPEN = 5
NAT_VERIFIED_RESTRICTED = 6
NAT_VERIFIED_DIRECT = 7
=== СООБЩЕНИЯ ПРОТОКОЛА ===
ETCP_INIT_REQUEST (0x02) [клиент -> сервер]
ETCP_INIT_RESPONSE (0x03) [сервер -> клиент, включает NAT info]
ETCP_INIT_REQUEST_NOINIT (0x04)
ETCP_INIT_RESPONSE_NOINIT (0x05)
ETCP_PING (0x06)
ETCP_PONG (0x07)
ROUTE_SUBCMD_NODEINFO (0x04)
ROUTE_SUBCMD_REQUEST_TABLE (0x05)
ROUTE_SUBCMD_WITHDRAW (0x06)
ROUTE_SUBCMD_PING_REQ (0x07)
ROUTE_SUBCMD_PING_RESP (0x08)
ROUTE_SUBCMD_NAT_INFO (0x09)
ROUTE_SUBCMD_NAT_CHECK_REQ (0x0A)
=== ПОЛНЫЙ FLOW (одна строка) ===
Handshake: etcp_connections_read_callback_socket -> INIT_REQUEST/RESPONSE -> link->initialized=1 -> etcp_conn_ready -> etcp_on_up -> route_bgp_on_conn_up -> route_bgp_new_conn -> route_bgp_start_link_nat_check -> route_ping_send_req_addr -> (через ETCP) -> route_ping_handle_req -> etcp_send_ping_to_socket -> (UDP) -> route_ping_single_cb -> route_ping_series_finish -> route_ping_handle_resp -> nat_link_check_cb -> route_bgp_send_nat_info -> route_bgp_handle_nat_info
NAT_CHECK_REQ flow: route_bgp_send_nat_check_req -> BGP_NAT_CHECK_REQ -> route_bgp_handle_nat_check_req -> route_bgp_start_link_nat_check -> [стандартный ping flow]