Перейти к основному содержимому

Транспорт к Telegram

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

Карточка транспорта к Telegram

Режим транспорта​

РежимЧто делает
Прямой 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 составляет список кандидатов и идёт по нему:

  1. Прямой TCP первым, если выбран режим Прямой TCP либо режим Авто и задан DC Relay.
  2. Собственный WebSocket-узел Telegram, kws<dc>.web.telegram.org. Так обслуживаются только дата-центры 2 и 4. Медиа-сессия сначала пробует имя kws<dc>-1, обычная - никогда.
  3. Свой WebSocket-домен, в виде kws<dc>.<домен>.
  4. Общий пул CF-доменов, в виде kws<dc>.<домен из пула>, пока включён CF-резерв.
  5. Домены Cloudflare Worker, в случайном порядке.
  6. Прямой 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 переподключается сам. Сам сервис при этом не перезапускается.