# 🛠️ Настройка MTProxy на mtproto.zig — пошагово и «что происходит на проводе»
> [!info] Что это и для кого
> Практический **runbook**: как поднять MTProxy на [[mtproxy/mtproto-zig|mtproto.zig]] и **понимать, что делает каждый слой защиты** — с учётом свежих наблюдений (протухший фингерпринт клиента из [tdesktop#30733](https://github.com/telegramdesktop/tdesktop/issues/30733), детект по `expected_64_got_0`, приёмы TCPMSS и SYN-ACK).
>
> Теория и «почему» — в обзорной статье [[mtproxy/mtproto-zig|MTProxy и mtproto.zig]]. Здесь — команды, конфиг и диагностика.
> [!tip] Почему mtproto.zig, а не telemt
> Оба — хорошие FakeTLS-прокси. `mtproto.zig` берут, когда нужен **обход DPI «под ключ»**: он сам ставит TCPMSS-дробление + nfqws-desync + nginx-маскировку одной командой, без ручного iptables. telemt — когда нужен REST API для бота ([[Zapret/mtproto/02-implementations|сравнение]]).
---
## Шаг 0. Подготовка
| Что | Как и почему |
|---|---|
| **VPS / подсеть** | Не «народный» хостинг (Selectel/Я.Облако — Сигнал 1 [[VLESS/dpi-tls-june-2026|сибирской схемы]]). Подбор — [[VPS/VPS\|VPS]]. |
| **Домен маскировки** | Популярный, с **одним раундом x25519**: `rutube.ru`, `ozon.ru`, `vk.com`, `yandex.ru`. **НЕ** `wb.ru` и др. HRR/secp521r1. |
| **Порт** | `443`. Любой другой подозрителен. |
| **Доступ** | root/sudo на сервере. |
> ⚠️ Домен вшивается в ссылку `tg://` и **неизменен** после раздачи. Выбирай один раз.
---
## Шаг 1. Установка
```bash
# 1. bootstrap mtbuddy (проверяет minisign-подпись + SHA-256)
curl -fsSL https://raw.githubusercontent.com/sleep3r/mtproto.zig/main/deploy/bootstrap.sh | sudo bash
# 2. установка прокси со всеми DPI-модулями
sudo mtbuddy install --port 443 --domain rutube.ru --yes
```
Что делает install (`--no-dpi` отключает п.5–6):
1. Качает готовый бинарь (определяет CPU: `x86_64_v3` → `x86_64` → `aarch64`)
2. Генерит секрет (или `--secret <32hex>`)
3. systemd-сервис `mtproto-proxy`
4. Открывает порт в `ufw`
5. **TCPMSS=88** iptables (дробит ClientHello) ← см. Шаг 4
6. **nginx-маскировка + nfqws-desync** ← см. Шаг 5
7. Печатает `tg://`-ссылку
Полезные флаги: `--secret`, `--user`, `--tcpmss <n>` (дефолт 88), `--no-tcpmss`, `--no-nfqws`, `--no-masking`, `--ipv6-hop`.
---
## Шаг 2. Конфиг `config.toml`
Большинство — уже дефолты; фиксируем ключевое явно (`/opt/mtproto-proxy/config.toml`):
```toml
[general]
use_middle_proxy = true # медиа на не-Premium + promo-теги
[server]
port = 443
# rate_limit_per_subnet = 0 # ОСТАВЬ 0 для мобильных юзеров РФ (carrier-NAT)
[censorship]
tls_domain = "rutube.ru" # single-round x25519, неизменен после раздачи
mask = true # форвард зондов на реальный домен (анти-probing)
fake_tls_only = true # реджектить палевный dd-транспорт
# desync = true # дефолт on — дробит ServerHello (1 байт + 3мс)
drs = true # мимикрия размеров TLS-записей под браузер
fast_mode = true
[metrics]
enabled = true # Prometheus /metrics (см. Шаг 6 — диагностика)
host = "127.0.0.1"
port = 9400
[access.users]
user1 = "00112233445566778899aabbccddeeff" # openssl rand -hex 16
```
После правки: `sudo systemctl restart mtproto-proxy` (SIGHUP-reload тоже есть, но при `workers>1` запрещён).
---
## Шаг 3. Что происходит на проводе (карта защит)
```
КЛИЕНТ (Telegram) ТСПУ СЕРВЕР (mtproto.zig)
│ ── ClientHello (почерк!) ──────► 👁 фингерпринт ──────► снимает fp в лог
│ │ (тут и блок #30733)
│ ◄──────────── ServerHello (дроблён desync) ──────────── mask/desync/drs
│ ── 64-байт MTProto-хендшейк ───► (если жив) ───────────► proxy → DC
```
| Слой | Что делает | Против чего |
|---|---|---|
| **TCPMSS=88** | клиент режет ClientHello на ~6 кусков | фингерпринт (DPI не пересобирает) |
| **nfqws desync** | fake-пакеты + TTL-split (S→C) | stateful DPI |
| **desync ServerHello** | 1 байт + 3мс + хвост | пассивные сигнатуры |
| **mask** | зонды → реальный `tls_domain` | active probing |
| **drs** | размеры записей как у браузера | статистика трафика |
> [!danger] Слабое звено, которое сервер НЕ чинит — фингерпринт клиента
> Почерк ClientHello (JA3/JA4) генерирует **приложение Telegram**, не сервер. По [tdesktop#30733](https://github.com/telegramdesktop/tdesktop/issues/30733): Desktop мимикрирует под **Chrome 134/macOS** (`t13d1516h2_8daaf6152771_d8a2da3f94cd`), а живой Chrome — 148 → пресет **протух**, и это маркер. Это **тот самый** блок, дающий `expected_64_got_0` ([[Zapret/mtproto/10-telemt-logs-dpi|разбор логов]]).
>
> Лечится только в самом 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 к клиенту:
>
> ```bash
> iptables -t mangle -A OUTPUT -p tcp --sport 443 \
> --tcp-flags SYN,ACK SYN,ACK -j TCPMSS --set-mss 96
> ```
>
> Конфиг telemt/mtproto.zig при этом трогать не надо — правило работает на уровне ядра.
Почему «на балансировщике»: clamp на бэкенде (где сидит сам прокси) **не дойдёт** до клиента, если балансировщик пере-устанавливает TCP. Правило должно быть на той коробке, что шлёт SYN-ACK клиенту.
> [!note] 88 или 96 — разница невелика
> Оба дают ~6 сегментов на ClientHello. mtproto.zig по умолчанию 88; совет из интернета — 96. Бери любое; если ставишь mtproto.zig напрямую (без отдельного балансировщика) — **TCPMSS уже стоит, дублировать руками не нужно**.
> [!tip] Это и есть «решение JA4» из teleproxy
> Когда говорят «в teleproxy решён JA4» — речь именно об этой фрагментации: teleproxy
> ставит `TCP_MAXSEG=256`, чтобы DPI не извлёк JA4 из первого пакета. JA4 при этом
> **не меняется** (его задаёт клиент). mtproto.zig делает то же самое и агрессивнее
> (MSS=88), так что **этот приём у тебя уже включён**. Почему это не «смена почерка»
> и где лежит настоящий фикс — [[mtproxy/ja4-sni-client-side|Кто может менять JA4/SNI]].
> [!warning] Дробление ≠ панацея
> 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»):
```bash
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-туннель.
```toml
[upstream]
type = "socks5" # "direct" | "tunnel" | "socks5" | "http"
[upstream.socks5]
host = "127.0.0.1"
port = 1080 # порт локального Xray/VLESS
# username = ""
# password = ""
```
Для туннеля вместо SOCKS5:
```toml
[upstream]
type = "tunnel"
[upstream.tunnel]
interfaces = ["awg0", "awg1"] # WireGuard/AmneziaWG, с авто-фолбэком
```
> [!important] Что это лечит, а что нет
> Egress-маршрут помогает, когда **дата-центры Telegram недоступны с твоего VPS**
> (заблокированы/режутся на пути proxy→DC), или нужен лишний хоп. Это путь
> **сервер→DC** — на **входящий** ClientHello (где JA4, который видит ТСПУ у
> клиента) он **не влияет**. Не путай: это про доступность DC, а не про обход
> детекта почерка. См. [[mtproxy/ja4-sni-client-side|Кто может менять JA4/SNI]].
---
## Шаг 6 (опционально). Лимит SYN-ACK — десинхрон + анти-залп
**На пальцах:** сервер иногда «роняет» свой ответ при установке соединения (SYN-ACK), клиент переспрашивает через секунду. От этого DPI сбивается со счёта и не опознаёт почерк клиента, а соединения идут не пачкой, а по одному в секунду. Спорный, но у людей **рабочий** приём.
Подробная механика (с аналогией), цена и **per-port** вариант (бюджет 1/сек на каждый порт, чтобы не калечить всех юзеров) — в [[Zapret/mtproto/10-telemt-logs-dpi#Лимит SYN-ACK — помогает или нет|разборе для telemt]] (для mtproto.zig всё идентично, только порт 443).
Коротко: ставить стоит, если блок держится после Шагов 4–5; брать **сразу per-port**; мониторить логи (Шаг 7), чтобы поймать адаптацию ТСПУ.
---
## Шаг 7. Диагностика — mtproto.zig сам показывает атаку DPI
### Фингерпринт клиента в логах
mtproto.zig **логирует почерк первых 16 ClientHello** (диагностический бюджет):
```bash
journalctl -u mtproto-proxy | grep "client ClientHello"
# client ClientHello [ciphers=... groups=... key_share=...] (we serve: ...)
```
> [!tip] Как связать с #30733
> Смотри `key_share` в логе. Свежий браузер шлёт **`X25519MLKEM768`** (post-quantum). Если твой клиент его **не** шлёт — он на старом пресете и попадает под детект из #30733. Это прямой способ увидеть «протух ли почерк» на своём трафике.
### Метрики close-reason — детектор начала блокировок
mtproto.zig отдаёт Prometheus-метрику с причинами закрытия — её **всплеск = ТСПУ начал резать**:
```bash
curl -s 127.0.0.1:9400/metrics | grep -E "close_reason|handshake_timeouts"
# mtproto_connection_close_reason_total{reason="tls_validation_failed"} ...
# mtproto_connection_close_reason_total{reason="replay_detected"} ... ← зонды Revisor
# mtproto_connection_close_reason_total{reason="bad_handshake"} ...
# mtproto_handshake_timeouts_total ... ← аналог expected_64_got_0
```
Рост `tls_validation_failed` / `replay_detected` / `handshake_timeouts` над фоном — это и есть сигнал, что цензор начал работать по тебе (так и задумано разработчиком). `replay_detected` отдельно ловит **active-probe зонды ТСПУ (Revisor)**.
Плюс есть веб-дашборд (порт 61208, Basic-auth, токен в `/opt/mtproto-proxy/monitor/dashboard.token`) — открывать **только через SSH-тоннель**.
---
## Когда всё-таки заблокировали — порядок действий
1. **Проверь логи/метрики** (Шаг 7): растёт ли `handshake_timeouts` / `tls_validation_failed`, и какой `key_share` у падающих клиентов.
2. **Подтюнь TTL nfqws** (Шаг 5) — частая причина, что desync «не достаёт» до ТСПУ.
3. **Снизь MSS** (`--tcpmss 80`) или добавь clamp на балансировщик (Шаг 4).
4. **Включи SYN-ACK per-port** (Шаг 6).
5. **Если рвётся путь до DC** (а не вход) — egress через Xray/SOCKS5 или туннель (Шаг 5.5).
6. **Смени узел/подсеть** (Сигнал 1) — если IP/диапазон попал под раздачу.
6. **Не дёргай настройки рефлекторно** под блоком — сам паттерн адаптации может усугубить.
7. **Запасной канал** — [[VLESS/dpi-tls-june-2026|VLESS+REALITY/XHTTP]] на отдельном узле.
---
## ✅ Чек-лист
- [ ] VPS на «чистой» подсети, домен single-round x25519, порт 443
- [ ] `mask = true`, `fake_tls_only = true`, `drs = true`
- [ ] `TCPMSS` активен (`iptables -t mangle -S OUTPUT | grep TCPMSS`) — или clamp на балансировщике
- [ ] nfqws запущен, **TTL подтюнен** (`systemctl status nfqws-mtproto`)
- [ ] `[metrics] enabled = true` + мониторинг `close_reason`/`handshake_timeouts`
- [ ] Проверил `key_share` клиента в логах (свежесть почерка, #30733)
- [ ] `rate_limit_per_subnet = 0` для мобильных юзеров РФ
- [ ] Готов запасной VLESS/XHTTP
---
## 📚 См. также
- [[mtproxy/ja4-sni-client-side|Кто может менять JA4/SNI]] — почему смена почерка/SNI возможна только на клиенте, что из мер ниже реально серверное
- [[mtproxy/mtproto-zig|MTProxy и mtproto.zig]] — теория: как работает и почему
- [[Zapret/mtproto/10-telemt-logs-dpi|Чтение логов и SYN-ACK лимит]] — детект DPI, per-port nft
- 🔗 [tdesktop#30733](https://github.com/telegramdesktop/tdesktop/issues/30733) — протухший фингерпринт
- [[Zapret/mtproto/05-censorship|ТСПУ: каскад детекции]]
- [[Zapret/mtproto/02-implementations|5 реализаций MTProxy]]
- [[VLESS/dpi-tls-june-2026|Сибирская схема DPI]]
- [[VPS/VPS|Выбор VPS]]