Клиент сам добавлял в список SOCKS5 127.0.0.1:1353 и выбирал его на новой установке. Это адрес внешнего сервиса telegram_proxy, который запущен не у всех: без него клиент бесконечно висел на подключении, а WSS через локальный адрес запрещён, так что и он не выручал. - Новая установка стартует без прокси и идёт через встроенный WSS, он и так сохранён транспортом по умолчанию. - Запись, подставленная прежними сборками, один раз убирается из списка. Если она была выбрана, прокси выключается. - Прокси 127.0.0.1:1353, добавленный вручную после обновления, остаётся. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
137 lines
19 KiB
Markdown
137 lines
19 KiB
Markdown
# ZaStoGram Desktop
|
||

|
||
|
||
**ZaStoGram** — форк [Telegram Desktop][tdesktop], заточенный под работу в сетях с DPI‑цензурой и под приватность. Цель проекта: чтобы клиент **уверенно подключался там, где обычный Telegram режут**, маскировал трафик под обычный браузерный HTTPS и **не терял переписку** (удалённые сообщения, истории, правки).
|
||
|
||
Это **неофициальная** сборка. Она основана на исходниках официального клиента и сохраняет весь его функционал, добавляя сверху сетевой стелс, WSS‑транспорт и набор приватных функций.
|
||
|
||
> ⚠️ Используйте на свой риск. Проект не связан с Telegram FZ‑LLC. Базовый код — под GPLv3 с OpenSSL‑исключением (см. раздел «Лицензия»).
|
||
|
||
---
|
||
|
||
## Чем отличается от обычного Telegram Desktop
|
||
|
||
| Область | Что добавлено |
|
||
|---|---|
|
||
| **Обход DPI** | FakeTLS‑стелс: профили ClientHello, правдоподобные повторные TLS‑подключения через поддельные билеты возобновления, маскировка старта, фрагментация ClientHello, варьирование размера TLS‑записей, пейсинг трафика, разнос попыток подключения |
|
||
| **Надёжность** | Классифицированный loop‑backoff переподключения (cap 8 c), деприоритизация «залипших» endpoint'ов (cooldown) |
|
||
| **Транспорт** | Встроенный **WSS** (MTProto поверх WebSocket к web‑релею Telegram) |
|
||
| **Прокси** | Без прокси клиент ходит только через WSS: прямого подключения в обход него нет |
|
||
| **Приватность** | Сохранение **удалённых** сообщений и **историй** (stories), **скачивание любых** (даже защищённых) историй, **история правок** сообщений |
|
||
| **Скорость подключения** | Убраны две клиентские задержки, найденные измерением: очередь дозвонов (было до 8 с ожидания на поздних сокетах) и невыключенный алгоритм Нейгла |
|
||
| **Производительность** | Ограничение числа потоков софт‑декодера видео, троттлинг под нагрузкой |
|
||
| **UX** | Список прокси больше не устраивает «шквал» проверок при открытии |
|
||
| **Бренд** | Имя и иконка ZaStoGram |
|
||
|
||
---
|
||
|
||
## 🛡️ Обход DPI — стелс MTProxy
|
||
|
||
Когда задан MTProxy (FakeTLS), клиент маскирует подключение под настоящий браузерный TLS‑хэндшейк. Всё настраивается тумблерами в окне прокси (**Настройки → Продвинутые → Тип соединения → список прокси**).
|
||
|
||
- **Профиль ClientHello** — ClientHello воспроизводит форму реального браузера/приложения: `Auto (Yandex)`, `Auto‑rotate`, `Firefox`, `Firefox Android`, `Yandex`, `Android OkHttp`. Профили `Chrome Modern` и `Android Chrome` остались в таблице, но больше не отправляются: измерением найдено, что фильтрующая сеть отвергает именно их — 3 попытки из 12 против 12 из 12 у остальных, на одном релее в одни минуты. Выбранный вручную отключённый профиль автоматически заменяется на рабочий.
|
||
- **Маскировка старта (startup‑cover)** — первые записи разбиваются и подаются так, чтобы начало сессии не выделялось характерным паттерном.
|
||
- **Фрагментация ClientHello** — ClientHello дробится при отправке, чтобы DPI было сложнее собрать и распознать его целиком.
|
||
- **Варьирование размера TLS‑записей** — размеры записей не фиксированы, что ломает сигнатуры по длине.
|
||
- **Пейсинг трафика** — межзаписевые задержки на старте сглаживают «взрывной» профиль (без удушения уже установленного потока).
|
||
- **Разнос попыток подключения** — попытки к нескольким endpoint'ам стартуют со сдвигом, а не пачкой. Сдвиг намеренно небольшой (50 мс): измерение показало, что релеи спокойно принимают два десятка одновременных рукопожатий, а большой разнос стоил секунд на старте — подробности в разделе про задержку.
|
||
- **Правдоподобные повторные TLS‑подключения** — первый ClientHello к узлу и имени назначения идёт без PSK, как обычный «холодный» заход браузера. После успешного fakeTLS‑хэндшейка клиент держит небольшой локальный пул поддельных билетов возобновления с ограниченным временем жизни и при повторных подключениях отправляет один из них с нормальным возрастом. Это убирает подозрительный паттерн «каждый параллельный сокет приносит новый случайный PSK» и делает повторные подключения похожими на обычный браузерный HTTPS. Эти билеты нужны только для маскировки, не используются для шифрования MTProto и не сохраняются на диск.
|
||
|
||
### Надёжность подключения
|
||
- **Loop‑backoff** — классифицированные таймауты переповтора, привязанные к прокси, с верхней границей, чтобы не зацикливаться на мёртвом узле и не спамить коннектами.
|
||
- **Endpoint cooldown** — endpoint, который только что отвалился, временно понижается в приоритете (а не выбрасывается), чтобы клиент пробовал живые маршруты, не теряя резервные.
|
||
|
||
---
|
||
|
||
## 🌐 WSS‑транспорт
|
||
|
||
Встроенный **MTProto‑over‑WebSocket** (чистая реализация на `QSslSocket` + RFC 6455): настоящий TLS → HTTP‑upgrade (`GET /apiws`) → бинарные WS‑фреймы, внутри которых идёт обфусцированный MTProto‑поток. Подключается к официальным web‑релеям Telegram (`kws2/kws4.web.telegram.org`) для **DC2/DC4**.
|
||
|
||
Включается тумблером **«Route via WSS (web, DC2/DC4 only)»**. Полезен там, где прямой TCP к DC блокируется, но веб‑Telegram работает. Может ходить как напрямую, так и через заданный SOCKS‑прокси.
|
||
|
||
WSS включён по умолчанию: новая установка не добавляет никаких прокси и сразу подключается через него.
|
||
|
||
Альтернатива встроенному WSS — внешний локальный прокси (`telegram_proxy` из zapret‑набора) на `127.0.0.1:1353`, к которому клиент подключается по SOCKS5. Его нужно добавить в список вручную (см. ниже).
|
||
|
||
---
|
||
|
||
## 🔌 Прокси и прямое подключение
|
||
|
||
- **Force‑proxy** — без выбранного прокси клиент не выходит в сеть; «щит» соединения виден всегда. Исключение — включённый режим WSS (он сам является методом обхода). Это страховка от случайного прямого подключения в опасной сети.
|
||
- **Локальный SOCKS5 `127.0.0.1:1353`** — endpoint внешнего сервиса `telegram_proxy`: схема `tdesktop → SOCKS5 1353 → telegram_proxy → WSS/FakeTLS → Telegram`. Сам он больше не добавляется: сервис запущен не у всех, и без него клиент бесконечно висел на подключении. Запись, которую подставили прежние сборки, убирается при обновлении; у кого сервис есть — добавьте прокси в список вручную.
|
||
|
||
---
|
||
|
||
## 🔒 Приватность
|
||
|
||
Клиент‑сайд функции, которые сохраняют данные локально (по умолчанию включены):
|
||
|
||
- **Сохранение удалённых сообщений** — когда сервер присылает «удалить», сообщение не уничтожается локально, а остаётся (помечается как удалённое отправителем). Переписка не пропадает.
|
||
- **Сохранение историй (stories)** — локальный снэпшот историй с восстановлением при старте; истории не исчезают по истечении срока.
|
||
- **Скачивание любых историй** — медиа истории сохраняется на диск даже для защищённых от пересылки (noforwards) и чужих историй, без Premium (снят клиентский гейт canDownload).
|
||
- **История правок** — при редактировании сообщения предыдущие версии (текст + время) сохраняются, чтобы видеть, что было изменено.
|
||
|
||
> Это локальные функции: они не влияют на сервер и не нарушают шифрование. Хранение части данных может быть только в памяти до перезапуска (персистентность отдельных частей — в развитии).
|
||
|
||
---
|
||
|
||
## ⚡ Производительность
|
||
|
||
- **Decoder policy** — централизованное ограничение числа потоков софтверного видео‑декодера и троттлинг запуска декодеров под нагрузкой, чтобы тяжёлые медиа не «съедали» CPU и не плодили лишние декодеры.
|
||
|
||
### Задержка подключения: что было измерено и убрано
|
||
|
||
Жалобу «через прокси медленно, пинг большой» обычно списывают на сеть. Мы разложили её на слои и померили с двух машин — на сети с фильтрацией и без неё:
|
||
|
||
| слой | что это | типичные значения |
|
||
|---|---|---|
|
||
| TCP | до релея | 11–70 мс |
|
||
| FakeTLS | релей отвечает сам | 9–71 мс |
|
||
| resPQ | релей → Telegram → релей | 55–94 мс суммарно |
|
||
|
||
Оказалось, что **фильтрация к задержке не добавляет ничего**: на одном и том же релее сеть с блокировками и сеть без них дали 17/55 мс против 11/56 мс. Секунды создавал сам клиент, и нашлось два источника.
|
||
|
||
- **Очередь дозвонов.** Попытки к одному релею разносились на 250 мс, а холодный старт открывает десятки сокетов — поздние ждали своей очереди секундами (в логе `tcp_ms` доходил до 8666 мс при сетевом round trip 17 мс). Разнос вводился ради маскировки, но измерение показало, что цена ему не соответствует: **24 дозвона вообще без разноса дошли до Telegram все 24, вся пачка за 170 мс**, тогда как через очередь те же 24 стоили около шести секунд. Разнос снижен до 50 мс — этого хватает, чтобы соединения приходили различимо, а не одним мгновением. Рост разноса при неудачах не тронут: именно он защищает релей, который действительно не тянет пачку.
|
||
- **Алгоритм Нейгла.** `TCP_NODELAY` не выставлялся ни на одном сокете. Нейгл придерживает короткую запись, пока не подтверждена предыдущая, а MTProto устроен ровно так: короткий запрос, затем ожидание. Тонкость, из‑за которой это легко сделать вхолостую: Qt применяет опции сокета через движок, который появляется только после установления соединения, поэтому выставлять их надо в обработчике `connected`, а не в конструкторе.
|
||
|
||
Обе правки закрыты тестами, которые держат числа рядом с константой — чтобы следующий, кто захочет вернуть разнос, спорил с измерением, а не с догадкой.
|
||
|
||
> **Как выбирать релей по скорости.** Сравнивать надо не пинг до релея, а сумму: путь до него плюс путь от него до дата‑центра Telegram. Релей с отличным пингом, но далёкий от Telegram, на практике медленнее скромного, стоящего рядом с ним — в наших замерах два релея различались вдвое по суммарному времени именно из‑за этого.
|
||
|
||
## 🧰 Спокойная архитектура прокси
|
||
|
||
- Список прокси **не запускает проверку всех строк** при открытии окна — это убирает «шквал» одновременных тестовых коннектов. Строки по умолчанию в состоянии *Unknown*; проверка запускается **вручную** по пункту *Check Status*.
|
||
|
||
---
|
||
|
||
## 🗺️ Roadmap (запланировано, ещё не реализовано)
|
||
|
||
- **Глобальный лимитер MTProxy‑handshakes** — в текущем Desktop каждый аккаунт держит свой `MTP::Instance` со своей DC‑сессией (разные auth keys, msg_id/seqno, salt), поэтому «один общий поток» для всех аккаунтов сделать нельзя без серверной поддержки. Вместо этого планируется безопасный лимитер: общий cap на число одновременных MTProxy‑handshakes между аккаунтами + jitter/backoff + очередь; снижение числа активных проверок ротации (10 → 1–2); кэширование статусов прокси; единый gate для всех `StartProxyCheck` и рабочих handshakes. Это сгладит всплеск подключений, не душа уже установленный трафик.
|
||
- **UI приватности** — видимая метка «удалено» на сохранённых сообщениях и просмотрщик истории правок (контекст‑меню).
|
||
|
||
---
|
||
|
||
## 🏗️ Сборка и проверки
|
||
|
||
- Forgejo Actions выполняет быстрые проверки исходников из `.forgejo/workflows/source-guards.yml` на изолированном Linux Runner.
|
||
- Тяжёлая Windows-сборка выполняется локальным публикатором на выделенной Windows-машине, после чего проверенные `.exe`, ZIP и файлы автообновления загружаются в Forgejo Releases.
|
||
- Единый список обязательных исходных проверок хранится в `Telegram/SourceFiles/tests/release_guards.txt`; его используют и Forgejo Actions, и локальный Windows-публикатор.
|
||
- Инструкции по ручной сборке официального клиента (применимы и здесь) — в [`docs/`](docs/).
|
||
|
||
> Базовый клиент собирается стандартным тулчейном Telegram Desktop. Артефакты пре‑релиза переименовываются в `ZaStoGram-<arch>.exe`.
|
||
|
||
---
|
||
|
||
## 📥 Установка
|
||
|
||
Скачайте `ZaStoGram-x64.exe` (или `x64_x86` для 32‑бит) из раздела **Releases** (пре‑релиз `dev-N`). Это сборка из исходников этого репозитория. Отдельно ничего настраивать не нужно: клиент подключается через встроенный WSS‑транспорт.
|
||
|
||
---
|
||
|
||
## 📄 Лицензия
|
||
|
||
Проект основан на [Telegram Desktop][tdesktop] и распространяется под **GPLv3 с OpenSSL‑исключением** — тот же текст лицензии, что и у апстрима, см. [LICENSE](LICENSE) и [LEGAL](LEGAL).
|
||
|
||
ZaStoGram — независимый форк; товарные знаки Telegram принадлежат их владельцам.
|
||
|
||
[tdesktop]: https://desktop.telegram.org/
|