🇷🇺 Что нового (RU)
Что решает этот релиз
Комплексное укрепление надёжности, безопасности и производительности прокси по итогам code review. Главные пользовательские эффекты:
- Медиа-трафик больше не тормозит. Прокси теперь различает обычные и медиа‑MiddleProxy и маршрутизирует фото/видео через выделенный media‑MP флот Telegram. Ранее все запросы шли на один MP, что вызывало стеллы и сбросы при загрузке медиа.
- Прокси на цензурируемых хостах обновляет конфигурацию MP через туннель. Если
core.telegram.orgзаблокирован, прокси автоматически фоллбэчит наcurl --interface <tunnel>и прогревает кэш MP в первые минуты работы (а не через 24 часа). - Устранены уязвимости: коллизия IPv4-mapped IPv6 в rate limiter, потенциальная коррупция данных в SOCKS5/HTTP CONNECT, переполнение буфера MiddleProxy, паника
@memcpyпри формировании nonce. - Повышена производительность: O(1) поиск секрета вместо O(N), streaming HMAC без аллокации ~3 KB, корректный DRS при отключённом anti-DPI.
Что изменено
Безопасность и корректность
-
Rate-limit: IPv4-mapped IPv6 (#197)
- На dual-stack
[::]listener'ах все IPv4-клиенты приходят как::ffff:a.b.c.d. Без патча они коллапсировали в один subnet key, и весь IPv4 интернет делил один token bucket. subnetKey()теперь детектирует IPv4-mapped адреса и применяет IPv4-specific/24логику.
- На dual-stack
-
SOCKS5/HTTP CONNECT pipelined data
- Лишние байты после успешного SOCKS5/HTTP CONNECT handshake теперь приводят к закрытию соединения с предупреждением вместо потенциальной коррупции протокола.
-
MiddleProxy buffer overflow
- Scratch-буфер
mp_c2s_scratchтеперь выделяется с запасом ×96 (реальный worst-case расширения обфускации) + 256 байт заголовков.
- Scratch-буфер
-
MiddleProxy nonce selector fix
- Исправлена регрессия формирования nonce-фрейма: 4 байта ключевого селектора корректно копируются побайтово вместо потенциально паникующего
@memcpy.
- Исправлена регрессия формирования nonce-фрейма: 4 байта ключевого селектора корректно копируются побайтово вместо потенциально паникующего
-
TOML escape tracking (
src/ctl/toml.zig)- При удалении инлайн-комментариев теперь учитывается
escaped-состояние (символ#внутри экранированной последовательности не считается началом комментария).
- При удалении инлайн-комментариев теперь учитывается
Производительность
-
O(1) secret resolution
- В
finishClientHandshakeиспользуетсяslot.validation_secretнапрямую вместо перебора всего списка пользователей.
- В
-
Streaming HMAC (
src/protocol/tls.zig)- В
buildServerHelloWithTemplateубрана heap-аллокация ~3 KB: данные теперь подаются в хэшер потоково.
- В
-
DRS init при
drs = false- Когда Dynamic Record Sizing отключён, инициализация теперь стартует с
full_size(16384), а не с 1369 — нет смысла клэмпить записи при отключённом anti-DPI.
- Когда Dynamic Record Sizing отключён, инициализация теперь стартует с
Медиа-aware MiddleProxy routing (ключевое изменение)
-
Bundled media MP addresses (
src/protocol/constants.zig)- Добавлен массив
tg_media_middle_proxies_v4с отдельными адресами для media‑MP, чтобыproxy_for -Nendpoints были доступны даже без подключения кcore.telegram.org.
- Добавлен массив
-
DcSignFilterв парсере getProxyConfigparseMiddleProxyAddressesForDc()теперь принимает фильтрpositive_only(обычный трафик) /negative_only(медиа) /any(legacy), корректно разделяя два пула MP.
-
MiddleProxySnapshotс media-полями- Добавлены
addrs_media_primary[5]иaddrs_media_dc4[16]для хранения media‑MP. getForDc()принимаетmedia: boolи возвращает соответствующий endpoint.
- Добавлены
-
buildDcConnectPlan()с media fallback- Если
is_media_path— используется media-MP; если media-пул пуст — fallback на обычный MP.
- Если
Работа из цензурируемой сети
-
fetchUrlBytesViaInterface()— curl-based fallback- Когда прямой HTTP к
core.telegram.orgнедоступен и сконфигурирован tunnel upstream, прокси вызываетcurl --interface <tunnel_iface>. - Исправлена передача аргументов:
--interfaceи значение как два отдельных элемента argv (не--interface=val).
- Когда прямой HTTP к
-
Early retry loop в
middleProxyUpdaterMain()- Перед переходом к 24-часовому циклу обновления MP выполняются ретраи с нарастающими интервалами: 10 с → 30 с → 1 мин → 5 мин → 30 мин.
- На цензурируемом хосте кэш MP с media-endpoints прогревается в первые минуты, а не на следующие сутки.
Edge-cases
- ENOBUFS / TCP aborts — корректная обработка
error.SystemResourcesи benign TCP-abort вacceptNewConnections. @memcpypanic guard — вmiddleProxyBeginпредварительный@memsetи условное побайтовое копирование ключевого селектора.
Tip
Обновление не требует изменения конфигурации. Все bundled MP-адреса автоматически обновляются из getProxyConfig при наличии связности (напрямую или через туннель).
🇬🇧 Release notes (EN)
What this release addresses
Comprehensive hardening of proxy reliability, security, and performance based on code review findings. Key user-visible effects:
- Media traffic no longer stalls. The proxy now distinguishes regular vs media MiddleProxy endpoints and routes photo/video downloads through Telegram's dedicated media MP fleet. Previously all traffic was routed to the same MP, causing stalls and connection resets on large media downloads.
- Proxy on censored hosts refreshes MP config via tunnel. When
core.telegram.orgis blocked, the proxy automatically falls back tocurl --interface <tunnel>and warms the MP cache within the first few minutes (instead of waiting 24 hours). - Security fixes: IPv4-mapped IPv6 rate-limiter collision, potential SOCKS5/HTTP CONNECT data corruption, MiddleProxy buffer overflow,
@memcpypanic in nonce frame construction. - Performance improvements: O(1) secret lookup instead of O(N), streaming HMAC without ~3 KB allocation, correct DRS initialization when anti-DPI is disabled.
What changed
Security & correctness
-
Rate-limit: IPv4-mapped IPv6 (#197)
- On dual-stack
[::]listeners, all IPv4 clients arrive as::ffff:a.b.c.d. Without this fix they collapsed to a single subnet key, sharing one token bucket across the entire IPv4 internet. subnetKey()now detects mapped addresses and applies IPv4-specific/24logic.
- On dual-stack
-
SOCKS5/HTTP CONNECT pipelined data
- Extra bytes after a successful SOCKS5/HTTP CONNECT handshake now cause the connection to be closed with a warning, preventing potential protocol corruption.
-
MiddleProxy buffer overflow
- The
mp_c2s_scratchbuffer now allocates ×96 headroom (real worst-case obfuscation expansion) + 256 bytes for headers.
- The
-
MiddleProxy nonce selector fix
- Fixed a regression in nonce frame construction: 4 bytes of the key selector are now safely copied byte-by-byte instead of using a potentially panicking
@memcpy.
- Fixed a regression in nonce frame construction: 4 bytes of the key selector are now safely copied byte-by-byte instead of using a potentially panicking
-
TOML escape tracking (
src/ctl/toml.zig)- Inline comment removal now respects the
escapedstate — a#inside an escape sequence is no longer treated as a comment start.
- Inline comment removal now respects the
Performance
- O(1) secret resolution —
finishClientHandshakenow usesslot.validation_secretdirectly instead of iterating all users. - Streaming HMAC (
src/protocol/tls.zig) — removed ~3 KB heap allocation frombuildServerHelloWithTemplate; data is now fed to the hasher in a streaming fashion. - DRS init when
drs = false— when Dynamic Record Sizing is disabled, initialization starts atfull_size(16384) instead of the probe-friendly 1369.
Media-aware MiddleProxy routing (key change)
- Bundled
tg_media_middle_proxies_v4addresses inconstants.zigfor fallback whengetProxyConfigis unavailable. parseMiddleProxyAddressesForDc()now takes aDcSignFilterparameter (positive_only/negative_only/any) to correctly separate regular vs media MP pools.MiddleProxySnapshotcarries separateaddrs_media_primaryandaddrs_media_dc4fields.buildDcConnectPlan()selects media MP whenis_media_path, with automatic fallback to regular MP if the media pool is empty.
Censored-network operation
fetchUrlBytesViaInterface()— curl-based fallback through the configured tunnel interface whencore.telegram.orgis unreachable.- Early retry loop in
middleProxyUpdaterMain()— retries at 10s, 30s, 1m, 5m, 30m before entering the 24-hour refresh cadence. Warms the MP cache within the first few minutes on censored hosts.
Edge-cases
- ENOBUFS / TCP aborts — proper handling of
error.SystemResourcesand benign TCP abort inacceptNewConnections. @memcpypanic guard — safe byte-by-byte copy of the key selector inmiddleProxyBegin.
Tip
This update requires no configuration changes. Bundled MP addresses are automatically refreshed from getProxyConfig when connectivity is available (directly or via tunnel).