Skip to content

proxy: DNS-резолв через туннель и UDP ASSOCIATE для SOCKS5-прокси#65

Closed
kyctarnik wants to merge 2 commits into
infosave2007:masterfrom
kyctarnik:master
Closed

proxy: DNS-резолв через туннель и UDP ASSOCIATE для SOCKS5-прокси#65
kyctarnik wants to merge 2 commits into
infosave2007:masterfrom
kyctarnik:master

Conversation

@kyctarnik

Copy link
Copy Markdown

Что добавляет

SOCKS5-прокси (--proxy-listen) получает две возможности:

  1. Резолв DNS через туннель. Имена из CONNECT (и из UDP-запросов) резолвятся
    smoltcp'шным dns::Socket через VPN-туннель, а не резолвером хостовой ОС. Запрос
    уходит в шифрованный туннель → нет утечки DNS на хост и работает для имён, которые
    локальный резолвер не отдаёт/подменяет (socks5h).
  2. UDP ASSOCIATE (RFC 1928). Полноценный UDP-релей: relay-сокет на стороне прокси,
    smoltcp UDP-сокет в туннель, обёртка SOCKS5 UDP request/response, per-association
    DNS-кэш, пиннинг адреса клиента. Открывает QUIC/HTTP3 и прочий UDP через прокси.

Детали реализации / на что смотреть при ревью

  • Стек — userspace smoltcp. MTU интерфейса = 1280, и это значимо: smoltcp не делает
    TCP PMTUD (и proto-ipv4-fragmentation не включён — фрагменты не пересобирает),
    поэтому MTU задаётся консервативно заранее. При downstream через Cloudflare WARP
    (inner MTU 1280) бóльшие значения дают чёрную дыру: крупные входящие сегменты (обычно
    TLS Certificate не-Cloudflare хостов) дропаются и хендшейк виснет. 1280 это снимает.
  • Цикл стека — event-driven, без busy-poll: поток спит на канале-будилке с таймаутом
    iface.poll_delay() и просыпается на входящих пакетах, новых CONNECT, исходящих данных
    и UDP/DNS-командах. poll_delay закрывает таймеры smoltcp, будилка — внешний I/O.
    wake_tx проброшен через ProxyHandle и клиента.
  • TcpSocket: set_nagle_enabled(false) + set_ack_delay(None) для форвардинга.

Известные ограничения / на будущее (в этом PR не решаются, отмечаю явно)

  • MTU захардкожен в 1280 и предполагает downstream через Cloudflare WARP. Сервер с
    другим egress-MTU потребует другого значения — это должно быть опцией CLI/конфига (или
    выводиться из дескриптора сервера), а не константой. Комментарий
    // совпадает с WAN_SAFE_TUN_MTU вводит в заблуждение: это другое ограничение
    (downstream-путь, а не WAN-хоп).
  • IPv6 в proxy-режиме фактически не поддержан. smoltcp-iface получает только
    IPv4-адрес и IPv4-маршрут по умолчанию, TCP DNS резолвит только A (want_v6=false), а
    handle_connect режет ATYP_IPV6 / v6-резолв цели с HOST_UNREACHABLE. Поэтому
    socks5h работает (IPv4-only), а socks5:// до dual-stack хоста может падать, когда
    клиент передаёт v6-литерал. proto-ipv6 в Cargo.toml включён, но для роутинга не
    используется.
  • Потолок скорости одного соединения. В smoltcp нет TCP window scaling, поэтому окно
    приёма упирается в ~64 КБ независимо от TCP_BUF; одиночный поток ≈ 64 КБ / RTT. Для
    браузера (много соединений) ок, для одной большой загрузки — медленно.
  • DNS использует единственный захардкоженный резолвер (1.1.1.1); Сокет работает только с одним сервером. Должно браться из конфига.

@infosave2007

Copy link
Copy Markdown
Owner

Внес Ваши правки гармонично в код и поправил некоторые уязвимости, спасибо!

@kyctarnik

Copy link
Copy Markdown
Author

Благодарю за ваше внимание данной проблеме и имплементацию её решения.

У меня так же были указаны некие проблемы моей реализации, и, как я вижу, они до сих пор сохранены. Прежде чем браться: вы принимаете внешние PR или предпочитаете реализовать всё сами? (конфигурируемые MTU, DNS и IPv6 в proxy.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants