🇷🇺 Что нового (RU)
Коротко
v1.9.0 добавляет два усиления, отобранных при разборе MTproxy-reanimation (тюнинг-обвязка для Telemt/MTProxyMax). Из пяти её приёмов мы взяли только два — остальные мы уже делаем лучше или они конфликтуют с нашими инвариантами. Апгрейд безопасен: ограничение SYN — опциональное и по умолчанию выключено, а таймаут коннекта к DC — безопасный дефолт, на здоровые соединения не влияет.
Ограничение SYN на уровне ядра (опционально) — mtbuddy setup syn-limit
- Per-IP ограничение входящих SYN на порту прокси через
iptables -m hashlimit. Дропает абьюзные SYN-всплески в ядре, доaccept()— там, где наши внутрипроксийные стражи слабее всего (flood guard и per-/24 лимитер работают послеaccept()и сами по умолчанию выключены, так что каждый абьюзный SYN сейчас всё равно стоит сокета иaccept()). - Ставится отдельным systemd-oneshot (
mtproto-syn-limit.service), поэтомуCAP_NET_ADMINпрокси не выдаётся. - По умолчанию выключено и с громким предупреждением про carrier-NAT/CGNAT (та же проблема общего egress-IP, из-за которой выключены внутрипроксийные стражи). Пресеты: soft
2/с·burst 5(дефолт при включении, безопаснее для CGNAT), medium1/с·3, hard1/с·1. Предупреждает, если включёнaccept_proxy_protocol(ядро видит IP балансировщика, а не клиента). - Счётчик дропов в
mtbuddy status; проверяет, что правило реально применилось (модульxt_hashlimitна месте), а не молча превратилось в no-op. Идемпотентная установка + полная очистка при uninstall. - Взяли iptables (а не nftables), чтобы лечь в существующий стек (TCPMSS, nfqws) — без новой зависимости.
sudo mtbuddy setup syn-limit --preset soft # soft 2/с·5 | medium 1/с·3 | hard 1/с·1
sudo mtbuddy setup syn-limit --status
sudo mtbuddy setup syn-limit --removePer-endpoint таймаут коннекта к DC — dc_connect_timeout_sec (дефолт 10с)
- Дедлайн на завершение TCP-
connect()к каждому эндпоинту Telegram DC. Заблэкхоленный эндпоинт не шлёт RST, и ядро держитSYN_SENT~2 минуты.handshake_timeout_sec(15с) уже ограничивает весь хендшейк — но глобально, поэтому медленный первый эндпоинт съедает бюджет failover для остальных. - Теперь один мёртвый эндпоинт отбрасывается быстро, и failover переходит к следующему в пределах общего потолка
handshake_timeout_sec. - На здоровые коннекты не влияет (они завершаются за <1с); проверка привязана к фазе
.connecting_upstream, поэтому никогда не трогает установленный релей. - Сознательно не поднимали
handshake_timeout_secдо больших значений — это расширило бы окно для active-probe/slow-loris, против которого заточены DD-логика и flood guard.
Что НЕ взяли (и почему)
- iOS keepalive sysctl (60/15/3): для нас no-op — на established-сокетах мы уже ставим
SO_KEEPALIVE 60/10/3+TCP_USER_TIMEOUT=30s(жёстче), а host-wide sysctl не достаёт pre-handshake сокеты безSO_KEEPALIVE(их и так жнут idle/handshake-таймауты). - iOS MSS=92 + отдельный порт с DNAT: отдельный порт = вторая
tg://-ссылка (наши ссылки иммутабельны после раздачи — твёрдое «нет»); MSS-половина конфликтует с нашимTCPMSS=88; и это folk-remedy для iOS-зависания, которое мы уже докопали до клиентского бага MtProtoKit (bad_server_salt) и закрылиclient_silence_close_sec(+ апстрим-PR Telegram-iOS#2197). - Автодетект деплоя + персист правил в systemd: у нас уже всё это есть для своего стека.
Проверено
zig build test зелёный + кросс-сборки + install-матрица (debian 11/12, ubuntu 20.04/22.04/24.04) + E2E + bench. Изменение в ядре прокси байт-прозрачно и вне happy-path; firewall-фича опциональна и изолирована в своём unit. Документация обновлена во всех README (en/ru/zh/fa/vi) и THREAT_MODEL.
🇬🇧 Release notes (EN)
TL;DR
v1.9.0 adds two hardening features picked from analysing MTproxy-reanimation (a tuning wrapper for Telemt/MTProxyMax). Of its five techniques we kept only two — the rest we already do better or they conflict with our invariants. Upgrading is safe: the SYN limiter is optional and off by default, and the DC connect timeout is a safe default that never affects healthy connections.
Optional kernel SYN rate-limiter — mtbuddy setup syn-limit
- Per-source-IP inbound SYN rate-limit on the proxy port via
iptables -m hashlimit. Drops abusive SYN bursts in the kernel, beforeaccept()— exactly where our in-proxy guards are weakest (the flood guard and per-/24 limiter run afteraccept()and themselves default off, so every abusive SYN currently still costs a socket + anaccept()). - Installed as a separate systemd oneshot (
mtproto-syn-limit.service), soCAP_NET_ADMINis never granted to the proxy. - Off by default, behind a loud carrier-NAT/CGNAT warning (the same shared-egress-IP problem that keeps the in-proxy guards off). Presets: soft
2/s·burst 5(default when enabling, CGNAT-safer), medium1/s·3, hard1/s·1. Warns whenaccept_proxy_protocolis set (kernel sees the LB IP, not clients). - Drop counter in
mtbuddy status; verifies the rule actually landed (xt_hashlimitpresent) instead of a silent no-op. Idempotent apply + full uninstall cleanup. - Uses iptables (not nftables) to match our existing stack (TCPMSS, nfqws) — no new dependency.
sudo mtbuddy setup syn-limit --preset soft # soft 2/s·5 | medium 1/s·3 | hard 1/s·1
sudo mtbuddy setup syn-limit --status
sudo mtbuddy setup syn-limit --removePer-endpoint DC connect timeout — dc_connect_timeout_sec (default 10s)
- A deadline for completing the TCP
connect()to each Telegram DC endpoint. A filtered/black-holed endpoint sends no RST, so the kernel sits inSYN_SENTfor ~2 min.handshake_timeout_sec(15s) already caps the whole handshake — but globally, so a slow first endpoint starves the failover budget for the rest. - Now one dead endpoint is abandoned fast and failover advances to the next, within the overall
handshake_timeout_secceiling. - Never affects healthy connects (they finish in <1s); the check is gated on the
.connecting_upstreamphase, so it can never touch an established relay. - Deliberately does not raise
handshake_timeout_sec— that would widen the active-probe / slow-loris window our DD-decision and flood guards exist to shrink.
Not ported (and why)
- iOS keepalive sysctl (60/15/3): a no-op for us — relay sockets already set
SO_KEEPALIVE 60/10/3+TCP_USER_TIMEOUT=30s(stricter), and a host-wide sysctl can't touch pre-handshake sockets that lackSO_KEEPALIVE(already reaped by our idle/handshake timeouts). - iOS MSS=92 + separate port DNAT: a second port = a second
tg://link (our links are immutable once distributed — hard no); the MSS half conflicts with ourTCPMSS=88; and it's a mechanism-free folk remedy for the iOS resume hang we already root-caused to the client MtProtoKitbad_server_saltbug and addressed withclient_silence_close_sec(+ upstream PR Telegram-iOS#2197). - Deployment autodetection + systemd rule persistence: already implemented for our own stack.
Verified
zig build test green + cross-builds + install matrix (debian 11/12, ubuntu 20.04/22.04/24.04) + E2E + bench. The proxy-core change is byte-transparent and off the happy path; the firewall feature is opt-in and isolated in its own unit. Docs updated across all READMEs (en/ru/zh/fa/vi) and THREAT_MODEL.
Full Changelog: v1.8.1...v1.9.0