Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mtproto-reality-stack

MTProto, VLESS+Reality и панель управления — на одном порту 443, с маскировкой под собственный работающий сайт.


License: MIT Ubuntu 26.04 Xray-core nftables shellcheck

Архитектура · Установка · Диагностика · Благодарности · English


Проблема

Есть известный фикс для MTProto-прокси: SYN rate limit на nftables. Он лечит бесконечные переподключения клиентов Telegram, которые начались, когда провайдерская фильтрация стала реагировать на паттерн реконнектов. Пока прокси на сервере один — фикс ставится в одну строку и работает.

Сложность начинается, когда на тот же сервер и тот же порт 443 хочется повесить ещё и VPN за nginx с SNI-роутингом. Фикс оказывается некуда поставить.

Вариант А — лимит на :443, перед nginx. В момент прихода SYN никакого SNI ещё не существует: TLS даже не начался. Ядро не может отличить MTProto-соединение от VPN-соединения и режет всё подряд. VPN с его совсем другим профилем трафика попадает под лимит, рассчитанный на MTProto, и отваливается.

Вариант Б — лимит на локальный порт, за nginx. Не работает по другой причине. nginx терминирует TCP-соединение клиента и открывает к бэкенду своё, новое. Исходный SYN до локального порта не доезжает вовсе, а источником всех соединений становится 127.0.0.1. Правило «не больше N с одного адреса» теряет смысл: с точки зрения ядра все клиенты слились в один localhost.

Развязка

В ядре, до nginx, делать не лимит, а классификацию.

redirect в nftables — это DNAT, а не проксирование. Пакету переписывается порт назначения, но он остаётся тем же самым пакетом: исходный SYN клиента сохраняется целиком. По отпечатку TCP SYN (JA4T) iOS-трафик уводится на отдельный порт, где минует гейт HAProxy — тот самый, который его душил. Всё остальное идёт через nginx, и уже там HAProxy применяет лимит, видя настоящий IP клиента через PROXY protocol.

Лимит в итоге живёт на ветке MTProto, а не на порту целиком. VPN его не касается.

Побочно из этой же схемы получается маскировка: неаутентифицированные соединения отдаются на собственный работающий сайт с настоящим сертификатом Let's Encrypt. Не «прокси, притворяющийся сайтом», а сервер, который при любой проверке отдаёт настоящий сайт.

Схема

flowchart LR
    C["Клиент<br/>всегда :443"] --> J{"nftables<br/>отпечаток TCP SYN"}
    J -->|"iOS → :8443"| N["nginx<br/>слушает оба порта<br/>разбирает SNI"]
    J -->|"остальные → :443"| N
    N -->|"MTProto с :443"| H["HAProxy<br/>лимит 54 за 60 сек"]
    H --> T["telemt · MTProto"]
    N -->|"MTProto с :8443"| T
    N -->|"VPN"| X["Xray · Reality"]
    N -->|"панель"| P["3x-ui"]
    N -->|"SNI не опознан"| D["Разрыв соединения"]
    T -.->|"нет секрета"| F["Заглушка — настоящий сайт"]
    X -.->|"не аутентифицирован"| F
Loading

Клиент всегда подключается на :443 — :8443 появляется только как результат redirect'а внутри ядра (nftables), а не как отдельная точка входа. Редирект существует, чтобы увести iOS-клиентов из-под лимита HAProxy, который их душил; на самом iOS сейчас лимита нет. Лимит 54 соединения за 60 секунд в HAProxy применяется только к не-iOS MTProto-трафику.

Подробно — 01-architecture.md.

Установка

Читать по порядку — каждый шаг опирается на предыдущий.

Шаг О чём
01 Архитектура развязка целиком: JA4T, SNI-роутер, self-steal
02 Установка сервер, система, docker, nginx, файрвол
03 Сертификаты wildcard через DNS-01, хук продления
04 Сервисы заглушки, SNI-роутер, MTProto, JA4T-сплит
05 Диагностика и грабли разобранные ошибки

Скрипты

Только читают состояние — ничего не меняют и не перезапускают.

sudo ./scripts/check-stack.sh                              # все слои разом
sudo ./scripts/diagnose-reality.sh 200 plug2.example.com   # разбор сессий по логу

Конфиги

В configs/ — шаблоны, повторяющие структуру путей на сервере. Все реальные значения заменены плейсхолдерами:

Плейсхолдер Чем заменить
example.com ваш домен
plug1.example.com · plug2.example.com ваши поддомены-заглушки
dashboard.example.com поддомен панели
YOUR_SERVER_IP IP сервера
<PANEL_PATH> секретный префикс URL панели
<MTPROTO_SECRET> openssl rand -hex 16

Лицензия

MIT

About

MTProto, VLESS+Reality и панель на одном порту 443: JA4T-сплит на nftables, self-steal маскировка, измеренные требования пост-квантового Reality

Topics

Resources

Stars

17 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages