Files
tglock/docs/ISSUE_AUDIT.md
T
Никита Sonic 945e794eb3 fix(proxy): LAN-режим отклонял настоящие адреса Telegram (#42) (#43)
@alexsagaidak: с компьютера прокси работает, с телефона — нет. Адрес машины
вписан верно, порт верный, брандмауэр выключен, порт добавлен в исключения.

Причина нашлась в проверке «это Telegram?». Она сравнивала два первых октета:

    (149, 154) => Some(...)
    (91, 108)  => Some(...)

То есть «телеграмом» считались целиком четыре /16 — десятки тысяч чужих
адресов, — а IPv6 не распознавался вообще ни один. Telegram владеет
149.154.160.0/20, шестью /22 в 91.108, 91.105.192.0/23, 185.76.151.0/24 и пятью
блоками IPv6.

Ошибка в обе стороны, и на loopback она не видна. Там allow_direct включён, и
неопознанный адрес всё равно релеится напрямую — соединение просто работает.
На сетевом слушателе allow_direct выключен, и тот же адрес получает SOCKS5
0x02. Отсюда ровно то, что описал репортёр: на компьютере работает, с телефона
нет. Заодно чужие адреса внутри этих /16 уходили в MTProto-туннель и умирали
там.

Список сетей теперь опубликованный самим Telegram
(core.telegram.org/resources/cidr.txt), проверка по маске префикса, IPv4 и
IPv6, с тестами на края блоков и на соседей за границей.

Отдельно разрешены имена веб-инфраструктуры: telegram.org, t.me, telegram.me,
telesco.pe, cdn-telegram.org. Это не MTProto, а обычный HTTPS — клиент ходит
туда за конфигурацией, превью и файлами CDN, и на телефоне эти запросы идут
через тот же прокси. Заворачивать их в туннель нельзя, поэтому они идут прямым
релеем. Совпадение по границе метки, так что telegram.org.example.com —
посторонний домен. В ограниченном режиме имя разрешается заранее и адреса
внутри локальной сети отбрасываются: назначение выбирает чужое устройство, и
DNS-ответ не должен открывать доступ к 192.168.х этой машины.

И главное для разбора следующего такого случая: отказ перестал быть
молчаливым. Появился счётчик «Отклонено» в диагностике и в строке статуса CLI,
отклонённый адрес один раз называется в журнале, и отдельно отмечается первое
подключение с каждого сетевого адреса. Без этого «с телефона не работает»
неразличимо распадалось на два случая: телефон не дошёл до машины — и дошёл,
но попросил адрес, который мы не пускаем. Теперь первый виден как ноль
соединений и ноль отказов, второй — как соединения есть, отказы растут.

Co-authored-by: by-sonic <171230345+by-sonic@users.noreply.github.com>
2026-08-19 09:07:50 +03:00

12 KiB
Raw Permalink Blame History

TGLock 2.0 issue audit

Проверено 29 июля 2026 года: все 15 issues и 5 pull requests, существовавшие в репозитории на момент аудита.

Статус на 30 июля 2026. Аудит ниже оставлен как есть — это фиксация состояния на дату проверки. Что с тех пор сделано:

  • Разобраны все issues и pull requests. Открытых PR не осталось.
  • Закрыты #1#5, #8, #11, #13, #14, #19, #23 и #3 — с техническими объяснениями в самих issues.
  • #15 реализован заново поверх архитектуры 2.0 в #25: смерджить исходный PR было нельзя, он патчил bypass.rs, network.rs и ws_proxy.rs, которых больше нет, и правил системный DNS. Взято разделение GUI/CLI и произвольный bind-адрес; DNS-менеджмент и проверка root отброшены как ненужные.
  • #12 закрыт: относился к шрифту старого egui-интерфейса.
  • #10 и #17 закрыты выпуском v2.0.0-beta.2: GUI перед стартом просит у WebView программный рендер. Проверить это на машине без 3D-ускорения возможности не было, поэтому закрыто как «исправление выпущено», а не «исправлено» — репортерам предложено переоткрыть, если проблема осталась. Независимо от WebView работает tglock-cli.
  • #21 закрыт: репорт относился к сборке macOS, которой больше нет, в v2.0.0-beta.2 она пересобрана универсальным .dmg.
  • #9 (Android) остаётся единственным открытым — backlog без сроков.

Претензия из публичного обсуждения, которую нельзя закрыть кодом: инсталлятор не подписан, из-за чего часть антивирусов на него реагирует. Решение принято и зафиксировано: подписи не будет, сертификат — ежегодный платёж, а проект бесплатный. Вместо неё в README описан механизм срабатывания и три проверяемых пути — сверка sha256 с публикуемым GitHub digest, открытый лог сборки в Actions и сборка из исходников одной командой.

Дополнительно исправлено то, чего в issues не было: коллизия MTProto-init с байтом 0x05 (одно соединение из 256 уходило в SOCKS5-ветку и умирало), подсчёт туннеля до успешного рукопожатия, неверные подписи маршрутов в интерфейсе и генерация нового секрета при каждом старте сервиса. Подробности — в ARCHITECTURE_V2.md.

Из списка «не подтверждённых обещаний» в конце документа закрыты все четыре пункта: формулировки про звонки и про «Подключено» приведены в соответствие с кодом, LAN-режим ограничен адресами Telegram на уровне типа, Cloudflare Worker остаётся исключительно пользовательской настройкой.

Статус на 19 августа 2026. С прошлой отметки вышли beta.6, beta.7, beta.8 и beta.9. Что закрыто и что осталось:

  • #32 (медиа). Файл настроек tglock.toml сделан в beta.6 — это была отдельная просьба из того же issue. Заодно исправлена паника println! при закрытом stdout. Причина проблем с медиа не подтверждена: репортёр не прислал строку статуса в момент, когда фото не грузится. Слабое место названо в самом issue — у DC203 закреплён один IP, резерва по адресам для медиа нет.
  • #37 («прокси настроен неверно»). В beta.7 перестала проглатываться ошибка записи секрета: раньше при неудачной записи в %APPDATA%\TGLock секрет молча генерировался заново при каждом запуске, и ссылка tg://proxy переставала совпадать с сохранённой в Telegram. Это гипотеза, а не подтверждённый диагноз — воспроизвести случай репортёра не удалось, но теперь видно, тот это случай или нет.
  • #39 (не работает). По скриншоту: соединения есть, DC определяется, туннелей ноль, 678 падений маршрутов за пять минут. Наружу не отвечает ни один маршрут — у провайдера заблокирована веб-инфраструктура Telegram целиком. Кодом это не лечится, остаётся свой Cloudflare Worker. Счётчик падений маршрутов, по которому это стало видно, появился в beta.7.
  • #40, #41 (свои). В LAN-режиме окно показывает готовый адрес для других устройств — люди искали его в интерфейсе и вписывали 127.0.0.1. И страж тега в CI, который ловит тег, поставленный не на HEAD.
  • #42 (LAN не работает с телефона). Нашлось в коде. Принадлежность адреса Telegram проверялась по двум первым октетам, то есть «телеграмом» считались целиком четыре /16, а IPv6 не распознавался вовсе. На loopback это не проявлялось: неопознанный адрес там всё равно релеится напрямую. На сетевом слушателе тот же адрес получал отказ — отсюда ровно то, что описал репортёр: на компьютере работает, с телефона нет. В beta.9 список сетей взят опубликованный Telegram, добавлены IPv6 и имена веб-инфраструктуры. Отказ перестал быть молчаливым: счётчик «Отклонено» и адрес в журнале.
  • #9 (Android) остаётся открытым. PR #36 собирает APK, но приложение никто ни разу не запускал — нужен человек с телефоном.

Общее по трём разобранным issue: во всех трёх диагноз упирался в то, что программа не рассказывала о себе достаточно. Каждый выпуск с beta.7 добавлял не функцию, а показание прибора.

Выводы

Главная причина жалоб «прокси подключён, но Telegram не работает» — приложение считало успешный запуск локального SOCKS5-сервера успешным подключением к Telegram. Единственный upstream kws{dc}.web.telegram.org может резолвиться в недоступный IP или блокироваться провайдером.

TGLock 2.0 разделяет эти состояния и использует адаптивный список Telegram IP, kwsN/kwsN-1, системный DNS и опциональный пользовательский Cloudflare Worker. TLS SNI и WebSocket Host проверяются. Системный DNS и файл hosts не изменяются.

Классификация

Issue Наблюдение Решение для 2.0
#1 Порт 1080 занят Уже есть выбор порта; добавить автоматический подбор
#2, #11 Неверный сетевой адаптер В переписанном Rust-ядре привязка исходящего адаптера отсутствует; добавить только как расширенную настройку
#3 Rust 1.75 не собирает зависимости Cargo.lock зафиксирован; MSRV 1.88 документирована и проверяется в CI
#4 Linux/серверный режим Добавить headless CLI и systemd/Docker-примеры
#5 macOS Публиковать universal .app, затем подписанный и notarized DMG
#8, #19, #21, #23 Нет подключения Резервные маршруты, live-probe, понятная диагностика вместо ложного «Подключено»
#9 Android Не входит в desktop 2.0; LAN остаётся отдельным сценарием
#10, #17 GUI не запускается без GPU/монитора Headless CLI; отдельно проверить software rendering
#13 Discord/YouTube Вне области проекта; не смешивать с Telegram-транспортом
#14 Медиа, звонки, LAN Медиа тестировать отдельно; звонки не обещать без UDP; LAN ограничить Telegram-адресами

Pull requests

  • #6 относится к старой Windows-реализации выбора адаптера.
  • #12 относился к шрифту старого GUI. В v2 интерфейс перенесён на Tauri 2 и использует системную типографику каждой платформы.
  • #15 содержит полезное направление разделения GUI/CLI, но основан на старой архитектуре и меняет DNS системы.
  • #18 — экспериментальный Linux GUI без подтверждённого мобильного сценария.
  • #7 не содержит продуктового изменения.

Не подтверждённые обещания

  • Голосовые и видеозвонки нельзя заявлять рабочими: SOCKS5 UDP Associate не реализован, а Telegram может обходить proxy для части звонков.
  • «Подключено» допустимо показывать только после успешного WebSocket handshake, а не после открытия локального порта.
  • LAN-режим не должен становиться открытым универсальным SOCKS5-прокси.
  • Резерв через чужую Cloudflare-инфраструктуру нельзя включать без ясной модели доверия, владельца, мониторинга и политики обновления endpoint-ов.