MTProto-прокси для Telegram на своём сервере

MTProto-прокси для Telegram на своём сервере: ставим mtg v2 с fake-TLS и своим доменом, раздаём ссылки, масштабируем и разбираем типичные сбои подключения.

Актуально на сентябрь 2026 года: mtg 2.2.8, telemt 3.5.9. В России прокси сейчас в гонке с блокировками: с апреля ТСПУ несколько раз менял способ находить fake-TLS, а автор mtg в июне посоветовал всем переходить на VPN. Прокси удобен тем, что человеку ничего не нужно ставить, но держите запасной путь, например VLESS Reality.

Что понадобится

  • VPS ForestsNet Cloud в Нидерландах или Германии на Ubuntu 22.04/24.04 или Debian 12. Адреса наших серверов ежедневно проверяются на блокировки ТСПУ.
  • Домен или поддомен с A-записью на IP сервера — зачем, объясняем в шаге 1. Как её завести — «Как привязать домен к серверу».
  • Доступ по SSH под root или пользователем с sudo — «Консоль VNC и первое подключение».
  • Запас по трафику: всё, что клиенты скачивают через прокси, для сервера исходящий трафик, а в пакет входит именно он.

Как устроен MTProto-прокси и чем он отличается от VPN

Клиент Telegram подключается к вашему серверу, а тот пересылает трафик в дата-центры Telegram. Переписка остаётся зашифрованной протоколом MTProto: владелец прокси видит IP-адреса и объём трафика, но не содержимое.

  • Работает только Telegram. Браузер и другие приложения идут мимо.
  • Клиенту ничего не нужно ставить. Поддержка встроена в официальные приложения: человек открывает ссылку tg://proxy?… или https://t.me/proxy?…, и Telegram предлагает подключиться.
  • Нет учётных записей. Доступ даёт секрет в ссылке: у кого ссылка, тот и пользуется.
  • Звонки идут мимо прокси — это ограничение самого Telegram.

Типы секретов

  • Обычный — 16 случайных байт, 32 hex-символа. Поток с первого байта похож на шум.
  • Secure — dd перед секретом: к шуму добавлена случайная добивка, скрывающая размеры пакетов.
  • Fake-TLS — ee, секрет и домен в hex: соединение начинается как TLS 1.3 с именем сайта в SNI и похоже на обычный HTTPS.

Сегодня имеет смысл только fake-TLS: поток, похожий на шум, выделяется сам по себе, и такие протоколы ТСПУ режет давно, Shadowsocks — с осени 2023 года. mtg v2 принимает только ee-секреты.

Какую реализацию выбрать

  • mtg v2 (Go): только fake-TLS, один секрет на процесс, domain fronting, подстройка TLS-записей под настоящий сайт, защита от повторов, метрики Prometheus, без спонсорского канала. Простой и предсказуемый — его и ставим.
  • telemt (Rust): много пользователей в процессе с лимитами, квотами и сроками, API, спонсорский канал. Выбор для раздачи большому числу людей.
  • Официальный MTProxy (C): единственный релиз — 2018 года, образ Docker устарел. Для новых установок не подходит.

Живы и другие: teleproxy (форк официального), mtproto.zig, alexbers/mtprotoproxy, seriyps/mtproto_proxy.

Шаг 1. Выберите домен и поднимите сайт-прикрытие

Имя из секрета уходит в SNI открытым текстом, и DPI видит пару «IP сервера — домен». Проверить её просто: разрезолвить домен и сравнить адреса, так что прокси в Нидерландах под видом microsoft.com выдаёт себя сразу. Автор mtg в рекомендациях от марта 2026 года пишет прямо: сервер должен быть настоящим сайтом, за которым прячется mtg.

  • Домен ваш, A-запись указывает на IP сервера, проксирование Cloudflare выключено.
  • На сервере работает сайт с сертификатом Let's Encrypt и TLS 1.3. Всех, кто пришёл без правильного секрета — браузер, сканер, зонд DPI, — mtg отправит на него.
  • Имя нейтральное, без proxy, mtproto, tg. На сайте — пара правдоподобных страниц.
  • Домен не заблокирован в стране клиентов: DPI фильтрует и по SNI.

Выдавать прокси за чужой сайт на серверах ForestsNet Cloud нельзя — ни в домене секрета, ни в domain fronting, ни в сертификате: это запрещают «Условия использования».

Дальше в примерах домен www.example.com и IP 203.0.113.10. Порт 443 займёт mtg, поэтому nginx слушает 80 для выпуска сертификата и 127.0.0.1:8443 для сайта. Страницы положите в /var/www/site:

sudo apt update && sudo apt install -y nginx certbot
sudo mkdir -p /var/www/site

Файл /etc/nginx/sites-available/site, пока только с портом 80:

server {
    listen 80;
    server_name www.example.com;
    root /var/www/site;
    location /.well-known/acme-challenge/ { }
    location / { return 301 https://$host$request_uri; }
}

Включите сайт и получите сертификат. Плагин --nginx не подходит: он допишет listen 443 и столкнётся с mtg.

sudo ln -s /etc/nginx/sites-available/site /etc/nginx/sites-enabled/site
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
sudo certbot certonly --webroot -w /var/www/site -d www.example.com --deploy-hook "systemctl reload nginx"

Допишите в тот же файл HTTPS-сервер и снова выполните sudo nginx -t && sudo systemctl reload nginx:

server {
    listen 127.0.0.1:8443 ssl;
    server_name www.example.com;
    ssl_certificate     /etc/letsencrypt/live/www.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    root /var/www/site;
}

Подробнее про certbot — «Бесплатный SSL с Let's Encrypt».

Шаг 2. Установите mtg

Скачайте релиз, сверьте контрольную сумму, заведите пользователя и каталог конфигов:

MTG=2.2.8
cd /tmp
curl -fsSLO https://github.com/9seconds/mtg/releases/download/v$MTG/mtg-$MTG-linux-amd64.tar.gz
curl -fsSLO https://github.com/9seconds/mtg/releases/download/v$MTG/mtg-$MTG-checksums.txt
sha256sum --ignore-missing -c mtg-$MTG-checksums.txt
tar -xzf mtg-$MTG-linux-amd64.tar.gz
sudo install -m 755 mtg-$MTG-linux-amd64/mtg /usr/local/bin/mtg
mtg --version
sudo useradd --system --no-create-home --shell /usr/sbin/nologin mtg
sudo mkdir -p /etc/mtg

Шаг 3. Сгенерируйте секрет и напишите конфиг

mtg generate-secret --hex www.example.com

Команда выведет ee, 32 hex-символа и домен в hex — это и пароль клиентов, и ключ прокси. Создайте /etc/mtg/main.toml:

secret = "ee…"
bind-to = "0.0.0.0:443"
public-ipv4 = "203.0.113.10"
prefer-ip = "prefer-ipv4"
concurrency = 8192

[domain-fronting]
ip = "127.0.0.1"
port = 8443

[stats.prometheus]
enabled = true
bind-to = "127.0.0.1:3129"

Выполните sudo chown root:mtg /etc/mtg/main.toml && sudo chmod 640 /etc/mtg/main.toml.

  • public-ipv4 — адрес для ссылок и проверок, иначе mtg спросит его у внешнего сервиса.
  • prefer-ip — по умолчанию mtg предпочитает IPv6. Без рабочего IPv6 оставьте prefer-ipv4.
  • concurrency — предел одновременных соединений, лишние отбрасываются.

Не копируйте целиком example.config.toml из архива: в нём debug = true.

Domain fronting: что делает и когда настраивать

В mtg он работает всегда. Если соединение не прошло проверку — неверный секрет, повтор перехваченного рукопожатия, устаревшая метка времени или просто браузер, — mtg соединяет его с настоящим сайтом и передаёт байты как есть. Проверяющий получает ответ сайта байт в байт.

По умолчанию mtg резолвит домен из секрета и идёт на его порт 443. Секция [domain-fronting] нужна, когда так нельзя: домен смотрит на этот же сервер (без неё mtg пойдёт сам к себе и зациклится), DNS-запрос к домену блокируется или перед mtg стоит балансировщик.

Важно: в ветке master параметр ip в [domain-fronting] уже переименован в host, а старое имя будет игнорироваться. После обновления на версию новее 2.2.8 запустите mtg doctor: он показывает устаревшие параметры.

Шаг 4. Запустите и проверьте

Шаблонный юнит позволит потом добавлять экземпляры без переделки — /etc/systemd/system/[email protected]:

[Unit]
Description=mtg MTProto proxy (%i)
After=network-online.target
Wants=network-online.target

[Service]
User=mtg
ExecStart=/usr/local/bin/mtg run /etc/mtg/%i.toml
Restart=always
RestartSec=3
LimitNOFILE=65536
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now mtg@main
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo mtg doctor /etc/mtg/main.toml

Порт 80 нужен для продления сертификата. Про файрвол — «Файрвол ufw: порты».

mtg doctor проверяет устаревшие параметры, часы, доступность дата-центров Telegram и сайта-прикрытия, совпадение DNS домена с IP сервера — все пункты должны пройти. Затем откройте https://www.example.com в браузере: должен открыться ваш сайт. Так сервер видит любой, у кого нет секрета.

Вариант с Docker

docker run --rm nineseconds/mtg:2.2.8 generate-secret --hex www.example.com
docker run -d --name mtg --restart unless-stopped --network host \
  -v /etc/mtg/main.toml:/config.toml:ro nineseconds/mtg:2.2.8
docker exec mtg /mtg doctor /config.toml

Тег фиксируйте версией, а не latest. --network host здесь по делу: 127.0.0.1 в конфиге указывает на nginx хоста, а правила ufw действуют — порты, опубликованные через -p, Docker проводит мимо них. Пользователь mtg не нужен, конфигу хватит chmod 600. Установка Docker — «Docker и Docker Compose».

Шаг 5. Раздайте ссылку и QR-код

sudo mtg access /etc/mtg/main.toml

В ответе есть tg_url и tme_url. Ссылка tg://proxy?server=…&port=443&secret=… сразу открывает приложение, https://t.me/proxy?… кликабельна в любом мессенджере и в почте. Секрет по умолчанию в base64, с флагом -x — в hex, клиенты понимают оба.

  • Подставьте домен вместо IP в параметр server: при блокировке вы смените IP и A-запись, а ссылки продолжат работать. TTL записи держите коротким.
  • Дайте две-три ссылки на разные адреса. Telegram Desktop с апреля 2026 года умеет сам переключаться между прокси.
  • QR-код делайте локально, командами ниже: поля tg_qrcode и tme_qrcode ведут на сторонний сервис, и ссылка с секретом уйдёт туда.
  • Не публикуйте ссылку в открытых каналах. Публичные прокси долго не живут: 19 мая 2026 года в Москве разом перестали работать все прокси из одного популярного Telegram-канала. Автор mtg советует держать прокси для узкого круга.
sudo apt install -y qrencode
qrencode -t ansiutf8 'https://t.me/proxy?server=www.example.com&port=443&secret=…'
qrencode -o proxy.png 'https://t.me/proxy?server=www.example.com&port=443&secret=…'

Шаг 6. Несколько экземпляров и нагрузка

По README один процесс mtg держит порядка 10–20 тысяч одновременных соединений. Считайте соединения, а не людей: клиент Telegram открывает их несколько, к разным дата-центрам и отдельно под файлы. Упирается всё в память: в трекере mtg оценивали до 120 КБ на соединение, в 2.2.5 расход снизили — смотрите на RSS процесса под своей нагрузкой. Все ядра процесс на Go занимает сам.

Экземпляры нужны для другого. У mtg один секрет на процесс, значит разные группы людей — разные экземпляры: утёкшую ссылку одной группы вы замените, не трогая остальных (много секретов в одном процессе умеет форк dolonet/mtg-multi). Мы держим по восемь экземпляров на узле. Как их разнести:

  1. Разные IP, у каждого свой 443: bind-to = "203.0.113.11:443". Лучший вариант: блокировка адреса задевает одну группу.
  2. Один IP, разные порты. Проще всего, но в гостевых и корпоративных сетях часто открыт только 443.
  3. Один IP и общий 443. Перед экземплярами стоит маршрутизатор по SNI: у каждого свой поддомен, nginx читает имя из ClientHello и отдаёт соединение нужному mtg, всё незнакомое — сайту. Ту же схему на HAProxy автор mtg выложил в contrib/sni-router.

Для третьего варианта поставьте libnginx-mod-stream и допишите в конец /etc/nginx/nginx.conf, вне блока http:

stream {
    map $ssl_preread_server_name $mtg_backend {
        a.example.com  127.0.0.1:4431;
        b.example.com  127.0.0.1:4432;
        default        127.0.0.1:8443;
    }
    server {
        listen 443;
        ssl_preread on;
        proxy_pass $mtg_backend;
        proxy_protocol on;
    }
}

Каждому экземпляру, включая main, — свой файл, например /etc/mtg/a.toml: секрет для a.example.com, bind-to = "127.0.0.1:4431", proxy-protocol-listener = true и proxy-protocol = true в [domain-fronting]. Сайт переведите на listen 127.0.0.1:8443 ssl proxy_protocol;, поддомены добавьте в сертификат через -d. Запуск — systemctl enable --now mtg@a mtg@b, ссылки — mtg access -p 443 /etc/mtg/a.toml.

Важно: PROXY protocol включается во всех звеньях сразу или нигде. Без него mtg увидит всех клиентов с адреса 127.0.0.1, а он входит в блок-лист firehol_level1, включённый по умолчанию, — каждое подключение получит отказ.

Ядро и мониторинг

mtg 2.2.8 сам пытается включить BBR, но процессу без root доступны только разрешённые системой алгоритмы. Включите BBR глобально — это ускоряет медиа в мобильных сетях с потерями. Файл /etc/sysctl.d/90-mtg.conf, затем sudo sysctl --system:

net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

С ufw каждое соединение попадает в conntrack: на десятках тысяч соединений сравнивайте nf_conntrack_count с nf_conntrack_max. Общая методика — «Высокая нагрузка на сервер».

Метрики Prometheus — на 127.0.0.1:3129, быстрый взгляд: curl -s 127.0.0.1:3129/ | grep '^mtg_'. Что держать на графиках:

  • mtg_client_connections — соединения клиентов: резкий провал при живом сервисе намекает на блокировку IP.
  • mtg_concurrency_limited — отказы по лимиту: поднимайте concurrency или добавляйте экземпляр.
  • mtg_domain_fronting и mtg_replay_attacks — уход на сайт-прикрытие и пойманные повторы: всплески означают сканирование или клиентов со старым секретом.
Из нашей эксплуатации: перезапускайте экземпляры по одному — клиенты возвращаются одну-две минуты, раньше делать выводы рано. Следите за памятью: у некоторых реализаций она неделями растёт, и еженедельный перезапуск по таймеру — дешёвая страховка. Не держите подробные логи на нагруженном узле: на восьми экземплярах журнал у нас рос на семь тысяч строк в минуту.

Спонсорский канал через @MTProxybot

@MTProxybot — официальный бот Telegram для регистрации прокси. Он выдаёт тег (ad tag): всем, кто подключён через прокси с тегом, Telegram показывает в списке чатов ваш канал с пометкой спонсора.

  1. В боте — /newproxy, затем 203.0.113.10:443 и секрет: 32 hex-символа без ee и домена.
  2. Бот вернёт тег. В telemt он прописывается в ad_tag вместе с use_middle_proxy = true, в официальном MTProxy — ключом -P.
  3. В /myproxies выберите прокси, нажмите Set promotion и пришлите ссылку на публичный канал — приватный не принимается. Изменения доходят примерно за час.

Ссылку, которую сгенерирует бот, не раздавайте: fake-TLS-части в ней нет. Плюсы тега — статистика и продвижение своего канала, минусы весомее:

  • Тег работает только через промежуточные серверы Telegram (middle proxy): лишнее звено, отправка файлов обычно медленнее.
  • mtg v2 тег не поддерживает, нужен telemt или официальный MTProxy.
  • В Android канал из списка чатов не убрать, а раскрученный прокси публичен — такие блокируют быстрее.

Диагностика

По умолчанию mtg пишет в журнал только предупреждения и ошибки. Чтобы увидеть причину отказа, временно включите debug = true, перезапустите экземпляр и смотрите journalctl -u mtg@main -f.

«Подключение…» бесконечно.

  • Сервис не слушает порт или его закрыл файрвол: sudo ss -tlnp | grep ':443', systemctl status mtg@main, sudo ufw status.
  • В журнале cannot read client hello. Причина incorrect client random — в ссылке чужой или старый секрет, timestamp … is too old — расходятся часы сервера (допуск 5 секунд), ip was blacklisted — адрес клиента в блок-листе.
  • Пакеты не доходят: запустите sudo tcpdump -ni any 'tcp dst port 443 and tcp[tcpflags] & tcp-syn != 0' и подключитесь с телефона. Если из российских сетей SYN не приходит, а из других приходит, адрес заблокирован.
  • Старая версия Telegram. 1 апреля 2026 года ТСПУ начал узнавать fake-TLS по ошибке в ClientHello официальных клиентов; за неделю её исправили, в августе Telegram Desktop 7.1 снова обновил отпечаток. Обновите приложение.
  • mtg старше 2.2.8. Раньше он отвечал в ServerHello GREASE-значением, которого не бывает у настоящих TLS-серверов, и DPI отбрасывал такие ответы.

Порт пропадает на несколько минут, чаще у Android и Desktop.

При подключении клиент Telegram открывает около пяти TLS-соединений почти одновременно, браузер — одно-два. С июня 2026 года ТСПУ на части сетей отвечает на такой всплеск временной блокировкой IP и порта прокси. Помогает лимит SYN с одного адреса: лишние попытки получают RST и растягиваются во времени. В telemt это параметр synlimit, для mtg добавьте правило ниже в /etc/ufw/before.rules перед строкой COMMIT и выполните sudo ufw reload. Значения — как у synlimit по умолчанию.

-A ufw-before-input -p tcp --dport 443 --syn -m hashlimit --hashlimit-name mtg-syn --hashlimit-mode srcip --hashlimit-above 48/minute --hashlimit-burst 24 -j REJECT --reject-with tcp-reset

Работает на Wi-Fi, но не на мобильном.

  • Мобильные сети фильтруют иначе, чем проводные, причём по-разному у операторов и даже у отдельных сот. Сравните с другой SIM-картой.
  • Режим белых списков: при ограничениях в регионах, а весной 2026 года и в Москве, мобильный интернет пускает только к ресурсам из утверждённого перечня. Зарубежного прокси в нём нет, сервер тут бессилен.

Отваливается через несколько минут или после блокировки экрана.

  • mtg старше 2.2.8. NAT мобильного оператора забывает простаивающее соединение через 5–30 минут, и после сна телефона Telegram висел на «Подключение к прокси», пока прокси не переключишь. В 2.2.8 появились TCP keepalive ([network.keep-alive]) и таймаут простоя 5 минут.
  • Между клиентом и mtg стоит L4-прокси с коротким таймаутом. Клиент шлёт служебный пинг примерно раз в минуту, поэтому таймаут короче пары минут рвёт живые сессии. У nginx stream proxy_timeout по умолчанию 10 минут — не уменьшайте.
  • Переполнена таблица conntrack: dmesg | grep conntrack.

Сообщения идут, а фото и видео грузятся медленно или не грузятся.

  • Фильтр «16 КБ»: с июня 2025 года ТСПУ на части сетей подвешивает соединения к зарубежным хостингам примерно после 16 КБ данных. Положите на сайт файл на несколько мегабайт и скачайте его из российской сети. Если загрузка замирает в самом начале, поможет только другой адрес или другая сеть.
  • Недоступен DC 203 — сеть доставки медиа Telegram. Его проверяет mtg doctor.
  • Telegram штрафует исходящий IP сервера. Мы ловили такое на своём VPN-узле: с одного адреса до части дата-центров Telegram молча терялось около 90% SYN, а с соседнего всё работало. Замерьте время соединения командой ниже: 1 или 3 секунды означают повторы SYN. Поможет новый IP или второй адрес сервера в маршруте к сетям Telegram через параметр src.
  • Трафик идёт через промежуточные серверы Telegram, как при спонсорском канале, или не включён BBR.
for ip in 149.154.175.50 149.154.167.51 149.154.175.100 149.154.167.91 149.154.171.5; do
  curl -so /dev/null -w "$ip %{time_connect}s\n" --max-time 5 http://$ip:443/
done

Безопасность и обслуживание

  • Доступ к серверу. Наружу открыты только SSH, 80 и 443, вход по SSH — по ключам: «Усиление SSH», «Чеклист базовой защиты VPS».
  • Ротация секрета — когда ссылка утекла или подключений заметно больше, чем людей, которым вы её давали. Сгенерируйте новый секрет с тем же доменом, замените его в конфиге, выполните sudo systemctl restart mtg@main и разошлите новую ссылку: старая перестанет работать сразу.
  • Смена IP при блокировке: впишите новый адрес в A-запись и public-ipv4, ссылки с доменом переживут переезд. Если адреса блокируют один за другим, автор mtg советует каскад: mtg на VPS в России, а к Telegram он ходит через туннель до зарубежного сервера — sing-box поднимает локальный SOCKS5, mtg подключается к нему параметром proxies.
  • Обновление. Фиксируйте версию, читайте заметки к релизу, после обновления запускайте mtg doctor и перезапускайте экземпляры по одному.

Источники