Files
minivless/README.md
T

171 lines
17 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.
# MiniVLESS
Маленький персональный Linux-клиент: Tauri 2, Rust, React/TypeScript и отдельный sing-box **1.14.x**. Подключается по VLESS-ссылке к совместимым серверам, в том числе Xray. GUI всегда работает от обычного пользователя.
[Скачать Linux-релиз](https://github.com/emil28092005/minivless/releases/latest)
![Дизайн интерфейса MiniVLESS](design/approved-dark.png)
## Установка готового релиза
Скачайте `MiniVLESS_0.1.1_amd64.deb` из Releases и выполните из каталога загрузки:
```bash
sudo apt install ./MiniVLESS_0.1.1_amd64.deb libcap2-bin
sudo setcap cap_net_admin,cap_net_raw+ep /usr/lib/MiniVLESS/binaries/sing-box
```
Запустите MiniVLESS из меню приложений. Пакет содержит sing-box 1.14.0; capabilities назначаются отдельно и только ему. Если раньше был установлен `/usr/local/lib/minivless/sing-box`, он имеет приоритет — проверьте права именно этого файла. Релиз пока собран для Linux x86_64; это не сборка для Windows/macOS. Контрольные суммы — в `SHA256SUMS` рядом с пакетом.
## Использование
1. Вставьте `vless://…` — ссылка скрыта и сохраняется только локально.
2. Выберите режим:
- **Tunneling включён:** VPN только для отмеченных программ. Остальной трафик — DIRECT.
- **Tunneling выключен:** VPN для всей системы, независимо от списка программ.
3. `Refresh` обновляет запущенные приложения. `Add application` позволяет выбрать установленную программу или указать абсолютный путь к её настоящему ELF-бинарнику.
4. Нажмите `Connect`. `Disconnect` останавливает core и освобождает TUN.
5. Кнопка **−** в заголовке скрывает окно в системный трей, сохраняя подключение. В меню значка доступны **Show MiniVLESS**, **Disconnect** и **Quit**. Крестик и Quit полностью завершают приложение и останавливают VPN.
Если системный трей недоступен (например, GNOME без расширения AppIndicator), кнопка − сворачивает окно в панель задач, откуда его можно вернуть. Для значка трея требуется поддержка StatusNotifier/AppIndicator в рабочем окружении.
Пути сохраняются независимо от PID. Несколько процессов одного исполняемого файла объединяются. Отмеченные/добавленные приложения остаются в списке после перезапуска. Переключатель меняет **выборочную маршрутизацию**, а не отключает TUN: TUN используется в обоих режимах.
## Требования Linux
- Linux с `/dev/net/tun`, nftables и IPv4/IPv6; kernel NFQUEUE (`nfnetlink_queue`, `nft_queue`) нужен для предварительного сопоставления правил sing-box. При его отсутствии core может использовать обычный TUN fallback.
- GTK 3, WebKitGTK 4.1, системный набор CA, libcap.
- Для сборки: Node.js 22+, npm, актуальный Rust stable, C/C++ toolchain, pkg-config.
- Для сетевых тестов: Python 3, OpenSSL, `ip`, `nft`, разрешённые unprivileged user namespaces.
Debian/Ubuntu:
```bash
sudo apt install build-essential pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev \
libayatana-appindicator3-dev librsvg2-dev patchelf libcap2-bin \
ca-certificates iproute2 nftables python3 openssl
```
## sing-box и права
Загрузчик получает фиксированный официальный релиз 1.14.0 для x86_64/aarch64 и проверяет SHA-256 по метаданным GitHub:
```bash
python3 scripts/fetch-sing-box.py
./binaries/sing-box version
```
Рекомендуется положить core в отдельный каталог с владельцем root, затем выдать capabilities **только ему**:
```bash
sudo install -D -o root -g root -m 0755 binaries/sing-box /usr/local/lib/minivless/sing-box
sudo setcap cap_net_admin,cap_net_raw+ep /usr/local/lib/minivless/sing-box
getcap /usr/local/lib/minivless/sing-box
```
Для локальной разработки допустимо:
```bash
sudo setcap cap_net_admin,cap_net_raw+ep "$(realpath binaries/sing-box)"
```
После замены/обновления бинарника capabilities нужно выставить заново. Файловая система должна поддерживать file capabilities и не блокировать их через `nosuid`. **Не запускайте MiniVLESS через sudo.** Приложение проверяет наличие core, его версию, TUN и capabilities; при ошибке показывает команду установки прав. Самостоятельно повышать права оно не пытается.
Порядок поиска core: `MINIVLESS_SING_BOX` (явное переопределение), `/usr/local/lib/minivless/sing-box`, ресурс установленного приложения, `binaries/sing-box` проекта в debug-сборке, `binaries/` рядом с исполняемым файлом, `/usr/bin/sing-box`, `/usr/local/bin/sing-box`. Переменная окружения задаёт только путь, не аргументы.
## Разработка и сборка
```bash
npm ci
npm run tauri -- dev
```
Один `npm run dev` запускает только браузерный предпросмотр; подключение в нём отключено.
```bash
npm run tauri -- build --bundles deb
```
Результаты:
- `src-tauri/target/release/minivless` — нативное приложение.
- `src-tauri/target/release/bundle/deb/*.deb` — Debian-пакет с core.
Установка пакета: `sudo apt install ./src-tauri/target/release/bundle/deb/*.deb`. Настройку capabilities выполните отдельно, как указано выше. Прямой запуск release-бинарника использует установленный `/usr/local/lib/minivless/sing-box`; можно также положить core в `binaries/` рядом с ним. AppImage не используется: файловые capabilities на смонтированном образе ненадёжны.
## Настройки и логи
Настройки: `$XDG_CONFIG_HOME/minivless/settings.json`, по умолчанию `~/.config/minivless/settings.json`.
Файл имеет права `0600`, каталог — `0700`; запись атомарная. Сохраняются ссылка, пути отмеченных/добавленных программ и положение переключателя. Повреждённые настройки не заменяются молча. Это локальный файл с credential, а не зашифрованное хранилище паролей.
Runtime-конфиг создаётся в приватном `runtime-*` под тем же каталогом и удаляется после остановки. Логи — только в памяти, максимум 300 строк по 4096 символов; credential и query-токены удаляются до показа. Полная ссылка не передаётся через аргументы процесса и не попадает в frontend logs. Раскрывающийся блок `Connection logs` показывает диагностику.
## Маршрутизация и DNS
Используется настоящий TUN sing-box, `auto_route`, Linux nftables `auto_redirect`, IPv4/IPv6 и точные правила `process_path`. В выборочном режиме TUN ограничен UID пользователя, а финальное правило — `direct`. В системном режиме ограничения UID нет, финальное правило — `proxy`. Интерфейс `minivless0`, routing table 2090; собственные routing marks/rules не совпадают со стандартными значениями sing-box.
DNS к внешним адресам, включая DNS в LAN, перехватывается средствами TUN/nftables. Запросы выбранных процессов идут по DoH через VLESS; остальные — по DoH напрямую. В системном режиме DNS идёт через VLESS. Используется `1.1.1.1` с проверкой TLS для `cloudflare-dns.com`; домен самого VLESS-сервера разрешается напрямую, чтобы не создавать петлю.
**Ограничение общего системного DNS:** при обращении программы к локальному `127.0.0.53` запрос в сеть отправляет systemd-resolved, а не исходная программа. В выборочном режиме такие запросы остаются у системного резолвера и идут DIRECT; установить исходную программу по этому сокету невозможно. Это может влиять на домены, блокируемые системным DNS. Прямые DNS/DoH-соединения выбранной программы маршрутизируются по её executable. В системном режиме исходящие DNS-запросы резолвера тоже входят в VPN. Loopback не перехватывается.
Настройки NetworkManager, resolv.conf и systemd-resolved не меняются. У pinned core отключён поиск внешних команд через `PATH`: это предотвращает автоматический вызов `resolvectl` в sing-tun, запросы Polkit и неявные изменения системных DNS-настроек. Используется native nftables backend; fallback через внешние iptables не поддерживается.
## Lifecycle
Перед стартом выполняется `sing-box check`. `Connected` означает, что core сообщил об успешном старте TUN; доступность конкретного удалённого сервера/credential проверяется реальным трафиком, это не результат speedtest или внешнего healthcheck. Ошибки соединений с сервером видны в логах.
Один backend state сериализует Connect/Disconnect. Файловые locks запрещают второй GUI и второй tunnel. Не используются shell-строки, `sh -c` или интерполяция пользовательского ввода. Аргументы передаются через `Command`.
GUI запускает маленький guardian в том же бинарнике. Он отслеживает открытый pipe GUI, посылает sing-box SIGTERM, ждёт до 3 секунд и при необходимости завершает его принудительно, затем удаляет runtime-файлы. Так core останавливается даже при SIGKILL GUI. Одного `PR_SET_PDEATHSIG` недостаточно: Linux сбрасывает его при exec с file capabilities. Обычное закрытие окна, SIGINT и SIGTERM ожидают остановки.
## Поддержка и ограничения MVP
- Поддерживаются обычный VLESS/TCP, TLS, REALITY, `xtls-rprx-vision`, WebSocket (path/Host, явные ed/eh), IPv4/IPv6 и XUDP. Xray на сервере совместим.
- gRPC, XHTTP, HTTPUpgrade, TCP HTTP headers, нестандартный flow и insecure TLS отклоняются понятной ошибкой.
- Список приложений сопоставляет `/proc` с Desktop Entries. Shell-launcher не является routing identity; укажите настоящий бинарник. Flatpak/Snap, временные AppImage mount paths, контейнеры и приложения со сторонними сетевыми helper-процессами не гарантируются. Для helper с отдельным executable его нужно отметить отдельно.
- VPN рассчитан на TCP/UDP. MPTCP не поддерживается core. Локальный loopback и некоторые непосредственно подключённые LAN-маршруты обходят TUN. Это не kill switch.
- Процесс, который не удалось идентифицировать в выборочном режиме, идёт DIRECT. `/proc` hidepid/ограничения безопасности могут мешать определению executable.
- Уже открытые соединения следует переподключить после смены режима. Совместная работа с другим активным VPN не гарантируется.
- Закрытие GUI и его отдельный SIGKILL проверены. Принудительное убийство одновременно guardian и core, сбой ядра/питания не дают гарантий cleanup. Core, который зависает и требует SIGKILL, также может оставить свои nftables-правила до ручной очистки/перезагрузки.
- Подписки, QR, аккаунты, статистика и автообновление не реализуются.
## Проверки
```bash
npm run format
cargo check --manifest-path src-tauri/Cargo.toml
cargo test --manifest-path src-tauri/Cargo.toml
npm run build
npm run tauri -- build --bundles deb
```
Для backend без GTK:
```bash
cargo test --manifest-path src-tauri/Cargo.toml --no-default-features --lib
cargo build --manifest-path src-tauri/Cargo.toml --no-default-features --example test_driver
src-tauri/target/debug/examples/test_driver --emit-configs /tmp/minivless-config-checks
```
Восемь сгенерированных конфигураций (TCP/TLS/REALITY/WS × два режима) проверяются настоящим `sing-box check -c <file>`.
Интеграционный тест запускает настоящий локальный VLESS-сервер, HTTP/UDP endpoints и TLS DoH-сервер в **отдельных network namespaces**. Проверяет маршрут по source IP, DNS, штатное отключение и смерть GUI; сравнивает IPv4/IPv6 rules и nftables до/после. Реальный VPN-сервер и Интернет не нужны:
```bash
unshare --user --map-root-user --net python3 tests/netns_integration.py
```
Не запускайте этот тест через host root. Скрипт требует пустое изолированное network namespace и отображение одного UID. `tests/ui-preview.html` — отдельная development-only IPC fixture для проверки React-интерфейса в браузере; в production bundle не входит и не заменяет сетевой тест.
## Документация upstream
- [Tauri: Linux prerequisites](https://v2.tauri.app/start/prerequisites/)
- [sing-box: TUN](https://sing-box.sagernet.org/configuration/inbound/tun/)
- [sing-box: process routing](https://sing-box.sagernet.org/configuration/route/rule/)
- [sing-box: VLESS](https://sing-box.sagernet.org/configuration/outbound/vless/)
- [sing-box: DNS over HTTPS](https://sing-box.sagernet.org/configuration/dns/server/https/)
- [Официальный sing-box 1.14.0](https://github.com/SagerNet/sing-box/releases/tag/v1.14.0)
Код MiniVLESS — MIT; sing-box распространяется отдельно по GPL-3.0-or-later. При распространении пакета с core соблюдайте его лицензию и предоставляйте соответствующий исходный код.