Полтора года назад я наткнулся в Telegram на новый тип прокси с пометкой WEB. Минуты три тупил: зачем городить веб-сервер, если есть MTProto и SOCKS5. Тогда закрыл и забыл. Вспомнил позже, когда собрал распределённую команду из шести человек. Половина работает из коворкингов и аэропортов, а мне нужен был один предсказуемый узел вместо десяти разнокалиберных конфигов в личке.
WEB proxy оказался не самым быстрым решением. Зато самым скучным в хорошем смысле: домен, сертификат, nginx, один systemd-юнит. Никаких экзотических портов, никакой магии. Ниже весь путь от пустого VPS до рабочего подключения в клиенте, с архитектурой и граблями, которые я собрал лично.
WEB proxy в Telegram на уровне архитектуры
Обычный прокси открывает отдельный порт и говорит на своём протоколе. WEB proxy устроен иначе: он живёт на стандартном HTTPS, на 443, и притворяется частью нормального сайта. Точка входа - путь base_path на твоём домене. Клиент открывает страницу по этому пути и получает от сервера capability - одноразовый пропуск. Дальше он гоняет через тот же домен API-запросы, которыми Telegram обменивается с серверами.
Внутри стоит tproxy_relay. Он принимает соединение от nginx и проверяет две вещи: HTTP-заголовок Host в запросе и тот самый capability. Если хоть что-то не совпало, соединение рвётся, и в клиенте ты видишь вечное «соединение». Понимание этих двух проверок экономит часа три отладки, проверено на себе.
Практический смысл схемы в том, что трафик неотличим от обычного визита на сайт: тот же порт, тот же TLS, тот же формат запросов. В корпоративных сетях из всего интернета часто открыты только 80 и 443. Тогда такой вариант не приходится согласовывать с сетевиками неделю.

Чем WEB отличается от MTProto и SOCKS5
MTProto - родной протокол Telegram с шифрованием на уровне транспорта. Поднимается за пять минут, работает шустро, задержка минимальная. Плата за простоту - отдельный порт, который пропустит не каждая сеть, и свой формат трафика, заметный с первого пакета.
SOCKS5 - универсальный солдат. Через него ходит и Telegram, и браузер, и любой софт с поддержкой прокси. Своего шифрования у него нет, TLS надо навешивать отдельно, иначе трафик читается на любом промежуточном узле.
WEB стоит в сторонке: HTTPS с валидным сертификатом, стандартный порт, поведение обычного веб-клиента. По моим замерам первый коннект занимает на 150-300 мс дольше, чем через MTProto, зато стабильность соединения в капризных сетях выше. Для чатов и файлов разница незаметна, для звонков MTProto всё ещё лучше.
Кому это реально нужно
Корпоративный узел. Один домен на компанию, единые логи, понятная точка входа. Сотрудник в роуминге открывает Telegram, видит в настройках уже добавленный прокси и жмёт «включить». Никто не пересылает друг другу ссылки и пароли в общий чат.
Защита трафика в публичных сетях. Открытый Wi-Fi в кафе, коворкинге или отеле - место, где снифферы живут припеваючи. WEB proxy заворачивает соединение в TLS до твоего сервера. Локальный администратор сети видит только аккуратный HTTPS к некоему домену.
Тестовые стенды. Когда гоняешь клиентские сценарии на своём билде Telegram, нужен контролируемый узел, куда можно смотреть логи в реальном времени. С публичными прокси такой фокус не выйдет.
Сбор данных и аналитика. Задачи, где нужно ходить по чужим сайтам из разных гео и не собирать капчу на второй минуте, требуют уже не одного узла, а пула. Об этом отдельно ниже.
Что понадобится до старта
Домен. Любой, лишь бы был доступ к DNS. A-запись на IP сервера. AAAA лучше не заводить вообще: лишний источник ошибок, особенно если IPv6 на VPS не настроен.
VPS. Ubuntu 22.04 или 24.04, от одного ядра и гигабайта памяти. Прокси не жрёт ресурсы, весь вес - это nginx и TLS-хендшейки. Порты 80 и 443 открыты в фаерволе, 80 нужен для выпуска сертификата Let's Encrypt.
Root-доступ. Один момент, на котором спотыкаются: бот проверяет сервер по SSH с паролем. Если у тебя вход только по ключам, а так и надо, автоматическая установка не пройдёт. Ставь руками по инструкции из репозитория. Не баг, а осознанный компромисс в пользу безопасности.
И убедись, что домен не спрятан за CDN с подменой IP. Оранжевое облако в панели DNS надо выключить, иначе бот увидит чужой адрес и откажется ставить прокси. Классическая история: «всё настроил, а он ругается».
Шаг 1. Добавляем прокси в интерфейсе Telegram
Когда узел готов, подключение занимает три тапа. В мобильном клиенте: Настройки, Данные и память, Прокси, Добавить прокси. В десктопе: Настройки, Продвинутые, Тип подключения, Прокси. В веб-версии настройка подтягивается с аккаунта, отдельно вводить ничего не надо.
Дальше два пути. Первый - вставить ссылку, которую прислал бот: Telegram сам распознает её, откроет карточку и предложит «Включить прокси». Второй - заполнить вручную: выбрать тип WEB, указать домен и путь base_path. Остальное клиент спросит сам. После сохранения в списке появится новая строка с ползунком и, что важнее, с пингом.
Пинг в этом списке - самый быстрый способ понять, живо ли соединение. Если цифра скачет от 60 до 3000 мс, дело не в Telegram, а в твоём сервере или DNS. Если пинга нет вообще, не трать время на клиент, иди смотреть логи nginx.
Шаг 2. Бот и проверка DNS
Схема через бота выглядит так. Отправляешь ему домен, он сразу дёргает DNS и сверяет A-запись с IP, который ты дал. Не совпало - ошибка, и это правильно: установщик не должен выпускать сертификат на домен, который смотрит в другую сторону. Иногда DNS расходится по резолверам. После правки записи подожди минут пять-десять и попробуй снова.
Следующий шаг - IP сервера и root-пароль. Пароль бот использует однократно для установки. Всё равно относись к этому как к передаче ключей от квартиры: не делай такую операцию из публичного Wi-Fi в кафе. После проверки бот предложит создать сайт прикрытия, соглашайся, о нём отдельно.
Шаг 3. Что установщик делает на сервере
Внутри три сущности. Nginx с конфигом на твой домен и отдельным location по base_path. Сервис tproxy_relay под systemd, который слушает локальный порт и общается с nginx. Сертификат Let's Encrypt с автопродлением и редирект с 80 на 443.
Установщик принимает три параметра: hostname, base_path и secret. Base_path - это тот самый путь, по которому клиент открывает страницу. Лучше делать его неочевидным, но и не в сто символов: длинный путь бессмысленно удлиняет каждый запрос. Secret - ключ, которым подписывается capability. Сгенерируй случайную строку, сохрани в менеджере паролей и никогда не коммить в git. Видел я репозитории, где этот секрет лежал в открытом виде в истории коммитов, вместе с паролем от root.
Заголовок Host - причина номер один для «подключился и отвалился»
Ситуация выглядит так. Прокси добавили, пинг зелёный, сообщения не ходят. Смотришь логи: tproxy_relay рвёт соединение на handshake. Причина в том, что перед WEB proxy стоит ещё один прокси или CDN. Он перезаписывает заголовок Host на внутренний адрес. Сервис ждёт в Host твой домен, получает что-то другое и закрывает соединение.
Лечится одной строкой в конфиге nginx внутри location по base_path: заголовку Host надо явно вернуть исходное значение с твоим доменом. После этого подключение проходит и через промежуточный прокси. Но честно, официальная документация не рекомендует ставить что-либо перед WEB proxy, и я согласен. Каждый дополнительный слой - ещё одна точка, где что-то перепишется не так.
Сайт прикрытия: не заглушка, а нормальная страница
Формально это просто страница, которая отдаётся по корневому пути. На практике пустой index.html с текстом «Hello» вызывает больше вопросов, чем его отсутствие. Сделай что-то правдоподобное: страницу корпоративного портала с формой входа, лендинг отдела, техноблог с парой постов. У нас на одном узле стоял внутренний статус-борд с графиками, смотрелось органично.
Заодно закрой лишнее. Запросы вне base_path должны отдавать 404, а не проваливаться в редирект. Методы кроме GET и POST на корне тоже отбой. User-agent и referer полезно логировать: по ним видно, кто интересуется сервером помимо твоих сотрудников.
Нагрузка, задержки и балансировка
Один VPS с двумя ядрами спокойно держит команду до 15-20 человек с активной перепиской. Узкое место не CPU, а количество одновременных TLS-хендшейков: каждый новый коннект - это полноценное рукопожатие. Включи keepalive в nginx, и клиенты перестанут дёргать сертификат на каждый чих.
Задержка складывается из трёх вещей: расстояния до сервера, времени на handshake и качества канала. Сервер во Франкфурте для команды в Москве даёт примерно 40-60 мс, для Владивостока уже 130-150. Второй узел в другом регионе дешевле, чем объяснения, почему чат «тормозит».
Балансировка на двух узлах делается на стороне клиента: Telegram умеет держать несколько прокси и переключаться. Раскидать сотрудников по гео проще, чем строить единую точку входа с балансировщиком. Меньше движущихся частей.
Один сервер или каскад
Каскад - это когда фронтальный сервер стоит в одной сети, а выход в другой. Каждый дополнительный хоп добавляет 30-60 мс задержки и ещё одно место, где может отвалиться сертификат. Для команды до двух десятков человек обычный один VPS держит нагрузку без проблем. Я такое видел на живых продакшенах.
Каскад оправдан в двух случаях: нужна гео-привязка исходящего IP, например платежи видят европейский адрес, или фронт и выход администрируются разными людьми. Во всех остальных сценариях это лишняя сложность.
Пять мест, где смотреть при проблемах
Клиент. Ползунок включён, но пинг не считается, значит TCP не проходит. Проверяй 443 и сертификат.
DNS. Копни домен с внешнего резолвера, а не с локального. Половина «сломанных» прокси ломается именно здесь. В обсуждениях на Reddit администраторы самодельных узлов отмечают, что чаще всего отваливается не tproxy_relay, а DNS: A-запись обновилась, а резолверы ещё держат старую.
Nginx. Логи покажут коды: 200 - норма, 403 - не совпал secret или capability, 404 - клиент стучится не туда по base_path.
Сервис. Статус tproxy_relay и его журнал. Если юнит падает на старте, почти всегда не читается конфиг или занят порт.
Сертификат. Просроченный Let's Encrypt выглядит как «прокси перестал работать внезапно». Поставь автообновление и проверь таймер отдельно, а не понадеяйся.
Ошибки, которые я видел чаще всего
- AAAA-запись осталась с прошлого сервера, и клиент часть времени стучится в пустоту
- домен за CDN с подменой IP, бот не может проверить A-запись
- secret лежит в открытом репозитории
- порт 80 закрыт, сертификат не выпускается, установка падает на середине
- root-пароль с символами, которые бот обрезает при парсинге
- base_path меняли после установки, а конфиг nginx остался старый
Каждая из этих шести строчек стоила кому-то вечера. Первая и вторая самые дорогие, потому что выглядят как проблема на стороне Telegram.
Безопасность: пара привычек, которые спасают
Отдельный пользователь для сервиса, root только для установки. SSH по ключам, пароль от root после настройки сменить. Fail2ban на SSH - это три строки конфига, а количество ботов в логах падает в разы. Ротация secret раз в пару месяцев: клиенты переподключатся, ссылку в боте обнови.
Логи access держи не вечно, двух недель хватает для разбора инцидента. И не храни query-параметры целиком: там могут проскочить токены. Мелочь, но неприятная.
Когда одного узла мало: пул прокси под задачи
Всё описанное выше - про один узел для себя или команды. Как только появляются задачи вроде мониторинга цен, проверки выдачи по регионам, работы с рекламными кабинетами или сбора данных с маркетплейсов, одного домена категорически не хватает. Нужен пул, и тут я обычно иду в каталог прокси 3seller.
Там есть резидентные, мобильные и датацентровые прокси с фильтрами по стране и протоколу. Для парсинга беру резидентные: они выглядят как домашние пользователи, и сайты реагируют на них спокойнее. Для высоконагруженных задач, где важна скорость, а не маскировка, дешевле и быстрее датацентровые. Мобильные - когда нужен максимально «человеческий» IP, они дороже, но своего стоят.
Практический момент: пул не отменяет собственный WEB proxy для Telegram. Два разных инструмента. Один даёт команде стабильный канал для переписки, второй - распределённые адреса для внешних запросов. У меня они живут параллельно и не конфликтуют.
Что сделать прямо сейчас
Купи домен, подними VPS, добавь A-запись. Дальше установка занимает минут двадцать, ещё столько же сайт прикрытия и проверка в клиенте. Не начинай с каскада и не пытайся сразу закрыть все сценарии: один сервер, один домен, один base_path. Когда заработает и отстоит неделю, станет понятно, нужен ли второй узел и в какой гео.
А если внешних задач с адресами больше, чем внутренних, посмотри готовый пул на 3seller.com/proxy. Это дешевле по времени, чем поднимать десяток своих серверов в десяти странах и потом следить за сертификатами на каждом.