EnglishРусский Map

MTproxy-reanimation

title
MTproxy-reanimation
type
toolbox
summary
SYN-лимитер в nftables и серверный TCP-десинхрон для MTProto-прокси Telemt с управлением через bash-меню
tags
shell, networking, censorship-circumvention, dpi, nftables, telegram, watchlist
language
Shell (bash)
license
MIT
created
2026-07-29
updated
2026-07-29
lang
ru
translation_of
mtproxy-reanimation
source_updated
2026-07-29
translated
2026-09-01
translator
lllm/antigravity/gemini-3.7-flash-medium

MTproxy-reanimation ("реаниматор") решает одну конкретную проблему: клиенты Telegram не могут завершить первое TCP-соединение с MTProto-прокси. Сам прокси работает; глушится именно рукопожатие. Инструмент представляет собой bash-меню под названием mtpr, которое настраивает правила nftables для обхода этой проблемы, а также выполняет небольшую безопасную оптимизацию Telemt и MTProxyMax. Он не заменяет ни один из них - он работает рядом и управляет правилами на уровне ядра и несколькими параметрами конфигурации.

Установка сама находит прокси: MTProxyMax, Docker-контейнер, юнит systemd или обычный локальный процесс. Скрипт читает конфигурацию Telemt, чтобы найти API-порт ([server.api], по умолчанию 9091), делает резервную копию конфигурации перед любыми изменениями и предлагает восстановиться из неё при удалении. Конфигурации Telemt Panel скрипт намеренно не трогает.

Выбор хука netfilter

Первая неочевидная деталь - выбор хука в зависимости от способа развёртывания. Telemt на хосте или с host networking получает правила в цепочке input. Telemt в сети Docker bridge получает forward, поскольку пакеты маршрутизируются в контейнер, а не доставляются локально. Для bridge есть два варианта: простой режим, который сопоставляет только порт, и точный режим Docker, который сопоставляет внутренний IP контейнера и запускает фоновый сервис (mtpr-bridge-watch.service), отслеживающий смену адреса. В README советуют сначала пробовать точный режим.

SYN-лимитер: Classic и Smart

Изначальный механизм - ограничение частоты входящих SYN-пакетов для каждого источника. Режим Classic использует один счётчик на всех:

tcp dport <PORT>
tcp flags & (syn | ack) == syn
meter { ip saddr timeout 60s limit rate over 1/second burst 1 packets }
counter drop

Ограничение входящих попыток подключения для починки связи кажется парадоксальным, пока не станет понятен его смысл. При помехах клиент Telegram агрессивно повторяет рукопожатия по нескольким возможным путям; принудительное замедление этого потока заставляет его быстрее зафиксироваться на рабочем маршруте, а не метаться без толку. Слабое место режима Classic в том, что он использует drop: клиент, попавший под лимит, ждёт таймаута повторной отправки, и установка соединения растягивается на 10-20 секунд.

Smart By-MEKO, рекомендуемый режим, делит клиентов на две ветки и меняет способ сброса. Клиенты на iOS определяются по TCP SYN fingerprint - прямому сопоставлению смещений в заголовке TCP, проверяющему структуру опций и значения окна вместо эвристик:

@th,108,20 0x2ffff  @th,160,16 0x204  @th,192,16 0x103
@th,224,24 0x10108  @th,320,32 0x4020000

iOS получает мягкий лимит (частота 15/сек, burst 30) и TCP reset при его превышении; всё остальное получает строгий лимит (частота 54/мин, burst 1) и по умолчанию reject with icmp type host-unreachable. Обе ветки работают на одном порту. Смысл ICMP вместо drop в том, что явный отказ Telegram воспринимает как быстрый сбой и немедленно пробует другое соединение. Согласно README, это сокращает время подключения до 3-8 секунд и, в частности, убирает долгое зависание при отправке медиафайлов с Android- и Desktop-клиентов. Лимит для любой из веток можно отключить вовсе. Более старый метод фингерпринтинга - ip ttl < 65 AND meta length 64 - остаётся доступным для совместимости.

Подход с фингерпринтами пришёл из MTPROTO-FIX-By-MEKO, которому в README отдают должное как за разделение iOS/Android, так и за идею быстрого сброса.

Режим zapret2: десинхронизацию выполняет сервер

В версии 1.2.0 (июль 2026 года) появился совершенно другой механизм, построенный на модификаторе пакетов nfqws2 из zapret2 со скриптами на Lua. Он не дополняет SYN-лимитер, а заменяет его: включение режима zapret2 автоматически отключает лимитер.

Последовательность шагов, которая полностью выполняется на сервере для его собственных исходящих пакетов:

  1. SYN+ACK отправляется с window = 1400, из-за чего клиент вынужден фрагментировать свой первый пакет с данными вместо отправки ClientHello целиком.
  2. Пустые ACK от сервера отправляются с window = 10, пока клиент не передаст полезную нагрузку, сохраняя ограничение.
  3. Первый пакет данных от клиента - ClientHello Fake-TLS - нарезается на три части. Первая уходит как обычно, третья - тоже как обычно со своим смещением, а средняя - с намеренно повреждённой контрольной суммой.
  4. Middlebox видит неполный и нарушенный по порядку ClientHello, который не может разобрать, а повреждённый сегмент отбрасывается до того, как пакет соберётся воедино.
  5. Клиент повторно отправляет среднюю часть, соединение устанавливается, а весь последующий трафик проходит без изменений - он пропускается через fwmark вместе с метками conntrack и параметром instance_cutoff в Lua-скрипте.

Это зеркальное отражение техники из tls-desync-fake-clienthello. Там клиент сбивает с толку DPI, отправляя фальшивый ClientHello с низким TTL перед настоящим; здесь же сервер делает так, чтобы ни один целый ClientHello не прошёл через middlebox в читаемом виде. Цель та же - проверка SNI в системах вроде tspu, но с противоположного конца соединения. Здесь используется та же терминология split/disorder/badsum, что и в семействе zapret, и, в отличие от eBPF-подхода в gecit, на стороне клиента ничего устанавливать не требуется.

Для клиентов на iOS сделано исключение: они определяются по фингерпринту на этапе SYN, помечаются через fwmark = 0x40000 и отправляются через rawsend_dissect_segmented без манипуляций с размером окна, так как игры с окном ухудшают их соединения. В более ранних версиях они просто пропускались (VERDICT_PASS), из-за чего пакеты зацикливались обратно в очередь netfilter.

Таблица nftables состоит из четырёх цепочек, выстроенных так, чтобы уже обработанные пакеты не попадали в очередь повторно:

table ip MTProto {
    chain predefrag   # output priority -401: fwmark accept + notrack
    chain output      # route mangle: ct mark set for marked packets
    chain postrouting # srcnat+1: ct mark accept + queue
    chain prerouting  # mangle: ct mark accept + queue
}

Ограничение wscale

Обход работает только в том случае, если анонсируемое окно приёма действительно мало, а TCP window scaling этому мешает. Эффективный размер окна равен win_ACK × 2^wscale, и ядро выбирает wscale исходя из размера буфера приёма. Поэтому сервер, оптимизированный под высокую пропускную способность, в принципе не может анонсировать достаточно маленькое окно:

wscale 2^wscale подходящий win ACK эффективное окно
7 128 10 1280 байт
9 512 2 1024 байта
11 2048 - невозможно

При wscale ≥ 11 (буфер от 64 МБ) не существует целого числа, дающего значение меньше 1400, и установщик выводит инструкции по уменьшению net.core.rmem_max. Эта проверка запускается при установке и повторно в пункте меню диагностики; её нужно выполнять заново при любом изменении параметров буферов в ядре. Это хороший пример техники обхода, применимость которой зависит от совершенно постороннего параметра sysctl.

Тонкая настройка и остальное меню

Помимо работы с netfilter скрипт управляет тремя таймаутами Telemt - tg_connect 30, client_handshake 90, client_keepalive 120 - и значениями client_mss / client_mss_bulk, которые в README рекомендуют отключать как в режиме Smart, так и в Zapret2, поскольку они решают ту же проблему хуже. Скрипт получает ссылки tg://proxy?... для пользователей через API Telemt с помощью jq, отфильтровывая записи IPv6 и учитывая public_host/public_port. Два старых обходных пути для iOS (параметры sysctl для TCP keepalive; отдельный порт 4443 с MSS=92 и прозрачным редиректом) были перенесены в подменю "legacy settings", так как оба текущих режима сделали их ненужными.

Один совет из README не связан напрямую с самим инструментом, но важен: домен для Fake-TLS обязан поддерживать постквантовый гибридный обмен ключами (X25519MLKEM768), иначе клиенты на iOS не подключатся вовсе. Никакая настройка nftables это не исправит.

Ограничения и нюансы

Репозиторий создан 2026-06-10 и представляет собой bash-скрипт одного автора с 294 звёздами и 5 форками. Он устанавливается через curl | sudo bash, создаёт юниты systemd и меняет правила фаервола на уровне ядра на рабочем сервере - сначала прочитайте скрипт. Всё описанное выше - это изложение из README о работе на серверах самого автора; независимых замеров цифры в 3-8 секунд или зависания при отправке медиа нет. Режим Docker bridge не тестировался с zapret2, согласно примечанию о совместимости в самом README. Кроме того, апстрим развивается: в Telemt 3.4.18+ появились возможности, пересекающиеся с функциями реаниматора, и в README рекомендуется выбрать что-то одно, а не запускать оба решения вместе.

Тег watchlist - см. watchlist. Инструменты для обхода цензуры быстро устаревают, а этот привязан к единственной реализации прокси, которая сама перенимает его возможности.

Клиентская сторона той же проблемы описана в xray-tutorial и happ-proxy; маршрутизация через полученные прокси - в mihomo и wirez.

MIT, ~294★ на 2026-07-29.