MTProxy + WEB + сайт на одном порту с помощью telEgo
- суббота, 29 августа 2026 г. в 00:00:11
telEgo - шустрый Telegram прокси на Go, в последней версии которого появилась поддержка всех четырёх WEB протоколов.
Telegram Desktop теперь умеет подключаться через WEB proxy. Снаружи такое соединение выглядит как работа обычного сайта: клиент открывает HTTPS-страницу в браузере, а она становится транспортом между Telegram Desktop и прокси.
У тех, кто уже держит свой MTProxy, сразу возникает практический вопрос: что делать с портом 443? Его нельзя одновременно отдать MTProxy и Nginx. Переносить прокси на необычный порт тоже не хочется.
В telEgo оба варианта подключения работают через один публичный порт 443. Обычные MTProxy-ссылки ee и dd продолжают работать, а WEB proxy добавляется без замены секретов. В этой статье разберём схему и поднимем её с помощью Docker Compose.
telEgo — реализация Telegram MTProxy на Go. Сетевой движок построен на gnet, поэтому основные соединения и WEB listener работают через epoll и kqueue.
Прокси поддерживает:
FakeTLS с секретами ee;
Obfuscated2 с секретами dd;
TLS fronting и передачу неподходящих соединений на настоящий сайт;
несколько пользователей и ограничения соединений;
метрики Prometheus;
четыре транспорта Telegram WEB proxy.
В текущей версии доступны следующие WEB carrier modes:
| Как передаются данные | Что требуется от Nginx |
|---|---|---|
| Один последовательный канал на | HTTP/1.1 до внутреннего listener |
| Отдельный HTTP-канал на каждый Telegram stream | HTTP/2 на публичном TLS listener |
| Один мультиплексированный WebSocket на WEB-сессию | Заголовки |
| Отдельный WebSocket на каждый Telegram stream | Заголовки |
Строго говоря, это четыре транспорта одного WEB-протокола. В конфигурации telEgo они выбираются параметром carrier.
Если параметр не задан, используется https. Для первой установки в примере выбран https-lanes. После проверки можно переключиться на другой режим и сравнить его на своей сети.
Схема выглядит так:
Интернет :443 | v telEgo MTProxy :443 |-- правильный MTProxy handshake ------> Telegram DC | `-- обычный TLS ------------------------> Nginx TLS :8443 | `-- HTTP --> telEgo WEB :8080 | `-- MTProxy --> Telegram DC
Публичный порт 443 принадлежит только telEgo. Программа распознаёт MTProxy handshake и обслуживает такое соединение сама. Обычный TLS она передаёт в Nginx, не завершая TLS-сессию.
Nginx принимает это соединение на приватном порту 8443, использует настоящий сертификат домена и передаёт HTTP-запрос во внутренний WEB listener telEgo на порту 8080. WEB stream после проверки возвращается во внутренний MTProxy backend и уходит к Telegram DC.
Получается небольшой цикл, но наружу торчит только один TLS-порт. Порты 8080, 8443 и 8444 доступны только внутри хоста или Docker-сети.
Сайт из nginx при этом продолжает прозрачно отдаваться браузерам. telEgo возвращает Nginx внутренний статус 418 для обычного запроса, и Nginx отправляет запрос в сайт-заглушку или ваш существующий upstream. Для запроса, похожего на WEB carrier, но не прошедшего аутентификацию, используется статус 419. Перед передачей такого запроса на сайт Nginx удаляет секреты, cookies, Authorization и служебные заголовки.
Для установки нужны:
VPS с публичными портами 80 и 443.
Домен или поддомен с A-записью на адрес VPS.
Docker с Compose.
Свободный порт 80 на время первого получения сертификата.
Если на сервере уже работает Nginx, не запускайте второй экземпляр вслепую. Возьмите server-блоки и upstream из готового примера и добавьте их в существующую конфигурацию. Внешний Nginx не должен занимать порт 443: публичный 443 должен слушать telEgo, а TLS server Nginx — приватный порт 8443 с PROXY protocol v2.
Склонируем репозиторий и откроем готовый пример:
git clone https://github.com/Scratch-net/telego.git cd telego/examples/web-proxy
В примере используются три основных файла:
docker-compose.yml — контейнеры и приватная сеть;
telego.toml — MTProxy, TLS fronting и WEB proxy;
nginx/nginx.conf — TLS, WEB ingress и обычный сайт.
Замените proxy.example.com на свой домен в telego.toml, nginx/nginx.conf и docker-compose.yml.
Генератор можно вызвать прямо из образа Docker Hub:
docker run --rm scratchnet/telego:latest \ generate proxy.example.com --web-host proxy.example.com
Первая позиция — домен для FakeTLS. Значение --web-host — публичный домен WEB proxy. Для простой установки это один и тот же домен.
Команда напечатает базовый 16-байтовый секрет, ссылки MTProxy ee и dd, а также WEB-ссылки. Добавьте базовый секрет без префикса в telego.toml:
[secrets] alice = "0123456789abcdef0123456789abcdef"
Для WEB proxy не нужен отдельный секрет. telEgo создаёт обычную и dd WEB-ссылки из того же базового значения. Не добавляйте в конфигурацию отдельный секрет с именем desktop-dd.
Минимальная конфигурация из примера:
[general] bind-to = "0.0.0.0:443" [secrets] alice = "0123456789abcdef0123456789abcdef" [tls-fronting] mask-host = "proxy.example.com" cert-host = "proxy.example.com" cert-port = 8444 splice-host = "nginx" splice-port = 8443 splice-proxy-protocol = 2 [web-proxy] enabled = true hostname = "proxy.example.com" carrier = "https-lanes" bind-to = "0.0.0.0:8080" backend = "127.0.0.1:443" trusted-proxy-cidrs = ["172.28.0.2/32"]
Адреса здесь привязаны к приватной Docker-сети из примера. Не копируйте их в установку без Docker. Для Nginx и telEgo на одном хосте используйте loopback-адреса из полной документации.
Первый сертификат получаем standalone-проверкой. В этот момент порт 80 должен быть свободен:
mkdir -p certbot/conf certbot/lib certbot/www docker run --rm -p 80:80 \ -v "$PWD/certbot/conf:/etc/letsencrypt" \ -v "$PWD/certbot/lib:/var/lib/letsencrypt" \ certbot/certbot certonly --standalone --non-interactive --agree-tos \ --email admin@example.com -d proxy.example.com
Замените адрес почты и домен. Команда должна завершиться до запуска Nginx.
Сначала проверим Compose-файл и отдельно запустим Nginx:
docker compose config --quiet docker compose up -d nginx docker compose exec -T nginx nginx -t
Если проверка прошла, запускаем весь стек:
docker compose up -d docker compose ps docker compose logs telego
В журнале должна появиться запись WEB proxy started. У контейнера telEgo опубликован только порт 443, у Nginx — только порт 80. Остальные порты доступны внутри сети telego-private.
Команда запуска telEgo содержит флаг -l, поэтому ссылки будут также напечатаны при старте:
docker compose logs telego | grep '_link='
WEB-ссылки имеют такой вид:
tg://webproxy?server=proxy.example.com&secret=0123456789abcdef0123456789abcdef https://t.me/webproxy?server=proxy.example.com&secret=0123456789abcdef0123456789abcdef
В режиме websocket страница открывает одно соединение wss://proxy.example.com/api/v1/ws. В websocket-lanes создаётся отдельное соединение для каждого потока. В режимах https используются fetch и long polling.
Секреты и MTProxy-ссылки менять не требуется. Порядок миграции такой:
Добавьте секцию [web-proxy].
Настройте Nginx на приватных портах 8443 и 8444.
Добавьте upstream на приватный WEB listener 8080.
Включите HTTP/2 на публичном TLS listener, если выбрали https-lanes.
Передайте заголовки Upgrade и Connection, если выбрали WebSocket.
Проверьте конфигурацию командой nginx -t.
Перезапустите telEgo и перезагрузите Nginx.
Запустите telEgo с флагом -l и добавьте напечатанную WEB-ссылку в Telegram Desktop.
Старые ссылки tg://proxy с префиксами ee и dd продолжат работать через тот же публичный listener.
В примере Nginx обслуживает /.well-known/acme-challenge/ из каталога certbot/www. Скрипт renew-certificate.sh вызывает certbot renew, проверяет Nginx и перезагружает его только после успешного продления.
Первую проверку выполните вручную:
./renew-certificate.sh
В каталоге systemd есть готовые service и timer. Они рассчитаны на установку примера в /opt/telego/examples/web-proxy:
sudo install -m 0644 systemd/telego-cert-renew.service /etc/systemd/system/ sudo install -m 0644 systemd/telego-cert-renew.timer /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now telego-cert-renew.timer sudo systemctl start telego-cert-renew.service
Если файлы находятся в другом каталоге, сначала измените путь в telego-cert-renew.service.
Не публикуйте WEB listener 8080 в интернет. К нему должен обращаться только Nginx.
Не добавляйте $http_sec_websocket_protocol в access log Nginx. В режиме WebSocket заголовок Sec-WebSocket-Protocol содержит bearer credential WEB proxy.
Nginx должен передавать реальный заголовок Host. telEgo сверяет его с [web-proxy].hostname. Не заменяйте $http_host константой в WEB ingress.
Публичный Nginx может работать по HTTP/2, но соединение Nginx с WEB listener telEgo должно оставаться HTTP/1.1.
Сейчас WEB proxy предназначен для Telegram Desktop. Наличие WEB-ссылки само по себе не добавляет поддержку в клиенты, которые не реализуют этот транспорт.
WEB proxy выключается независимо от MTProxy. Сначала верните прежний маршрут сайта в Nginx и проверьте конфигурацию:
nginx -t nginx -s reload
Затем установите enabled = false в секции [web-proxy] и перезапустите telEgo. Существующие секреты, ee-ссылки и dd-ссылки при этом не изменятся.
Порт 443 не нужно делить между двумя публичными процессами. telEgo остаётся первой точкой входа, самостоятельно обслуживает MTProxy и передаёт обычный TLS в Nginx. Nginx завершает настоящий TLS, обслуживает сайт и возвращает WEB carrier во внутренний listener telEgo.
В результате на одном домене и одном публичном порту работают:
обычный сайт;
MTProxy FakeTLS ee;
MTProxy Obfuscated2 dd;
Telegram WEB proxy в одном из четырёх режимов.
Исходный код: github.com/Scratch-net/telego
Полная инструкция по WEB proxy: docs/web-proxy.md
Образ Docker Hub: scratchnet/telego