golang

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

  • суббота, 29 августа 2026 г. в 00:00:11
https://habr.com/ru/articles/1075506/

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:

carrier

Как передаются данные

Что требуется от Nginx

https

Один последовательный канал на fetch и long polling

HTTP/1.1 до внутреннего listener

https-lanes

Отдельный HTTP-канал на каждый Telegram stream

HTTP/2 на публичном TLS listener

websocket

Один мультиплексированный WebSocket на WEB-сессию

Заголовки Upgrade и Connection

websocket-lanes

Отдельный WebSocket на каждый Telegram stream

Заголовки Upgrade и Connection

Строго говоря, это четыре транспорта одного 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 и служебные заголовки.

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

Для установки нужны:

  1. VPS с публичными портами 80 и 443.

  2. Домен или поддомен с A-записью на адрес VPS.

  3. Docker с Compose.

  4. Свободный порт 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-ссылки менять не требуется. Порядок миграции такой:

  1. Добавьте секцию [web-proxy].

  2. Настройте Nginx на приватных портах 8443 и 8444.

  3. Добавьте upstream на приватный WEB listener 8080.

  4. Включите HTTP/2 на публичном TLS listener, если выбрали https-lanes.

  5. Передайте заголовки Upgrade и Connection, если выбрали WebSocket.

  6. Проверьте конфигурацию командой nginx -t.

  7. Перезапустите telEgo и перезагрузите Nginx.

  8. Запустите 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