# 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. Как пользоваться ### Инициализация ```c udp_proxy_init(inst, ua); // exit или клиент — определяется автоматически ``` При инициализации регистрируется коллбэк `udp_proxy_recv_cb` в `etcp_router` для сервиса `ETCP_RT_ID_UDP_PROXY`. ### Клиент: отправка датаграммы в exit ```c 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` на чтение. При получении ответа от внешнего хоста ответ упаковывается и отправляется обратно клиенту. ### Очистка ```c 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 для доставки приложению. |