- Java 60.9%
- C++ 24.3%
- C 10.5%
- Kotlin 2.5%
- Python 1.3%
- Other 0.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
Some checks failed
Build three ZaStoGram APKs / build (arm64-v8a, ZaStoGram-standalone-arm64-v8a, Arm64, arm64) (push) Has been cancelled
Build three ZaStoGram APKs / build (armeabi-v7a, ZaStoGram-standalone-armeabi-v7a, Armv7, armv7) (push) Has been cancelled
Build three ZaStoGram APKs / build (x86, ZaStoGram-standalone-x86, X86, x86) (push) Has been cancelled
ZaStoGram source guards / guards (push) Has been cancelled
У части провайдеров порт 443 к релею отдельного датацентра закрыт целиком: у пользователя kws2-1 и kws4-1 отвечают, а kws1-1 не отвечает ни по IPv4, ни по IPv6 — 15 таймаутов подряд на стадии установки TCP, ни одного успешного подключения. Эмодзи и реакции лежат как раз на этом датацентре, и WSS оставлял их без загрузки навсегда, работая по принципу «всё или ничего». Теперь неудачи, не дошедшие даже до установленного TCP, считаются по датацентру отдельно от выбора адреса. После трёх подряд маршрут WSS для него отключается на десять минут, и соединение идёт напрямую; успешный апгрейд счётчик сбрасывает. Остальные датацентры продолжают работать через WSS как раньше. Заодно откачено предпочтение IPv6, введённое в 1.1.17: наличие у устройства глобального IPv6-адреса не означает, что маршрут до релея работает, и попытки тратились на заведомо недостижимый путь. Теперь IPv4 идёт первым как известно рабочий, а IPv6 — дополнительным кандидатом при отказе. Запрос AAAA сохранён: он даёт второй адрес там, где у IPv4 он единственный. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
| .codex | ||
| .forgejo/workflows | ||
| buildSrc | ||
| docs | ||
| gradle/wrapper | ||
| TMessagesProj | ||
| TMessagesProj_App | ||
| TMessagesProj_AppHockeyApp | ||
| TMessagesProj_AppHuawei | ||
| TMessagesProj_AppStandalone | ||
| TMessagesProj_AppTests | ||
| Tools | ||
| .gitignore | ||
| .gitmodules | ||
| apkdiff.py | ||
| apkfrombundle.py | ||
| build.gradle | ||
| Dockerfile | ||
| gradle.properties | ||
| gradlew | ||
| LICENSE | ||
| README.md | ||
| settings.gradle | ||
ZaStoGram — Telegram для Android с MTProxy FakeTLS и нативным WSS
ZaStoGram — экспериментальный форк официального Telegram для Android. Он сохраняет протокол и серверную инфраструктуру Telegram, но добавляет:
- более строгий и диагностируемый MTProxy FakeTLS для
ee-секретов; - управляемые JA4/TLS-профили с рабочим автопрофилем Telegram Desktop;
- отдельный нативный WSS-транспорт через официальные WebSocket-релеи Telegram;
- клиентские функции приватности, локальную историю правок и UX-настройки;
- Python-плагины, совместимые с реализованной частью API exteraGram;
- встроенные stable/dev-обновления из Forgejo Releases.
Это не новый мессенджер, не VPN и не отдельный протокол. Текущая база —
Telegram Android 12.9.2, минимальная версия Android — 7.0 (minSdk 24).
Stable и dev используют разные package id, поэтому устанавливаются параллельно:
org.zastogram.messenger и org.zastogram.messenger.dev соответственно.
Скачать
Выбирайте APK по архитектуре устройства:
| APK | Для чего |
|---|---|
arm64-v8a |
Почти все современные Android-смартфоны и планшеты |
armeabi-v7a |
Старые 32-битные ARM-устройства |
x86 |
Старые 32-битные эмуляторы |
Актуальный стабильный релиз публикуется для этих трёх ABI, подписывается
релизным ключом ZaStoGram и использует канал обновлений stable. Сборка
x86_64 поддерживается исходниками, но не публикуется без отдельного запроса.
Транспортная архитектура
Клиент не смешивает WSS, MTProxy и SOCKS5 в один комбинированный прокси.
ConnectionSocket выбирает один маршрут для конкретного соединения:
flowchart TD
A["tgnet / ConnectionSocket"] --> B{"Выбранный маршрут"}
B -->|"WSS включён, прокси выключен, DC поддержан"| C["wss::Socket"]
B -->|"Выбран SOCKS5 или MTProxy"| D["Обычный proxy path"]
B -->|"WSS выключен или route недоступен"| E["Прямой Telegram transport"]
C --> F["TLS + WebSocket /apiws"]
F --> G["Официальные relay DC1–DC5"]
D --> H["SOCKS5 или MTProxy dd/ee"]
H --> I["FakeTLS policy только для ee"]
Главные границы конструкции:
- прямой транспорт не зависит от MTProxy lifecycle и его retry-политик;
- MTProxy policy вынесена в
TMessagesProj/jni/mtproxy/и работает через фазовые состояния, evidence и один retry authority; - WSS реализован отдельным
transport::SocketвTMessagesProj/jni/tgnet/wss/WssSocket.*и сам владеет TCP-дескриптором, TLS, WebSocket upgrade и очередями кадров; - legacy-прокси и WSS взаимоисключаемы: включение WSS выключает активный SOCKS5/MTProxy, а выбор обычного прокси выключает WSS;
- WSS не наслаивается поверх SOCKS5 или MTProxy.
MTProxy FakeTLS
Relay-контракт ClientHello
FakeTLS применяется только к MTProxy с ee-секретом. Перед отправкой
ClientHello проверяется по правилам reference relay:
- SNI должен байт-в-байт совпадать с доменом из
ee-секрета; - TLS record и handshake должны иметь согласованные длины;
- session id должен занимать 32 байта;
- первый набор шифров после relay-compatible GREASE должен быть TLS 1.3
(
0x1301–0x1303); - размер ClientHello должен быть от канонических
517до максимальных4096байт; - некорректный профиль блокируется до отправки в сеть.
Lowercase, trim, punycode и вариант без SNI могут рассчитываться для диагностики, но не подменяют wire-SNI. Relay сравнивает его с исходным доменом из секрета.
ClientHello и последующие TLS-записи имеют собственные pending-буферы.
Неблокирующий send() может принять часть записи: остаток досылается на
следующем EPOLLOUT, а MTProto payload удаляется из очереди только после
полной отправки TLS frame.
JA4 / TLS-профили
Автоматический профиль синхронизирован с проверенной формой Telegram Desktop:
Autoотправляет рабочий Yandex-shaped профиль с намеренно сохранённой tdesktop-совместимой формой последнего GREASE extension;Auto rotateвыбирает из проверенного пула Yandex, Firefox Android, Firefox и Android OkHttp и меняет профиль только после релевантного post-ClientHello сбоя;- DNS-ошибки и
tcp_not_connectedне вращают JA4: ClientHello в этих фазах ещё не участвовал; - Chrome Modern и Android Chrome удерживаются от отправки и переводятся на безопасный автопрофиль: в контрольной сети они отвечали заметно хуже рабочего пула;
- каждый собранный профиль повторно проходит relay-контракт перед отправкой.
Это не попытка сделать байт-в-байт копию установленного браузера. Приоритет — сначала совместимость с MTProxy relay, затем форма JA4 и дополнительные эксперименты.
Управляемые слои
Настройки MTProxy находятся в обычном экране прокси и передаются Java → JNI → native без пересборки APK:
| Настройка | Что меняет |
|---|---|
JA4 / TLS-профиль |
Выбор ClientHello-рецепта |
Мягкая фрагментация ClientHello |
Две неблокирующие отправки одного валидного hello |
Размер TLS-записей |
Размер завершённых FakeTLS ApplicationData frames |
Тайминги трафика |
Короткие паузы только между полностью отправленными frames |
Стартовая маскировка MTProxy |
Форму первых реальных MTProto ApplicationData-записей |
Меньше параллельных каналов |
Fanout download/upload при активном MTProxy |
Паттерн подключений |
Допуск и приоритет новых FakeTLS handshakes |
Размеры, тайминги и startup cover не перепаковывают MTProto в HTTP. Они меняют только TLS-подобное обрамление уже установленного FakeTLS-соединения.
Фазы и восстановление
MTProxy не лечит все сбои сменой JA4. Основные классы evidence разделены:
host_resolve_failed— DNS и кэш endpoint;tcp_not_connected— путь до TCP и endpoint circuit breaker;client_hello_sent_no_server_hello— ClientHello/relay recipe;server_hello_hmac_mismatch— ответ пришёл, но не прошёл MTProxy HMAC;post_handshake_no_appdata— handshake завершён, data-path не начался;dropped_early_after_appdata— data-path успел заработать и быстро оборвался;mtproxy_packet_sent_no_response— отдельный lifecycle обычныхdd/legacy секретов, где JA4 вообще не участвует.
Модули MtProxyEndpointPolicy, MtProxyHandshakeScheduler,
MtProxyProbeCoordinator, MtProxyAdaptivePolicy, MtProxyRecoveryPolicy и
MtProxyRetryAuthority разделяют запись фактов, выбор рецепта, координацию
проб и фактический reconnect. GUI и runtime-логи используют ту же карту фаз.
DRS пока не первым: до расширения динамических размеров записей должны быть
стабильны DNS, TCP, handshake и data-aware отправка завершённых TLS frames.
Иначе host_resolve_failed или mtproxy_packet_sent_no_response ошибочно
выглядят как проблема record sizing, хотя соответствующий слой ещё не
участвовал.
Архитектура проверки прокси
ProxyCheckScheduler владеет Java-очередью проверок, native socket публикует
фазовые события, а finishProxyCheck завершает ровно активное поколение
проверки. Java backoff использует ту же фазовую идею ключей: network-сбои
группируются по адресу, а проверки склеиваются только по полному exact key
host:port:username:password:secret.
Наблюдение generic Connected не стирает свежую terminal phase конкретного
endpoint. Явный новый старт подключения может начать новое поколение, но не
должен стирать ещё актуальный usable success. Итог проверяется через
Tools/analyze_mtproxy_markers.py; verdict
connected_without_socket_connected_marker означает, что Java увидела
connected-state без подтверждённого native socket marker.
Нативный Telegram WSS
WSS — настоящий TLS + WebSocket transport, а не FakeTLS и не локальный proxy bridge. Он включается одним глобальным флажком:
Настройки → Данные и память → Прокси → Использовать WSS транспорт
Новая установка начинает с выключенным WSS. При миграции старый выбранный WSS
режим превращается в этот флажок, а устаревшие host, port, path, SOCKS и
MiniApp-поля удаляются схемой proxy config V4.
Как строится route
- production DC1–DC5 используют
kwsN.web.telegram.org; - media/download/upload соединения используют соответствующий
kwsN-1.web.telegram.org; - путь WebSocket —
/apiws, subprotocol —binary; - route, DNS, TLS SNI и hostname verification используют один официальный hostname; ручной таблицы relay IP нет;
- WSS не наследует адрес или secret от выбранного TCP/MTProxy
dcOption; - obfuscated init и каждый готовый abridged MTProto packet отправляются отдельными binary WebSocket messages;
- test backend, неизвестные и CDN DC остаются на обычном транспорте;
- пока WSS не умеет маршрутизировать CDN DC ids, клиент не объявляет поддержку CDN redirects для загрузок в этом режиме.
Что проверяет WSS socket
- TLS не ниже 1.2;
- цепочку сертификата через Android и встроенные root certificates;
- hostname через SNI и
SSL_set1_host; - HTTP status
101и точныйSec-WebSocket-Accept; - размеры входных/выходных буферов и WebSocket frames;
- masked client frames, binary/continuation frames и ping/pong.
В новой конструкции отсутствуют custom WSS gateway, SOCKS upstream, режим
«SOCKS внутри WSS», MiniApp bridge и локальный relay на 127.0.0.1. Это
намеренно: WSS — простой официальный транспорт клиента, а список Telegram
proxy остаётся отдельным.
Пользовательские функции
ZaSto Приватность
Отдельный экран управляет клиентскими override-функциями:
- сохранять удалённые сообщения;
- сохранять view-once и самоуничтожающиеся материалы;
- хранить локальную историю редактирования сообщений;
- разрешать сохранение и пересылку защищённого контента и историй;
- разрешать скриншоты и не отправлять screenshot ping в секретном чате;
- отключать рекламные и промо-поверхности Telegram.
Это локальное поведение клиента, а не изменение серверной политики Telegram и не полноценная система архивирования.
Остальные изменения
- скрытие stories row и кнопки создания истории на главном экране;
- опция скрытия вкладки «Все чаты», когда создана хотя бы одна пользовательская папка, с переключением на первую доступную папку;
- опция «Всегда держать сеть в фоне» без вызова клиентского
native_pauseNetwork(); - online presence отправляет только выбранный аккаунт;
- кнопка прокси доступна в обычном login-flow до настройки прокси;
- контакты не вызывают автоматический prompt доступа при открытии;
- домашний DC показывается в профиле, если его можно надёжно определить;
- Android 12+ splash использует логотип ZaStoGram;
- файловые логи очищаются при старте нового процесса;
- ссылки на канал, VPN, поддержку и управляемая sponsor-строка
Zapret VPNs.
Плагины exteraGram
ZaStoGram запускает .plugin-файлы внутри приложения через CPython 3.11 и
Chaquopy. Установка:
Настройки → Плагины → + → выбрать .plugin файл
Реализованы:
- lifecycle
on_plugin_load()/on_plugin_unload(); - нативные экраны
create_settings(); client_utils,android_utils,hook_utils,file_utils,ui.alertиui.bulletin;send_request()иRequestCallback;requests, Pillow/PIL иpyfigletвнутри APK;- Java hooks через Pine и Xposed-compatible API;
- post-response hook для пропуска, замены или отмены ответа.
Совместимость покрывает только реализованную поверхность exteraGram. Плагин с другими API нужно адаптировать. Устанавливайте только доверенные плагины: они выполняются внутри процесса Telegram и могут менять UI, сеть и данные аккаунта.
Обновления и релизы
В APK встраиваются канал, тег Forgejo и номер сборки. Обновлятор выбирает файл по
Build.SUPPORTED_ABIS и не предлагает уже установленный тег.
| Канал | Package ID / имя | Forgejo Release | Логи | Назначение |
|---|---|---|---|---|
stable |
org.zastogram.messenger / ZaStoGram |
Обычный release с semver-тегом, например 1.1.1 |
Выключены по умолчанию | Повседневная установка |
dev |
org.zastogram.messenger.dev / ZaStoGram Dev |
Prerelease zastogram-apk-<run>-<attempt> |
MTProxy network logs включены | Диагностика и тестирование |
Android versionName следует версии upstream Telegram, а версия ZaStoGram
задаётся встроенным release tag. versionCode включает upstream code, номер
сборки Forgejo Actions и ABI-цифру, поэтому новые сборки устанавливаются поверх
старых в правильном порядке.
Push в master запускает фоновую проверочную сборку трёх релизных ABI в Forgejo
Actions. Публикация stable/dev-релиза остаётся локальным процессом: он собирает
и проверяет все три APK, подписанные восстановленным production-ключом, и
загружает именно эти файлы в Forgejo Releases.
Forgejo Actions требует отдельные Telegram API credentials из repository
secrets TELEGRAM_API_ID и TELEGRAM_API_HASH. Публичная тестовая пара
Telegram запрещена релизным guard: без обоих secrets проверочная сборка
завершится ошибкой. Если собрать проект локально без своих параметров подписи,
будет использован публичный dummy key из репозитория; такой APK не заменит
сборку, подписанную production-ключом.
Сборка из исходников
Нужны JDK 17, Android SDK 35, build-tools 35.0.0, NDK 27.2.12479018 и CMake
3.10.2.4988404. Для быстрого повторного native-build рекомендуется ccache.
git clone --recursive https://git2.zapret.moe/zastogram/ZaStoGram.git
cd ZaStoGram
git submodule update --init --recursive --depth=1
Получите собственные api_id и api_hash в
Telegram API development tools и сохраните их
вне репозитория:
# ~/.config/zastogram-signing/telegram-api.properties (права 0600)
TELEGRAM_API_ID=12345678
TELEGRAM_API_HASH=0123456789abcdef0123456789abcdef
Вместо файла можно передать TELEGRAM_API_ID и TELEGRAM_API_HASH через
окружение. Локальный релиз и Forgejo Actions отказываются собирать APK с
публичной тестовой парой Telegram.
Пример локальной arm64-сборки:
export ANDROID_HOME=/opt/android-sdk
export ANDROID_SDK_ROOT=/opt/android-sdk
export USE_CCACHE=1
export CCACHE_DIR="$HOME/.cache/zastogram-ccache"
./gradlew --build-cache \
--no-configuration-cache \
--parallel \
-PzastoAbiFilter=arm64-v8a \
:TMessagesProj_AppStandalone:assembleArm64Standalone
Gradle task-output cache уже включён для всего проекта. ccache повторно
использует неизменившиеся C/C++-объекты даже после потери каталога .cxx.
Configuration cache намеренно выключен: задачи Chaquopy 16.1 с ним пока
несовместимы. Каждая ABI собирается отдельным запуском Gradle: при совместной
конфигурации Chaquopy упаковывает runtime всех выбранных архитектур в каждый
APK. Повторные запуски используют тот же Gradle daemon, task-output cache и
ccache, поэтому кэш ускоряет сборку, но не попадает в готовое приложение.
zastoAbiFilters и одновременный запуск нескольких standalone ABI-задач
намеренно запрещены.
По умолчанию собирается stable. Для параллельно устанавливаемой dev-сборки
передайте ZASTO_UPDATE_CHANNEL=dev; package id, Android label и встроенный
update-channel переключатся вместе:
ZASTO_UPDATE_CHANNEL=dev ./gradlew --build-cache \
-PzastoAbiFilter=arm64-v8a \
:TMessagesProj_AppStandalone:assembleArm64Standalone
APK появится в:
TMessagesProj_AppStandalone/build/outputs/apk/arm64/standalone/app.apk
Перед собственной публикацией настройте отдельные Telegram api_id/api_hash
и release keystore. Не публикуйте APK с чужой API-парой или публичным dummy key
как официальный релиз своего форка.
Проверки
Основной MTProxy suite:
python3 Tools/check_mtproxy_all.py
Ключевые соседние guards:
python3 Tools/check_wss_transport_mode.py
python3 Tools/check_wss_official_default.py
python3 Tools/check_build_apk_workflow.py
python3 Tools/check_forgejo_update_contract.py
python3 Tools/check_plugin_client_utils_contract.py
python3 Tools/check_plugin_python_deps.py
python3 Tools/check_runtime_resilience.py
Guards проверяют не только наличие строк, но и границы модулей, wire-контракты, JNI-сигнатуры, partial writes, retry ownership, WSS TLS/WebSocket invariants и release identity. Они не заменяют установку APK и проверку на реальной сети.
Диагностика MTProxy
Dev APK включает подробные сетевые маркеры. На Windows/WSL лог можно собрать готовым скриптом:
D:\bin\platform-tools\adb.exe devices -l
powershell.exe -NoProfile -ExecutionPolicy Bypass \
-File "$(wslpath -w Tools/collect_mtproxy_logs.ps1)" \
-Adb "D:\bin\platform-tools\adb.exe" \
-Package org.zastogram.messenger \
-Seconds 180
Основные результаты:
mtproxy_markers.txt— события native/Java по времени;mtproxy_analysis.txt— попытки и terminal phase;mtproxy_runtime_contract.txt— проверка handshake/data-path инвариантов;mtproxy_attempts.csv— отдельные FakeTLS-попытки;mtproxy_endpoint_profile_stats.csv— агрегат endpoint + profile;mtproxy_plain_account_stats.csv— обычныеdd/legacy соединения;mtproxy_proxy_check_stats.csvиmtproxy_scheduler_stats.csv— проверки и control plane.
Повторная проверка сохранённой сессии:
python3 Tools/verify_mtproxy_runtime_logs.py mtproxy-logs-live/<session>
mtproxy_runtime_contract.txt подтверждает порядок live-маркеров и наличие
transport_state=. Сначала фиксируется endpoint_handshake_ok.
endpoint_data_path_success должен появляться только после первого first_tls_app_recv
для FakeTLS либо после first_mtproxy_packet_recv для обычного MTProxy.
Stable APK не включает принудительные сетевые логи.
Ограничения
- FakeTLS делает старт MTProxy похожим на TLS, но не превращает MTProto в настоящий браузерный HTTP/2 или HTTP/1.1.
- SNI берётся из
ee-секрета и не ротируется независимо от него. - Record sizing, timing, fragmentation и startup cover — диагностические режимы, а не доказанная универсальная защита от любого DPI.
- Официальный WSS работает только для route'ов Telegram DC1–DC5. Test, неизвестные и CDN DC используют обычный fallback transport.
- Встроенный WSS не поддерживает custom gateway или SOCKS upstream.
- Фоновая сеть не отменяет Doze, battery saver и остановку процесса Android.
- Плагины имеют привилегии процесса приложения и требуют доверия к автору.
- Это неофициальный форк и не гарантия постоянного обхода меняющихся правил фильтрации.
Основа и благодарности
- DrKLO/Telegram — официальный Telegram Android;
- tsrman/tg — рабочая база изменений FakeTLS, JA4 и интервалов;
- telemt/tdlib-obf — идеи и референсы по профилям, DRS/IPT и диагностике.
Проект распространяется по условиям GPL-2.0.
