5.0 KiB
UDP Proxy (udp_proxy)
1. Назначение
Проксирование UDP-датаграмм между клиентским и exit-узлом по протоколу ETCP. Клиентский узел
принимает UDP-пакеты с TUN-интерфейса, инкапсулирует их и отправляет через etcp_route_send
на exit-узел. Exit-узел создаёт нативные UDP-сокеты для каждого потока (5-tuple) и ретранслирует
датаграммы во внешнюю сеть. Ответы проходят обратный путь — от exit к клиенту и затем в TUN.
Один экземпляр контекста на процесс (глобальный g_udp_ctx), режим определяется флагом
inst->tcp_proxy_server.enabled: включён → is_exit=1, иначе is_exit=0.
2. Как пользоваться
Инициализация
udp_proxy_init(inst, ua); // exit или клиент — определяется автоматически
При инициализации регистрируется коллбэк udp_proxy_recv_cb в etcp_router для сервиса
ETCP_RT_ID_UDP_PROXY.
Клиент: отправка датаграммы в exit
udp_proxy_send_to_exit(inst, exit_node_id, src_ip, src_port, dst_ip, dst_port, payload, len);
Вызывается из обработчика TUN-трафика. Пакет упаковывается в формат ETCP и отправляется
через etcp_route_send. Ответ приходит асинхронно в udp_proxy_recv_cb, который вызывает
udp_proxy_deliver_reply для записи IP/UDP-пакета обратно в TUN.
Exit: приём датаграмм
Exit автоматически принимает REQUEST-ы через etcp_router. Для каждого нового потока
(уникальный client_node_id + src_ip:port + dst_ip:port) создаётся нативный UDP-сокет,
который регистрируется в uasync на чтение. При получении ответа от внешнего хоста
ответ упаковывается и отправляется обратно клиенту.
Очистка
udp_proxy_destroy(inst); // закрывает все flows, отменяет таймер, unbind из etcp_router
Нюансы
- Потоки истекают через 60 секунд неактивности (
UDP_FLOW_TIMEOUT_TB). Таймерexpire_timerзапускается при создании первого потока, перезапускается после каждой очистки. - UDP-сокеты на exit привязываются к
INADDR_ANY:0(bind), трафик отправляется черезsendto. - Ответы в TUN на клиенте доставляются через
inst->tcp_proxy_client->tun->input_queue.
3. API
Структуры
| Структура | Назначение |
|---|---|
struct udp_flow |
Состояние одного UDP-потока на exit: 5-tuple, нативный сокет, uasync read_id, времена создания и последней активности. Связный список. |
struct udp_proxy_ctx |
Глобальный контекст: флаг is_exit, inst, ua, список flows, таймаут истечения, таймер очистки. |
Формат пакета
| Смещение | Размер | Поле |
|---|---|---|
| 0 | 1 | svc_id = ETCP_RT_ID_UDP_PROXY |
| 1 | 1 | subcmd = UDP_PROXY_SUBCMD_DATA (0x01) |
| 2 | 8 | sender_node_id |
| 10 | 4 | src_ip (клиент→exit: IP отправителя; exit→клиент: dst_ip) |
| 14 | 2 | src_port |
| 16 | 4 | dst_ip (клиент→exit: IP назначения; exit→клиент: src_ip) |
| 20 | 2 | dst_port |
| 22 | N | payload (UDP-датаграмма) |
Функции
| Функция | Назначение |
|---|---|
udp_proxy_init(inst, ua) |
Выделяет контекст, определяет is_exit, регистрирует коллбэк в etcp_router. Возвращает 0 при успехе. |
udp_proxy_destroy(inst) |
Закрывает все потоки, сокеты, отменяет таймеры, отвязывает коллбэк, освобождает память. |
udp_proxy_recv_cb(conn, entry) |
Единый коллбэк etcp_router. По subcmd направляет в exit_handle_data (exit) или client_handle_reply (клиент). |
udp_proxy_send_to_exit(inst, ...) |
Клиент: упаковывает UDP-датаграмму и отправляет через etcp_route_send на exit. |
udp_proxy_deliver_reply(inst, ...) |
Клиент: собирает IP/UDP-пакет и помещает в TUN input_queue для доставки приложению. |