🛠️ Настройка MTProxy на mtproto.zig — пошагово и «что происходит на проводе»
Что это и для кого
Практический runbook: как поднять MTProxy на mtproto.zig и понимать, что делает каждый слой защиты — с учётом свежих наблюдений (протухший фингерпринт клиента из tdesktop#30733, детект по expected_64_got_0, приёмы TCPMSS и SYN-ACK).
Теория и «почему» — в обзорной статье MTProxy и mtproto.zig. Здесь — команды, конфиг и диагностика.
Почему mtproto.zig, а не telemt
Оба — хорошие FakeTLS-прокси. mtproto.zig берут, когда нужен обход DPI «под ключ»: он сам ставит TCPMSS-дробление + nfqws-desync + nginx-маскировку одной командой, без ручного iptables. telemt — когда нужен REST API для бота (сравнение).
Слабое звено, которое сервер НЕ чинит — фингерпринт клиента
Почерк ClientHello (JA3/JA4) генерирует приложение Telegram, не сервер. По tdesktop#30733: Desktop мимикрирует под Chrome 134/macOS (t13d1516h2_8daaf6152771_d8a2da3f94cd), а живой Chrome — 148 → пресет протух, и это маркер. Это тот самый блок, дающий expected_64_got_0 (разбор логов).
Лечится только в самом Telegram. Всё, что может сервер — спрятать/сломать опознание этого почерка (TCPMSS, desync), а не поправить его. Поэтому Шаги 4–6 важны.
Шаг 4. TCPMSS — дробление ClientHello
Как работает
Сервер анонсирует в SYN-ACK малый MSS, и клиент вынужден резать всё исходящее (включая ClientHello ~517 байт) на мелкие сегменты. DPI без потоковой пересборки не складывает почерк целиком → не матчит сигнатуру.
В mtproto.zig включено по умолчанию (TCPMSS=88). Сменить значение: mtbuddy install --tcpmss 96.
Вариант «через балансировщик» — помогает?
Да, помогает. Это тот же механизм. Если перед прокси стоит балансировщик (он терминирует клиентский TCP), MSS-clamp надо вешать именно на балансировщик — там рождается SYN-ACK к клиенту:
Конфиг telemt/mtproto.zig при этом трогать не надо — правило работает на уровне ядра.
Почему «на балансировщике»: clamp на бэкенде (где сидит сам прокси) не дойдёт до клиента, если балансировщик пере-устанавливает TCP. Правило должно быть на той коробке, что шлёт SYN-ACK клиенту.
88 или 96 — разница невелика
Оба дают ~6 сегментов на ClientHello. mtproto.zig по умолчанию 88; совет из интернета — 96. Бери любое; если ставишь mtproto.zig напрямую (без отдельного балансировщика) — TCPMSS уже стоит, дублировать руками не нужно.
Это и есть «решение JA4» из teleproxy
Когда говорят «в teleproxy решён JA4» — речь именно об этой фрагментации: teleproxy
ставит TCP_MAXSEG=256, чтобы DPI не извлёк JA4 из первого пакета. JA4 при этом
не меняется (его задаёт клиент). mtproto.zig делает то же самое и агрессивнее
(MSS=88), так что этот приём у тебя уже включён. Почему это не «смена почерка»
и где лежит настоящий фикс — SNI.
Дробление ≠ панацея
MSS-clamp бьёт по DPI, который не пересобирает поток. Если ТСПУ делает реассемблинг — одного дробления мало, нужен desync (nfqws, Шаг 5), который активно ломает пересборку fake-пакетами. Поэтому их ставят вместе.
Шаг 5. nfqws TCP desync + тюнинг TTL
Ставится при install. Стратегия: --dpi-desync=fake,split2 --dpi-desync-ttl=6 --dpi-desync-fooling=md5sig — fake-пакет с заниженным TTL (долетает до ТСПУ, умирает до клиента) + битая MD5-опция, чтобы сбить state-машину DPI.
TTL надо подтюнить под маршрут (дефолт 6 не универсален, «4–8 для росс. ISP»):
traceroute <ip_клиента_или_DC> # прикинуть хоп, где сидит ТСПУsudo mtbuddy nfqws --ttl 7 # переставитьsystemctl status nfqws-mtproto # проверить, что запущен
TTL должен быть больше расстояния до ТСПУ, но меньше расстояния до клиента.
Шаг 5.5 (опционально). Egress через Xray/SOCKS5 или туннель
Это аналог SOCKS5_PROXY + DIRECT_MODE из конфигов teleproxy: маршрут
исходящего трафика прокси к дата-центрам Telegram через Xray/VLESS (SOCKS5)
или WireGuard/AmneziaWG-туннель.
[upstream]type = "tunnel"[upstream.tunnel]interfaces = ["awg0", "awg1"] # WireGuard/AmneziaWG, с авто-фолбэком
Что это лечит, а что нет
Egress-маршрут помогает, когда дата-центры Telegram недоступны с твоего VPS
(заблокированы/режутся на пути proxy→DC), или нужен лишний хоп. Это путь
сервер→DC — на входящий ClientHello (где JA4, который видит ТСПУ у
клиента) он не влияет. Не путай: это про доступность DC, а не про обход
детекта почерка. См. SNI.
На пальцах: сервер иногда «роняет» свой ответ при установке соединения (SYN-ACK), клиент переспрашивает через секунду. От этого DPI сбивается со счёта и не опознаёт почерк клиента, а соединения идут не пачкой, а по одному в секунду. Спорный, но у людей рабочий приём.
Подробная механика (с аналогией), цена и per-port вариант (бюджет 1/сек на каждый порт, чтобы не калечить всех юзеров) — в разборе для telemt (для mtproto.zig всё идентично, только порт 443).
Коротко: ставить стоит, если блок держится после Шагов 4–5; брать сразу per-port; мониторить логи (Шаг 7), чтобы поймать адаптацию ТСПУ.
Шаг 7. Диагностика — mtproto.zig сам показывает атаку DPI
Фингерпринт клиента в логах
mtproto.zig логирует почерк первых 16 ClientHello (диагностический бюджет):
Смотри key_share в логе. Свежий браузер шлёт X25519MLKEM768 (post-quantum). Если твой клиент его не шлёт — он на старом пресете и попадает под детект из #30733. Это прямой способ увидеть «протух ли почерк» на своём трафике.
Метрики close-reason — детектор начала блокировок
mtproto.zig отдаёт Prometheus-метрику с причинами закрытия — её всплеск = ТСПУ начал резать:
Рост tls_validation_failed / replay_detected / handshake_timeouts над фоном — это и есть сигнал, что цензор начал работать по тебе (так и задумано разработчиком). replay_detected отдельно ловит active-probe зонды ТСПУ (Revisor).
Плюс есть веб-дашборд (порт 61208, Basic-auth, токен в /opt/mtproto-proxy/monitor/dashboard.token) — открывать только через SSH-тоннель.
Когда всё-таки заблокировали — порядок действий
Проверь логи/метрики (Шаг 7): растёт ли handshake_timeouts / tls_validation_failed, и какой key_share у падающих клиентов.
Подтюнь TTL nfqws (Шаг 5) — частая причина, что desync «не достаёт» до ТСПУ.
Снизь MSS (--tcpmss 80) или добавь clamp на балансировщик (Шаг 4).
Включи SYN-ACK per-port (Шаг 6).
Если рвётся путь до DC (а не вход) — egress через Xray/SOCKS5 или туннель (Шаг 5.5).
Смени узел/подсеть (Сигнал 1) — если IP/диапазон попал под раздачу.
Не дёргай настройки рефлекторно под блоком — сам паттерн адаптации может усугубить.