You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

5.2 KiB

Proxy: потоки TCP и датаграммы

Клиентские входы — TUN (lwIP), SOCKS5 CONNECT и HTTP proxy/CONNECT. Exit открывает обычный TCP-сокет к назначению. TCP-поток на exit определяется парой (peer_node_id, stream_id). Клиент принимает ответы и уведомления restart только от настроенного exit в UTUN-группе. UDP/ICMP-контексты принадлежат конкретному UTUN_INSTANCE.

TCP

Общие определения находятся в src/proxy/proxy_protocol.h. Передаваемый заголовок: svc_id:1, command:1, stream_id:4; поля маршрута добавляет ETCP-router.

  • CONNECT (1): IPv4:4 и порт:2 в сетевом порядке.
  • CONNECTED (2): exit подтвердил успешный TCP connect. Только после этого клиент сообщает SOCKS success / HTTP 200 и начинает передавать накопленные данные.
  • DATA (3): от 1 до 4096 байт.
  • CLOSE (4), ERROR (5): прекращение потока.
  • FIN (6): конец одного направления; все предшествующие DATA должны быть переданы.
  • WINDOW (7): uint32_t, число дополнительно разрешённых байт.

У каждого направления начальное окно 65536 байт. DATA уменьшает окно отправителя и получателя. Получатель возвращает кредит после записи в локальный TCP-сокет либо принятия данных ограниченным send-buffer lwIP. Очередь ETCP сама по себе не является подтверждением потребления данных конечным TCP.

FIN ждёт освобождения исходящей очереди, включая данные, остановленные окном или backpressure роутера. Закрытие одного направления не прекращает другое. Окончательное освобождение происходит после обоих FIN и передачи оставшихся данных. Непереданные управляющие сообщения повторяются таймером. Ошибки и переходы состояния диагностируются категорией proxy; состояние сокетов — socket.

Парсеры сохраняют остаток после greeting/request/HTTP headers. HTTP CONNECT ждёт полного блока заголовков. Во время DNS/connect чтение ограничено очередью tcp_io; накопленные HTTP headers/body передаются частями размером DATA.

UDP и ICMP

REQUEST и REPLY различаются явно. Ответ допускается только от настроенного exit. UDP-ответ восстанавливается с нулевой UDP checksum (допустимо для IPv4), IPv4 checksum пересчитывается. ICMP checksum учитывает нечётный последний байт без чтения за буфером.

Exit заменяет ICMP id/sequence уникальной среди ожидающих запросов парой и сопоставляет ответ также с IP назначения. Исходные id/sequence восстанавливаются для клиента. Это исключает смешивание ping-запросов разных клиентов с одинаковыми исходными ID.

Проверки и ограничения

test_proxy_packets проверяет IPv4/UDP/ICMP и payload длиной 0..1501. test_tcp_io_flush проверяет уведомление после последнего синхронного send. test_proxy_regressions использует реальные локальные сокеты и управляемую доставку ETCP: совместные/раздельные handshake, ранние данные, отложенный CONNECTED, HTTP 502, большой POST, одинаковые stream ID разных пиров, FIN при закрытом окне, RST и IPv4 options.

На Linux полный ./check.sh: 109 passed, 0 failed, 1 skipped; дополнительно прошли настоящий TUN, full-duplex burst и нагрузка 8 соединений / 128 МиБ. Windows/FreeBSD в этом прогоне не проверялись.

SOCKS IPv6 явно отклоняется кодом address type not supported. IPv4-фрагменты на входе proxy TUN отклоняются с диагностикой; сборка фрагментов не реализована. Формат TCP дополнен CONNECTED/WINDOW, UDP-команды разделены: клиент и exit необходимо обновлять вместе; совместимость со старым proxy-протоколом не предусмотрена.