MTProxy + WEB на одном порту с помощью telEgo

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
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. После проверки можно переключиться на другой режим и сравнить его на своей сети.
Как MTProxy и WEB делят порт 443
Схема выглядит так:
Интернет :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.
Быстрый запуск через Docker Compose
Склонируем репозиторий и откроем готовый пример:
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.
1. Создаём секрет
Генератор можно вызвать прямо из образа 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.
2. Настраиваем telEgo
Минимальная конфигурация из примера:
[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-адреса из полной документации.
3. Получаем сертификат
Первый сертификат получаем 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.
4. Запускаем сервисы
Сначала проверим 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.
Если telEgo уже установлен
Секреты и 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 в одном из четырёх режимов.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.