Транспорт к Telegram
Настройки, Telegram, Транспорт к Telegram (общий). Эти настройки определяют, как сам b4 доходит до дата-центров Telegram. Их используют и прокси-сервер, и WebSocket-мост, поэтому они действуют даже при выключенном прокси-сервере.

Режим транспорта
| Режим | Что делает |
|---|---|
| Прямой TCP | Набирает адрес дата-центра напрямую или через DC Relay, если он задан. |
| Авто (WebSocket -> TCP) | Сначала пробует маршруты WebSocket, затем откатывается на прямой TCP. |
| Только WebSocket | Маршруты WebSocket без TCP вообще. DC Relay в этом режиме игнорируется. |
Список относится к прокси-серверу. WebSocket-мост принудительно использует Авто для каждой своей сессии.
Для прямого TCP нужен хост, который дотягивается до адресов дата-центров. 149.154.0.0/16 покрывает большинство, но не все: DC 203 находится на 91.105.192.100, а DC 4 и DC 5 - в 91.108.4.0/24 и 91.108.56.0/24.
Какие маршруты есть и в каком порядке
Для конкретного дата-центра b4 составляет список кандидатов и идёт по нему:
- Прямой TCP первым, если выбран режим Прямой TCP либо режим Авто и задан DC Relay.
- Собственный WebSocket-узел Telegram,
kws<dc>.web.telegram.org. Так обслуживаются только дата-центры 2 и 4. Медиа-сессия сначала пробует имяkws<dc>-1, обычная - никогда. - Свой WebSocket-домен, в виде
kws<dc>.<домен>. - Общий пул CF-доменов, в виде
kws<dc>.<домен из пула>, пока включён CF-резерв. - Домены Cloudflare Worker, в случайном порядке.
- Прямой TCP, если выбран режим Авто и он не был поставлен первым.
Worker-ы, недавно замолчавшие посреди сессии, дописываются в конец, а не выбрасываются, и если список оказался пуст в режиме, допускающем TCP, прямой маршрут возвращается обратно без учёта его кулдаунов.
Кандидаты не ждут друг друга по очереди, а перекрываются. Следующий запускается, если предыдущий не ответил за полсекунды, или сразу, если он упал, и одновременно в работе не больше трёх. Имена собственного узла Telegram делят один адрес, поэтому они набираются по одному, а соседнее имя отбрасывается, как только перестал отвечать сам адрес. Кроме того, список разбит на ступени в порядке выше: прямой TCP стартует только после того, как упали все WebSocket-маршруты перед ним, а релей, поставленный первым, должен упасть до старта любого WebSocket-маршрута. Worker вступает в гонку, когда WebSocket-маршруты перед ним работают уже полторы секунды, если только он не понижен после зависания. Сессию несёт первый подключившийся кандидат, а более медленный, подключившийся позже, остаётся прогретым запасным соединением.
Новые попытки не начинаются позже примерно четырёх с половиной секунд, и каждой отводится не больше трёх. Telegram Desktop бросает сессию, которая не добралась до дата-центра примерно за три секунды.
Адрес, не ответивший на TCP-рукопожатие, последующие сессии обходят минуту, имя, на котором TLS-рукопожатие ушло в пустоту, - пять минут, и оба срока удваиваются, пока сбои повторяются, до тридцати минут. Один ответ их сбрасывает.
Прокси-сервер держит небольшой пул прогретых WebSocket-соединений и заглядывает в него до того, как построит список выше. Поэтому при режиме Авто с настроенным DC Relay прогретое соединение из пула может опередить релей, стоящий в плане первым. Мост пользуется тем же пулом, пока прокси-сервер работает в режиме Авто или Только WebSocket, а в остальное время держит собственный.
Запасное соединение выводится из пула через 75 секунд, потому что Telegram и маршруты через Cloudflare закрывают неиспользуемое соединение примерно через 90. Каждые пять секунд пул выбрасывает устаревшие соединения и пополняет дата-центры, к которым обращались за последние десять минут, или за три для тех, что идут через общие домены Cloudflare. Пока собственный узел Telegram не отвечает, дата-центры 2 и 4 держатся в пуле на маршрутах Cloudflare, а узел проверяется из пула, не чаще раза в тридцать секунд, а не на сессии клиента.
Собственный узел есть только у дата-центров 2 и 4. Для 1, 3, 5 и 203 «WebSocket» означает свой домен, общий пул или Worker, и именно поэтому медиа в зарубежных каналах отваливается первым, когда не настроено ничего из этого.
Домен Cloudflare Worker
Бесплатный персональный WebSocket-релей на собственном аккаунте Cloudflare, пробуемый последним из маршрутов WebSocket. Настройка, скрипт и объяснение его места в списке - на странице Релей на Cloudflare Worker.
CF-резерв
Ротируемый пул проксируемых через Cloudflare доменов, обновляемый раз в час по URL из раздела Резервные источники. Он покрывает дата-центры, которые не обслуживает собственный узел Telegram. Источник по умолчанию - список tg-ws-proxy на GitHub, его можно заменить своим.
Свой WebSocket-домен
Один домен, проксирующий WebSocket-трафик к Telegram, вместо общего пула. b4 сам подставляет kws1., kws2. и так далее по дата-центрам, поэтому одной записи хватает на все, и имя должно резолвиться для каждого используемого дата-центра. Пробуется после собственного узла Telegram и до общего пула, работает независимо от CF-резерва.
IP edge-сервера Telegram
Любое соединение с именем kws*.web.telegram.org идёт на один адрес, 149.154.167.220; дата-центр выбирается именем в HTTP-заголовке Host, а не адресом. Это поле заменяет адрес для сети, в которой на адрес по умолчанию никто не отвечает. Принимается хост или IP без порта, пустое значение оставляет адрес по умолчанию. Свой WebSocket-домен резолвит собственное имя и не затрагивается.
Имя для фронтинга WS-узла
Узел Telegram отвечает своим сертификатом на любое TLS-имя и направляет WebSocket только по заголовку Host. Там, где DPI обрывает рукопожатие для имён kws*.web.telegram.org, а сам адрес остаётся доступным, b4 передаёт в TLS-рукопожатии это имя, а настоящее оставляет в Host, поэтому сессия всё равно попадает в тот дата-центр и тот кластер, которые запросила.
Пока поле пустое, фронтинг выключен. sprinthost.ru - имя, которое использует tg-ws-proxy. Это имя пробует только прогретый пул, не чаще раза в тридцать секунд, после того как рукопожатие под собственными именами Telegram успело бы завершиться, но осталось без ответа или было сброшено. Рукопожатие под этим именем должно закончиться сертификатом telegram.org; всё остальное закрывается до отправки запроса, и на этом адресе имя тридцать минут больше не пробуется. Как только через имя прошло соединение, сессии клиентов к узлу тоже используют его, пока рукопожатие под ним не сорвётся и узел снова не ответит на свои имена. Адрес, который вообще не принимает TCP-соединение, под этим именем повторно не пробуется.
Фронтинг бесполезен в сети, блокирующей адрес узла целиком, и в сети, чей DPI сам отвечает за этот адрес и пересылает соединение по увиденному имени. Во втором случае рукопожатие под этим именем доходит до настоящего хоста за ним, чей сертификат не принадлежит Telegram, и дата-центры 2 и 4 остаются на маршрутах Cloudflare.
Резервные источники
Список дата-центров Telegram запрашивается при старте у самого Telegram. Резервное зеркало списка DC определяет, что происходит, когда этот эндпоинт недоступен, и по умолчанию включено.
Зеркало по умолчанию размещено автором b4 и получает IP-адрес запрашивающего, и ничего кроме. Выключение переключателя убирает резерв, поле URL зеркала списка DC заменяет его на другое.
Обновление списка меняет то, как b4 сопоставляет адрес с дата-центром и какие адреса печатает помощник DC Relay. Адреса, которые b4 набирает, оно не меняет: они встроены в сервис.
Проверка
- Проверить соединение обращается к дата-центру 2 настроенными транспортами, сохраняя заданный DC Relay, и показывает задержку.
- Прямой TCP обращается к дата-центру 2 напрямую, в обход релея, что отделяет проблему релея от проблемы Telegram.
Включение и выключение прокси, а также смена порта, адреса привязки, Fake SNI, режима транспорта, своего WebSocket-домена, IP edge-сервера, имени для фронтинга и CF-резерва перезапускают MTProto-прокси и разрывают переносимые им сессии. Telegram переподключается сам. Сам сервис при этом не перезапускается.