Files
tglock/docs/ARCHITECTURE_V2.md
T
Никита Sonic b06272437c fix(gui): просить программный рендер, чтобы окно создавалось без 3D (#28)
Интерфейс построен на системном WebView, а тот без 3D-ускорения окно не
создаёт. Отсюда весь класс жалоб: не стартует в виртуалке, не стартует с
дефолтным драйвером Microsoft, не стартует без монитора. Диагноз в #17 дал
@de4me: в VirtualBox приложение запускается только после включения галочки
«Включить ускорение 3D».

Перед стартом Tauri TGLock теперь сам запрашивает программный рендер:
- Windows: WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS с --disable-gpu
  и --disable-gpu-compositing;
- Linux: WEBKIT_DISABLE_COMPOSITING_MODE и WEBKIT_DISABLE_DMABUF_RENDERER;
- macOS: не требуется, WebKit сам уходит в программный рендер.

Для панели со статусом программный рендер не стоит ничего заметного, поэтому
он выбран значением по умолчанию, а не аварийным режимом. Уже заданные
оператором переменные не перезаписываются, TGLOCK_FORCE_GPU=1 отключает
механизм целиком.

Логика вынесена в чистую функцию software_rendering_vars и покрыта четырьмя
тестами: значение по умолчанию, отключение через TGLOCK_FORCE_GPU, уважение
чужой переменной и правильный набор ключей на каждой платформе.

Версия поднята до 2.0.0-beta.2 в Cargo.toml, package.json и tauri.conf.json:
нужен тег, чтобы в релиз попали и tglock-cli, и этот фикс.

README получил отдельный вопрос в FAQ про «окно не появляется»,
ARCHITECTURE_V2.md — обновлённый пункт в Current limitations.

Co-authored-by: by-sonic <171230345+by-sonic@users.noreply.github.com>
2026-07-30 13:40:04 +03:00

129 lines
8.8 KiB
Markdown
Raw 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.
# TGLock 2.0 architecture
## Сборка: ядро, GUI и headless
Крейт собирается в библиотеку и два бинаря:
- `src/lib.rs` — ядро: `mtproto`, `transport`, `proxy`, `config`. Не зависит ни
от Tauri, ни от оконной системы;
- `src/main.rs` — GUI, доступен только при включённой фиче `gui`
(`required-features`);
- `src/bin/cli.rs` — headless `tglock-cli`.
Фича `gui` включена по умолчанию и подтягивает `tauri`, `tauri-build` и `open`.
При `--no-default-features` ни Tauri, ни системный WebView, ни фронтенд в сборку
не попадают, и `build.rs` не вызывает `tauri_build`. Так TGLock собирается и
работает там, где WebView недоступен в принципе: сервер без графического
окружения, контейнер, машина без монитора. Для случаев, где WebView есть, но нет
3D-ускорения, GUI дополнительно просит программный рендер — см. Current
limitations.
## Local protocols
Один TCP-порт автоматически принимает два типа клиентов:
- MTProto proxy с постоянным 16-байтовым secret — основной режим;
- SOCKS5 без авторизации — режим совместимости.
MTProto init проверяется по secret и transport tag. Из него извлекаются DC,
признак media-соединения и тип транспорта. Для upstream создаётся новый
стандартный obfuscated2 init, а последующий поток пере-шифровывается между
локальным secret и Telegram.
### Различение протоколов
Определять протокол по первому байту нельзя. SOCKS5-приветствие начинается с
`0x05`, но MTProto init — это 64 случайных байта, и `is_reserved_init`
исключает только `0xef`, `0xee`, `0xdd`, HTTP-глаголы и заголовок TLS-записи.
Значение `0x05` попадается примерно в одном init из 256, и такое соединение
уходило в SOCKS5-ветку и умирало — снаружи это выглядит как «Telegram
отправляет сообщения через раз».
Поэтому неоднозначный первый байт разрешается так: не потребляя данные,
ожидается полный 64-байтовый init и делается попытка разобрать его под текущим
secret. Успешный разбор означает MTProto. Настоящий SOCKS5-клиент присылает
короткое приветствие и блокируется на ответе, поэтому 64 байта у него не
появятся и по истечении короткого таймаута он корректно уходит в SOCKS5-ветку.
## Политика прямого релея
Не-Telegram адреса релеятся напрямую, без шифрования, и пользы для обхода в
этом нет. Поэтому такой релей разрешён только когда прокси слушает loopback,
где до него дотягиваются лишь локальные процессы. На `0.0.0.0` и любом другом
сетевом адресе не-Telegram запросы отклоняются кодом SOCKS5 `0x02`, иначе
LAN-режим превращал бы машину в открытый прокси. Правило выражено в типе
`config::ListenConfig`, а не в условиях по месту вызова; переопределяется
только явным `--allow-direct` в CLI.
## Учёт состояния
`Stats::ws` считает **установленные** туннели: счётчик поднимается после
успешного `transport.connect`, а не перед попыткой. Иначе интерфейс
рапортовал бы «Telegram на связи», пока рукопожатие ещё перебирает маршруты по
несколько секунд каждый. Состояния «порт открыт», «идёт перебор маршрутов» и
«туннель установлен» различимы и в GUI, и в выводе CLI.
Секрет прокси — половина ссылки `tg://proxy`. Для сервиса его нужно закрепить
файлом (`--secret-file`): под `DynamicUser` и `ProtectHome` домашней папки нет,
путь по умолчанию не определяется, и секрет генерировался бы заново при каждом
старте, отключая всех уже настроенных клиентов.
## Transport cascade
Для каждого DC и отдельно для media-соединений строится список маршрутов:
1. сохранённый успешный маршрут;
2. точный Telegram IP с `kwsN` или `kwsN-1` в TLS SNI и WebSocket Host;
3. дополнительный Telegram IP, если он определён;
4. системный DNS;
5. явно настроенный пользователем Cloudflare Worker.
Поддерживаются DC15 и media/CDN DC203. DC203 использует WebSocket-host DC2,
но подключается к собственному IP.
После ошибки маршрут получает exponential cooldown от 30 секунд до 30 минут.
Успешный маршрут становится первым для следующего соединения того же DC и
типа трафика.
## TLS policy
Проверка сертификатов и hostname никогда не отключается. При подключении к
заданному Telegram IP TCP destination отделён от URI host: TLS продолжает
проверять сертификат настоящего `kws*.web.telegram.org`.
Cloudflare Worker принимается только как пользовательская настройка. TGLock
не загружает и не скрывает публичные списки чужих доменов.
## Cloudflare Worker contract
Worker должен принимать WebSocket на:
```text
/apiws?dst=<telegram-ip>&dc=<dc-id>
```
и проксировать бинарные frames в TCP `<telegram-ip>:443`. Рекомендуется
добавить собственную авторизацию до стабильного релиза; поэтому Worker
остаётся расширенной опцией alpha-версии.
## Current limitations
- SNI camouflage не включена: небезопасное отключение hostname verification
из референсной реализации не переносится.
- Голосовые звонки по UDP не поддерживаются.
- **GUI зависит от WebView, а тот — от 3D-ускорения.** Начиная с
2.0.0-beta.2 приложение перед стартом Tauri само просит программный рендер:
на Windows через `WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS`, на Linux через
`WEBKIT_DISABLE_COMPOSITING_MODE` и `WEBKIT_DISABLE_DMABUF_RENDERER`. Уже
заданные оператором значения не перезаписываются, а `TGLOCK_FORCE_GPU=1`
возвращает аппаратное ускорение. Для машин без монитора остаётся
`tglock-cli`, которому WebView не нужен вовсе (issues #10, #17).
- Windows-инсталлятор не подписан, macOS-сборка не нотарифицирована. Часть
антивирусов реагирует на неподписанный установщик, открывающий локальный
сокет; проверяемый ответ — сборка из исходников либо публичные логи
GitHub Actions.
- Работоспособность медиа зависит от конкретного DC аккаунта и доступности
Telegram/Cloudflare у провайдера.
- Пулы заранее открытых WebSocket-соединений будут добавлены после измерения,
что они не создают лишнюю нагрузку и не ухудшают стабильность.