ZaStoGram_desktop/README.md
loop-uh 567994f15b Не подставлять локальный прокси 1353 и подключаться через WSS
Клиент сам добавлял в список 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>
2026-10-01 14:58:37 +03:00

137 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ZaStoGram Desktop
![Обзор ZaStoGram Desktop](docs/assets/zastogram-overview.webp)
**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/