Commit Graph

12 Commits

Author SHA1 Message Date
by-sonic 8491cf9292 chore(release): 2.0.0-beta.6
Файл настроек для headless-версии (#32, #35) и исправление падения демона при
закрытом stdout.
2026-07-30 20:19:47 +03:00
Никита Sonic 9429975403 feat(cli): файл настроек tglock.toml (#35)
* fix(bundle): спрятать CLI за фичей — beta.2 и beta.3 упаковывали не тот бинарь

Мой предыдущий фикс (mainBinaryName в #31) фиксом не был. Он изменил только
имя выходного файла: бандлер по-прежнему брал headless CLI и просто
переименовывал его в tglock. Проверено по содержимому опубликованных
артефактов, а не по имени:

  версия  файл в MacOS/  размер  признаки CLI       признаки GUI
  beta.1  tglock         17.8 МБ  нет               ipc.localhost, wry×3206
  beta.2  tglock-cli      4.3 МБ  tglock-cli×6      нет
  beta.3  tglock          4.3 МБ  tglock-cli×6      нет

То есть beta.3 тоже не запускается, и моя же проверка CFBundleExecutable это
пропустила, потому что сверяла имя.

Настоящая причина найдена воспроизведением локально. Ломается только при явном
--target: без него бандлер выбирает GUI, с ним — CLI. Локальная сборка, на
которой я объявил фикс подтверждённым, шла без --target, а обе сборки в CI — с
ним. Обобщение было неправомерным.

Исправление убирает саму возможность выбора: CLI спрятан за фичей cli, которой
нет в default. При сборке приложения второго бинаря просто не существует.

Проверено против воспроизведённой поломки:
  до : tglock.exe 1.7 МБ, признаки CLI, GUI нет
  после: tglock.exe 9.0 МБ, признаки GUI, CLI нет, tglock-cli.exe не собран

Проверки переписаны на содержимое:
- release.yml распаковывает .app и .deb и ищет ipc.localhost (есть только в
  GUI) и allow-direct (есть только в CLI). Поймала бы и beta.2, и beta.3;
- новая задача CI bundle собирает бандл с явным --target aarch64-apple-darwin
  и проверяет его так же. Ловит до публикации, а не после;
- заодно исправлен шаблон grep для .deb: dpkg-deb -c выводит путь без ./, из-за
  чего проверка ложно падала на исправной сборке.

Команда сборки CLI теперь требует --features cli; обновлены README, ci.yml и
release.yml.

* fix(ci): одна проверка бандла на Python вместо трёх копий grep

Проверка содержимого бандла, добавленная в #33, работала на Linux и давала
ложное «в бандле не GUI» на macOS. Причина в BSD grep: в UTF-8-локали он молча
не находит строки в бинарных данных там, где GNU grep находит. Из-за этого
задача macOS в релизе beta.4 упала уже после загрузки артефактов, а вместе с
ней снова пропустилась задача с CLI-бинарями.

Сами артефакты beta.4 при этом корректны — проверено скачиванием: в бандле
tglock на 20.3 МБ, universal/fat, признаки GUI на месте, признаков CLI нет.
Не хватает только tglock-cli-*.

Проверка вынесена в scripts/verify_bundle_binary.py и вызывается из всех трёх
мест: задачи CI bundle, проверки macOS и проверки Linux в релизе. Один скрипт
вместо трёх копий шелл-кода исключает и платформенные различия grep, и
расхождение копий между собой.

Скрипт проверен на реальных исторических артефактах:
  beta.4 (исправный)  → код 0
  beta.3 (сломанный)  → код 1, найдены allow-direct и secret-file
  beta.2 (сломанный)  → код 1, то же

* feat(cli): файл настроек tglock.toml

Запрошено в #32: держать все параметры и секрет в одном месте, чтобы не
собирать батник с ключами при каждом запуске.

Файл ищется рядом с бинарём под именем tglock.toml — как и просили в ишью, —
либо указывается через --config. Приоритеты: значения по умолчанию → файл →
флаги. Флаги-переключатели могут только включать: отсутствие --quiet не
отменяет quiet = true из файла, иначе файлом нельзя было бы ничего включить.

Секрет можно вписать прямо в конфиг, в том числе в форме с префиксом dd — то
есть скопировав из напечатанной ссылки tg://proxy. Отдельный secret_file
остаётся, inline-секрет важнее.

deny_unknown_fields намеренно: опечатка вроде porrt = 1443 останавливает старт
с перечислением допустимых полей. Сервис, который из-за опечатки слушает 1080
вместо 1443, хуже сервиса, который не запустился. Явный --config к
несуществующему файлу тоже ошибка, а не тихий откат к настройкам по умолчанию.

Если секрет не закреплён ни одним из способов, CLI печатает предупреждение:
после перезапуска ссылка станет другой и настроенные клиенты отвалятся.

Найдено при живом прогоне и исправлено здесь же: демон падал, если stdout
закрывался. println! при ошибке записи паникует, а канал закрывается штатно —
`| head`, закрытый терминал, перезапуск сборщика логов. Воспроизводилось
одной командой:

  tglock-cli --port 18101 | head -2
  thread 'tokio-rt-worker' panicked at stdio.rs: failed printing to stdout

Печать переведена на say(), который возвращает признак успеха; наблюдатель
статуса при закрытом stdout просто прекращает печатать, туннель продолжает
работать.

Тестов в CLI стало 26 вместо 12: приоритеты, конфликт lan и bind из разных
источников, обе формы записи секрета, отказ на опечатке и на битых значениях,
комментарии в файле. Плюс parse_secret в ядре с проверкой того, что секрет,
сам начинающийся с dd, не теряет первый байт.

В CI добавлены три шага: чтение настроек из файла, перекрытие флагом и отказ
на опечатке; отдельно — проверка, что закрытый stdout не роняет демон.

Документация: секция про файл настроек в README, полный пример с пояснениями в
tglock.example.toml, юнит systemd переведён на --config.

* fix: вернуть плоский путь бинаря, модуль настроек — в библиотеку

Проверка бандла в CI упала на этом PR:

  failed to rename app binary .../release/cli: No such file or directory

Причина моя. Я перенёс CLI в каталожную форму src/bin/cli/main.rs, и
перечисление бинарей в Tauri вывело имя приложения из имени каталога —
получилось "cli", которого не существует. Явное name = "tglock-cli" в
[[bin]] при этом игнорируется. До переноса, при плоском src/bin/cli.rs,
всё собиралось.

Путь бинаря вернулся к src/bin/cli.rs, а модуль настроек переехал в
библиотеку как cli_settings под фичей cli. Ему там и место: он работает с
ListenConfig, mtproto и proxy, а clap не использует вовсе.

Проверено воспроизведением того же условия локально — сборка бандла с явным
--target: приложение собирается, скрипт проверки подтверждает GUI-бинарь
(9.0 МБ, ipc.localhost и wry на месте, признаков CLI нет).

Тестов: 66 в библиотеке с фичей cli, 12 в бинаре, clippy чист в обоих
вариантах сборки. Живой прогон с конфигом и отказ на опечатке сохранились.

---------

Co-authored-by: by-sonic <171230345+by-sonic@users.noreply.github.com>
2026-07-30 20:19:31 +03:00
Никита Sonic 4ae755c6ae fix(ci): одна проверка бандла на Python вместо трёх копий grep (#34)
* fix(bundle): спрятать CLI за фичей — beta.2 и beta.3 упаковывали не тот бинарь

Мой предыдущий фикс (mainBinaryName в #31) фиксом не был. Он изменил только
имя выходного файла: бандлер по-прежнему брал headless CLI и просто
переименовывал его в tglock. Проверено по содержимому опубликованных
артефактов, а не по имени:

  версия  файл в MacOS/  размер  признаки CLI       признаки GUI
  beta.1  tglock         17.8 МБ  нет               ipc.localhost, wry×3206
  beta.2  tglock-cli      4.3 МБ  tglock-cli×6      нет
  beta.3  tglock          4.3 МБ  tglock-cli×6      нет

То есть beta.3 тоже не запускается, и моя же проверка CFBundleExecutable это
пропустила, потому что сверяла имя.

Настоящая причина найдена воспроизведением локально. Ломается только при явном
--target: без него бандлер выбирает GUI, с ним — CLI. Локальная сборка, на
которой я объявил фикс подтверждённым, шла без --target, а обе сборки в CI — с
ним. Обобщение было неправомерным.

Исправление убирает саму возможность выбора: CLI спрятан за фичей cli, которой
нет в default. При сборке приложения второго бинаря просто не существует.

Проверено против воспроизведённой поломки:
  до : tglock.exe 1.7 МБ, признаки CLI, GUI нет
  после: tglock.exe 9.0 МБ, признаки GUI, CLI нет, tglock-cli.exe не собран

Проверки переписаны на содержимое:
- release.yml распаковывает .app и .deb и ищет ipc.localhost (есть только в
  GUI) и allow-direct (есть только в CLI). Поймала бы и beta.2, и beta.3;
- новая задача CI bundle собирает бандл с явным --target aarch64-apple-darwin
  и проверяет его так же. Ловит до публикации, а не после;
- заодно исправлен шаблон grep для .deb: dpkg-deb -c выводит путь без ./, из-за
  чего проверка ложно падала на исправной сборке.

Команда сборки CLI теперь требует --features cli; обновлены README, ci.yml и
release.yml.

* fix(ci): одна проверка бандла на Python вместо трёх копий grep

Проверка содержимого бандла, добавленная в #33, работала на Linux и давала
ложное «в бандле не GUI» на macOS. Причина в BSD grep: в UTF-8-локали он молча
не находит строки в бинарных данных там, где GNU grep находит. Из-за этого
задача macOS в релизе beta.4 упала уже после загрузки артефактов, а вместе с
ней снова пропустилась задача с CLI-бинарями.

Сами артефакты beta.4 при этом корректны — проверено скачиванием: в бандле
tglock на 20.3 МБ, universal/fat, признаки GUI на месте, признаков CLI нет.
Не хватает только tglock-cli-*.

Проверка вынесена в scripts/verify_bundle_binary.py и вызывается из всех трёх
мест: задачи CI bundle, проверки macOS и проверки Linux в релизе. Один скрипт
вместо трёх копий шелл-кода исключает и платформенные различия grep, и
расхождение копий между собой.

Скрипт проверен на реальных исторических артефактах:
  beta.4 (исправный)  → код 0
  beta.3 (сломанный)  → код 1, найдены allow-direct и secret-file
  beta.2 (сломанный)  → код 1, то же

---------

Co-authored-by: by-sonic <171230345+by-sonic@users.noreply.github.com>
2026-07-30 16:26:32 +03:00
Никита Sonic ed121d0968 fix(bundle): спрятать CLI за фичей — beta.2 и beta.3 упаковывали не тот бинарь (#33)
Мой предыдущий фикс (mainBinaryName в #31) фиксом не был. Он изменил только
имя выходного файла: бандлер по-прежнему брал headless CLI и просто
переименовывал его в tglock. Проверено по содержимому опубликованных
артефактов, а не по имени:

  версия  файл в MacOS/  размер  признаки CLI       признаки GUI
  beta.1  tglock         17.8 МБ  нет               ipc.localhost, wry×3206
  beta.2  tglock-cli      4.3 МБ  tglock-cli×6      нет
  beta.3  tglock          4.3 МБ  tglock-cli×6      нет

То есть beta.3 тоже не запускается, и моя же проверка CFBundleExecutable это
пропустила, потому что сверяла имя.

Настоящая причина найдена воспроизведением локально. Ломается только при явном
--target: без него бандлер выбирает GUI, с ним — CLI. Локальная сборка, на
которой я объявил фикс подтверждённым, шла без --target, а обе сборки в CI — с
ним. Обобщение было неправомерным.

Исправление убирает саму возможность выбора: CLI спрятан за фичей cli, которой
нет в default. При сборке приложения второго бинаря просто не существует.

Проверено против воспроизведённой поломки:
  до : tglock.exe 1.7 МБ, признаки CLI, GUI нет
  после: tglock.exe 9.0 МБ, признаки GUI, CLI нет, tglock-cli.exe не собран

Проверки переписаны на содержимое:
- release.yml распаковывает .app и .deb и ищет ipc.localhost (есть только в
  GUI) и allow-direct (есть только в CLI). Поймала бы и beta.2, и beta.3;
- новая задача CI bundle собирает бандл с явным --target aarch64-apple-darwin
  и проверяет его так же. Ловит до публикации, а не после;
- заодно исправлен шаблон grep для .deb: dpkg-deb -c выводит путь без ./, из-за
  чего проверка ложно падала на исправной сборке.

Команда сборки CLI теперь требует --features cli; обновлены README, ci.yml и
release.yml.

Co-authored-by: by-sonic <171230345+by-sonic@users.noreply.github.com>
2026-07-30 16:08:56 +03:00
Никита Sonic af3b14395f fix(bundle): в v2.0.0-beta.2 упаковывался CLI вместо приложения (#31)
Симптом: на macOS приложение не запускается совсем — иконка подпрыгивает в
доке и гаснет, хотя разрешение выдано.

Причина. В #25 в крейте появился второй бинарь tglock-cli, а mainBinaryName в
tauri.conf.json задан не был. Бандлер Tauri выбрал главным исполняемым файлом
приложения headless CLI. Запуск .app стартовал консольный прокси, окна не
создавалось.

Проверено на опубликованных артефактах:

  CFBundleExecutable   размер MacOS/*
  beta.1  tglock       18.6 МБ   ← GUI, правильно
  beta.2  tglock-cli    4.5 МБ   ← консольный прокси

Задеты все платформы, не только macOS. В .deb лежит usr/bin/tglock-cli, а в
TGLock.desktop прописан Exec=tglock-cli. Установщик Windows упал с 2.0 МБ до
0.6 МБ — тот же признак. То есть beta.2 не запускается нигде.

Почему это уехало с зелёным CI: сборка релиза была успешной, потому что никто
не проверял, что внутри бандла. Тесты гоняют ядро, а не собранное приложение.

Исправление: mainBinaryName = "tglock" в tauri.conf.json. Проверено сборкой на
этой же ветке — Tauri берёт tglock.exe, установщик вернулся к нормальному
размеру.

Чтобы это не повторилось, добавлены две проверки:
- в CI, на каждый PR: mainBinaryName обязан совпадать с именем [[bin]], у
  которого required-features = ["gui"]. Проверено в обе стороны — на верном
  конфиге проходит, на подставленном tglock-cli падает;
- в release.yml, после сборки: на macOS читается CFBundleExecutable из
  Info.plist, на Linux проверяется наличие /usr/bin/tglock в .deb. Смотрит
  внутрь настоящего артефакта, а не в конфиг.

README: пример команды с хешем больше не прибит к конкретной версии, ссылка на
запуск сборки заменена на общее указание, и добавлена строка для тех, кто уже
скачал beta.2 и не смог её открыть.

Co-authored-by: by-sonic <171230345+by-sonic@users.noreply.github.com>
2026-07-30 15:40:18 +03:00
Никита 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
Никита Sonic 55653ed0bc feat(cli): headless tglock-cli, GUI behind a feature, deep test coverage (#25)
Реализует направление PR #15 поверх архитектуры 2.0. Сам PR смерджить нельзя:
он патчит src/bypass.rs, src/network.rs и src/ws_proxy.rs, которых больше нет,
и правит системный DNS — в 2.0 это не нужно, потому что адреса Telegram зашиты
в маршрутах, а SNI остаётся настоящим. Взято разделение GUI/CLI и произвольный
bind-адрес, отброшены DNS-менеджмент и проверка root: CLI не требует прав.

Closes #10, #17 — GUI не создаёт окно без 3D-ускорения, на машине без монитора
и в виртуалке. Причина в WebView под Tauri, поэтому лечится не программным
рендером, а бинарём, в котором WebView нет вовсе: при выключенной фиче gui
Tauri и фронтенд в сборку не попадают. Отдельная задача CI собирает и гоняет
CLI на голом ubuntu без Node.js и без libwebkit2gtk.

Структура:
- src/lib.rs — ядро (mtproto, proxy, transport, config), без Tauri
- src/main.rs — GUI, required-features = ["gui"]
- src/bin/cli.rs — headless-бинарь на clap
- build.rs вызывает tauri_build только при включённой фиче gui

Исправлено по пути:
- Определение протокола: SOCKS5 и MTProto различались по первому байту, но
  is_reserved_init не исключает 0x05, поэтому примерно одно соединение из 256
  уезжало в SOCKS5-ветку и умирало. Теперь неоднозначный первый байт решается
  по полному 64-байтному init и секрету.
- Ярлык маршрута в UI: код 2 подписывался как «Cloudflare Worker», хотя это
  запасной Telegram IP, а системный DNS и настоящий Worker оба показывались
  как «Автоматический маршрут». Метки переехали в transport::route_label,
  общий для обоих интерфейсов.
- Секрет прокси: под DynamicUser и ProtectHome домашней папки нет, secret_path
  возвращает None и секрет генерировался заново при каждом старте, ломая всем
  настроенным клиентам tg://-ссылку. Добавлен --secret-file.
- README обещал Rust 1.75+, тогда как Cargo.toml требует 1.88 и CI это
  проверяет. Это и есть первопричина #3.

Политика доступа: прямые не-Telegram соединения разрешены только на loopback,
на любом сетевом адресе нужен явный --allow-direct. Правило из ISSUE_AUDIT о
том, что LAN не должен становиться открытым SOCKS5, теперь выражено в типе
ListenConfig и покрыто тестами.

Тесты: 46 в библиотеке + 12 в CLI. Появился сквозной тест туннеля против
мок-релея, который реализует сторону Telegram по obfuscated2 — проверяется
не внутренняя консистентность, а что реле получает ровно тот открытый текст,
который отправил клиент, и обратно. Плюс расписание backoff, фолбэк при всех
маршрутах в cooldown, валидация Worker-доменов, отказы SOCKS5, устойчивость
секрета к перезапуску и корректная остановка по SIGTERM.

Документация: секция CLI в README с юнитом systemd и Dockerfile.

Co-authored-by: by-sonic <171230345+by-sonic@users.noreply.github.com>
2026-07-30 13:12:21 +03:00
Никита Митусов c25bea1d92 feat: rebuild TGLock with adaptive transport and Tauri UI 2026-07-29 15:22:54 +03:00
by-sonic 09b7a03a0a v1.0.0: Clean rewrite — cross-platform, dark UI, stable WS tunnel
Made-with: Cursor:
2026-04-08 14:56:50 +03:00
by-sonic c40ad94e11 v0.3.1: Fix WebSocket keepalive - respond to Ping with Pong
Made-with: Cursor:
2026-03-17 12:38:30 +03:00
by-sonic fd9e2351c3 v0.3.0: Fix DC detection from obfuscated2 init, use kws endpoints
Made-with: Cursor:
2026-03-17 12:32:49 +03:00
by-sonic d0646af85d TG Unblock v0.2.0: Telegram WebSocket bypass proxy
Made-with: Cursor:
2026-03-16 23:54:42 +03:00