- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll - stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close - utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP), add deferred drain in both Phase J and L - stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39, exchange ed25519_pubkey in both handshake directions - etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb - chat_sync.c: fix lk->conn NULL dereference for TCP links - test_stcp.c: update stcp_server_create/stcp_client_connect callsites - tools/chat_tcp_test: change transport udp→tcp
5.4 KiB
ICMP Proxy (icmp_proxy)
1. Назначение
Проксирование ICMP Echo (ping) между клиентским и exit-узлом по протоколу ETCP. Клиент
принимает ICMP Echo Request с TUN-интерфейса, упаковывает запрос и отправляет через
etcp_route_send на exit. Exit-узел через нативный SOCK_RAW-сокет отправляет ICMP Echo
во внешнюю сеть, сопоставляет ответы по echo_id/echo_seq и возвращает клиенту. Клиент
восстанавливает IP/ICMP Echo Reply и доставляет в TUN.
Один экземпляр контекста на процесс (глобальный g_icmp_ctx). Режим определяется флагом
inst->tcp_proxy_server.enabled. Для тестов предусмотрен loopback-режим без raw-сокета.
2. Как пользоваться
Инициализация
icmp_proxy_init(inst, ua); // exit создаёт SOCK_RAW, клиент — нет
При инициализации регистрируется коллбэк icmp_proxy_recv_cb в etcp_router для сервиса
ETCP_RT_ID_ICMP_PROXY. На exit создаётся один SOCK_RAW(IPPROTO_ICMP) на весь модуль.
Клиент: отправка ping-запроса
icmp_proxy_send_to_exit(inst, exit_node_id, dst_ip, orig_src_ip, echo_id, echo_seq, payload, len);
Вызывается из обработчика TUN-трафика. Запрос упаковывается и отправляется через etcp_route_send.
Ответ приходит асинхронно в icmp_proxy_recv_cb (REPLY), где вызывается icmp_proxy_deliver_reply
для сборки IP/ICMP Echo Reply и записи в TUN.
Тестовый loopback
icmp_proxy_set_test_loopback(inst, 1); // exit отвечает эмуляцией без raw-сокета
В этом режиме exit не отправляет реальный ICMP Echo, а сразу возвращает REPLY клиенту — полезно для тестирования прохождения пакетов через ETCP без необходимости в SOCK_RAW и внешней сети.
Очистка
icmp_proxy_destroy(inst); // закрывает raw-сокет, удаляет pending-запросы, unbind
Нюансы
- Запросы истекают через 5 секунд (
ICMP_TIMEOUT_TB). Таймерexpire_timerзапускается при добавлении первого запроса и перезапускается после каждой очистки. - Неопознанные echo-ответы (не найденные в pending) логируются как
DEBUG_WARNи игнорируются. - Контрольная сумма ICMP пересчитывается на exit (при отправке) и на клиенте (при сборке ответа).
- Поле
orig_src_ipв протоколе нужно для восстановления исходного dst_ip на клиенте.
3. API
Структуры
| Структура | Назначение |
|---|---|
struct icmp_request |
Состояние активного echo-запроса на exit: client_node_id, dst_ip, orig_src_ip, echo_id, echo_seq, payload, время отправки. Связный список. |
struct icmp_proxy_ctx |
Глобальный контекст: is_exit, inst, ua, raw_sock, raw_read_id, список pending, таймаут запросов, флаг test_loopback, таймер очистки. |
Формат пакета
| Смещение | Размер | Поле |
|---|---|---|
| 0 | 1 | svc_id = ETCP_RT_ID_ICMP_PROXY |
| 1 | 1 | subcmd = REQUEST (0x01) / REPLY (0x02) |
| 2 | 8 | sender_node_id |
| 10 | 4 | dst_ip (IP цели для ping) |
| 14 | 4 | orig_src_ip (IP исходного отправителя для обратной доставки) |
| 18 | 2 | echo_id (icmp_id) |
| 20 | 2 | echo_seq (icmp_seq) |
| 22 | N | payload (данные ICMP echo) |
Функции
| Функция | Назначение |
|---|---|
icmp_proxy_init(inst, ua) |
Выделяет контекст, определяет is_exit, на exit создаёт SOCK_RAW и регистрирует его в uasync. Регистрирует коллбэк в etcp_router. |
icmp_proxy_destroy(inst) |
Закрывает raw-сокет, отменяет таймер, освобождает pending, отвязывает коллбэк, освобождает память. |
icmp_proxy_recv_cb(conn, entry) |
Единый коллбэк etcp_router. По subcmd направляет REQUEST → exit_handle_request, REPLY → client_handle_reply. |
icmp_proxy_send_to_exit(inst, ...) |
Клиент: упаковывает ICMP Echo Request и отправляет через etcp_route_send на exit. |
icmp_proxy_deliver_reply(inst, ...) |
Клиент: собирает IP/ICMP Echo Reply-пакет и помещает в TUN input_queue. |
icmp_proxy_set_test_loopback(inst, enabled) |
Включает/выключает тестовый loopback-режим на exit (эмуляция echo-ответа без raw-сокета). |