No description
  • C# 97.2%
  • Shell 2.3%
  • PowerShell 0.5%
Find a file
2026-05-24 18:45:43 +03:00
.forgejo/workflows Изменения 2026-05-24 18:44:41 +03:00
build Изменения 2026-05-24 18:44:41 +03:00
CaviCodeVPN.App ?????? 2026-05-24 17:17:30 +03:00
CaviCodeVPN.Core Изменения 2026-05-24 18:44:41 +03:00
CaviCodeVPN.Infrastructure Изменения 2026-05-24 18:44:41 +03:00
docs Изменения 2026-05-24 18:44:41 +03:00
.gitignore Лютый багфикс продолжается 2026-04-22 02:45:59 +03:00
AGENTS.md Изменения 2026-05-24 18:44:41 +03:00
CaviCodeVPN.Desktop.sln Правки прав и логов + ребрендинг 2026-04-22 20:00:37 +03:00
global.json Полная переделка проекта :) 2026-04-17 13:20:23 +03:00
NuGet.Config Полная переделка проекта :) 2026-04-17 13:20:23 +03:00
README.md Изменения 2026-05-24 18:44:41 +03:00

CaviCode VPN Desktop

Десктопный GUI-клиент для VPN-протокола TrustTunnel (Avalonia UI + .NET 8).
Приложение — графическая оболочка над CLI-бинарником trusttunnel_client: управляет процессом через System.Diagnostics.Process, парсит stdout/stderr в реальном времени, ведёт историю соединений и логи в SQLite.

Поддерживаемые платформы: Windows 10+ (x64) · Linux x64/arm64 (Alt Linux, Ubuntu 20.04+, Debian 11+).


Содержание


Требования

  • .NET 8 SDK (версия зафиксирована в global.json8.0.121, rollForward: latestFeature).
  • Git — для клонирования репозитория.
  • TrustTunnel Client — не требуется для сборки, нужен только в рантайме:
    • Linux: /opt/trusttunnel/trusttunnel_client
    • Windows: C:\Program Files\TrustTunnel\trusttunnel_client.exe
    • Либо любой путь из PATH, либо указанный вручную в Настройки → TrustTunnel.
    • Установить клиент можно прямо из GUI на вкладке Установщик (скачает релиз с GitHub).

На Linux дополнительно нужны GTK/X11-библиотеки (обычно уже стоят в десктоп-дистрибутиве) и polkit/pkexec для эскалации привилегий.


Структура репозитория

CaviCodeVPN-Desktop/
├── CaviCodeVPN.Desktop.sln          # Solution
├── CaviCodeVPN.App/                 # Avalonia UI, точка входа, ViewModels, Views
├── CaviCodeVPN.Core/                # Модели, перечисления, интерфейсы (без зависимостей)
├── CaviCodeVPN.Infrastructure/      # SQLite, Process IPC, HTTP, платформо-специфика
├── global.json                      # Пин версии .NET SDK
└── NuGet.Config                     # Источники пакетов (nuget.org)

CaviCodeVPN.Core

Чистая библиотека без внешних зависимостей.

Путь Содержимое
Enums/ VpnStatus, NavigationItem, AppTheme, AppThemeMode, SessionStatus, LogLevel, RoutingAction, UpdatePolicy, …
Interfaces/ ITrustTunnelService, IConnectionActivityRepository, ISessionRepository, ILogRepository, IConfigRepository, ISettingsService, IUpdateService, IPlatformService, …
Models/ VpnState, VpnConfig, ConnectionActivity, ConnectionSession, LogEntry, AppSettings, RoutingRule, UpdateInfo, …

CaviCodeVPN.Infrastructure

Путь Содержимое
Services/TrustTunnelService.cs Управление процессом trusttunnel_client, парсинг логов, публикация VpnState через SimpleSubject<T>
Services/InstallerService.cs Скачивание и установка бинарника с GitHub Releases
Services/UpdateService.cs Проверка обновлений через Octokit
Services/DeeplinkService.cs Декодирование tt://-URI, NamedPipe для single-instance
Services/SettingsService.cs Чтение/запись settings.json
Repositories/ ConnectionActivityRepository, SessionRepository, LogRepository, ConfigRepository, EventRepository — всё через Dapper + SQLite
Database/DatabaseInitializer.cs Идемпотентная инициализация схемы, retention-очистка
Platform/ WindowsPlatformService, LinuxPlatformService

CaviCodeVPN.App

Путь Содержимое
Program.cs Точка входа: эскалация прав, deeplink, DI-контейнер, Avalonia host
App.axaml.cs Инициализация темы/языка, трей, диалог обновлений, определение запущенных туннелей
Views/MainWindow.axaml Корневое окно: кастомный хром, навигация (два ListBox), resize-ручки
ViewModels/MainWindowViewModel.cs Корневая VM: маршрутизация навигации, онбординг, туториал
Views/ Dashboard, Configs, Filtering, Logs, History, Diagnostics, Installer, Settings, About, Onboarding, Tutorial, Updater
Services/ ThemeService, LocalizationService, TrayIconService, MessageBox, InMemoryLogSink
Converters/ BytesToHumanReadableConverter, ConnectionActionToBrushConverter, VpnStatusToColorConverter, …
Localization/ Strings.resx (RU, default), Strings.en.resx (EN)

Быстрый старт

git clone <repo-url>
cd DSvinkaVPN-Desktop
dotnet restore
dotnet run --project CaviCodeVPN.App

При первом запуске приложение создаёт рабочий каталог:

ОС Путь
Windows %AppData%\CaviCodeVPN\
Linux ~/.config/CaviCodeVPN/

Внутри: app.db, configs/, logs/, settings.json. Схема БД и retention выполняются автоматически.


Сборка

Debug

dotnet build CaviCodeVPN.Desktop.sln -c Debug

Release

dotnet build CaviCodeVPN.Desktop.sln -c Release

Self-contained (единый исполняемый файл)

Linux x64:

dotnet publish CaviCodeVPN.App -c Release -r linux-x64 \
  --self-contained true -p:PublishSingleFile=true -o ./publish/linux-x64

Linux arm64: заменить -r linux-x64 на -r linux-arm64.

Windows x64:

dotnet publish CaviCodeVPN.App -c Release -r win-x64 ^
  --self-contained true -p:PublishSingleFile=true -o .\publish\win-x64

Итоговый бинарник — publish/<rid>/CaviCodeVPN.App[.exe].


Запуск

Из исходников

dotnet run --project CaviCodeVPN.App

Из собранного бинарника

./publish/linux-x64/CaviCodeVPN.App       # Linux
.\publish\win-x64\CaviCodeVPN.App.exe     # Windows

Права администратора

trusttunnel_client поднимает TUN-адаптер и меняет системный DNS — нужны права root/admin.

  • Windows — UAC при старте (requireAdministrator в app.manifest). Одно подтверждение — и всё приложение работает от администратора.
  • Linux — GUI работает от обычного пользователя (трей, DBus). При Connect бинарник запускается через pkexec — polkit показывает графический промт. При Disconnect отправляет SIGTERM через pkexec /bin/kill (непривилегированный процесс не может сигналить root-потомка).

Чтобы убрать промты совсем — выдать CAP_NET_ADMIN:

sudo setcap cap_net_admin,cap_net_raw=eip /opt/trusttunnel/trusttunnel_client

Обнаружение запущенных туннелей

При старте приложение проверяет наличие уже запущенных процессов trusttunnel_client. Если найдены — показывает диалог с предложением закрыть их, чтобы избежать конфликта сетевых интерфейсов.

CaviCodeVPN.App --deeplink "tt://import?config=<base64_toml>"
CaviCodeVPN.App "tt://import?config=<base64_toml>"   # короткая форма

Если инстанс уже запущен — URI доставляется в него через NamedPipe, второй процесс завершается.


Функциональность

Дашборд

Отображает текущее состояние VPN (Disconnected / Connecting / Connected / Error), активный профиль, время подключения, скорость и суммарный трафик сессии. Кнопки Connect / Disconnect управляют процессом trusttunnel_client.

Перед запуском туннеля выполняется preflight-проверка: если не удаётся подключиться к Endpoint — отдельно различаются кейсы «нет интернета» и «Endpoint недоступен», с понятной ошибкой на Dashboard.

Конфигурации

Список профилей VPN в формате TOML (trusttunnel_client.toml). Поддерживает создание, редактирование (встроенный текстовый редактор с подсветкой ошибок), удаление и импорт через deeplink tt://.

Фильтрация

Управление правилами маршрутизации (RoutingRule): какой трафик пускать через туннель, обходить (bypass) или блокировать.

Подключения (История)

Журнал соединений текущей и прошлых сессий из таблицы ConnectionActivity.

  • Динамическая подгрузка: первые 200 записей грузятся сразу, следующие страницы — по мере прокрутки (каждые 15% от конца списка), максимум 1000 записей в памяти.
  • Очистка при подключении: при каждом новом подключении список сбрасывается и показывает только текущую сессию.
  • Авто-обновление: пока VPN активен — список обновляется каждые 5 секунд.
  • Фильтры (работают на уровне SQL): поиск по домену/адресу, фильтр по протоколу (TCP/UDP) и действию (Tunnel / Bypass / Reject / Default / Destroyed).
  • Сводка: суммарные счётчики соединений, отправленных и полученных байт.
  • Экспорт в CSV.

Логи

Поток логов trusttunnel_client в реальном времени (через InMemoryLogSink Serilog). Фильтрация по уровню и поиск по тексту. Экспорт в файл.

Диагностика

Набор автоматических проверок: доступность бинарника, версия, сетевые интерфейсы, права, TCP-досягаемость Endpoint и стабильность подключения (серия ICMP-пингов — потери, jitter, средний/максимальный RTT). Результат по каждому тесту — OK / Warning / Error, с экспортом отчёта.

Установщик

Проверяет GitHub Releases, скачивает и устанавливает свежую версию trusttunnel_client (с прогресс-баром). Поддерживает Linux (tar.gz) и Windows (zip/exe).

Настройки

Категория Параметры
Интерфейс Тема (SleepyPrincess / DemonessEngineer), режим (Light / Dark / System), язык (RU / EN)
Поведение Сворачивать в трей при закрытии
Обновления AutoInstall / NotifyOnly / Never
TrustTunnel Путь к бинарнику trusttunnel_client

Тема и язык применяются мгновенно (live-preview). Настройки сохраняются в settings.json.

Онбординг и туториал

При первом запуске — визард выбора темы и языка, обучающий тур по интерфейсу.

Системный трей

Иконка в трее с меню Connect/Disconnect и быстрым переключением профилей. Двойной клик — восстановить окно.

Обновления приложения

Фоновый воркер проверяет обновления при старте и раз в 24 часа. При NotifyOnly показывает диалог с changelog (Markdown); при AutoInstall — устанавливает тихо.


Настройки и данные

Файл / каталог Назначение
app.db SQLite: Sessions, LogEntries, AppEvents, ConnectionActivity, RoutingRules
configs/*.toml Профили VPN
logs/app-YYYYMMDD.log Логи приложения (Serilog, rolling daily, хранятся 14 дней)
settings.json Тема, язык, политика обновлений, путь к бинарнику

Retention по умолчанию: логи TrustTunnel — 30 дней, сессии и события — 90 дней.

Схема базы данных

Sessions          -- VPN-сессии: время, профиль, статус, трафик
LogEntries        -- Строки логов trusttunnel_client
AppEvents         -- События приложения (старт, подключение, ошибки)
ConnectionActivity-- Соединения: домен, адрес, протокол, действие, байты
RoutingRules      -- Правила маршрутизации (Filtering)

Архитектура

Стек

Слой Технологии
UI Avalonia 11.2, FluentTheme, DataGrid, Material.Icons
MVVM CommunityToolkit.Mvvm 8.3 (source generators, [ObservableProperty], [RelayCommand])
DI Microsoft.Extensions.DependencyInjection 8
БД SQLite (Microsoft.Data.Sqlite) + Dapper
Логирование Serilog 4 (File + InMemorySink)
Обновления Octokit (GitHub API)
Конфиги Tomlyn (TOML)
Архивы SharpZipLib

Поток данных VPN

trusttunnel_client (stdout/stderr)
    ↓ парсинг строк (TrustTunnelService)
    ├─→ SimpleSubject<VpnState>   → DashboardVM, HistoryVM, TrayIconService
    ├─→ SimpleSubject<LogEntry>   → LogsVM, DiagnosticsVM
    └─→ ConnectionActivityRepository (SQLite) → HistoryVM

Навигация

Два ListBox в левой панели:

Основная: Dashboard · Filtering · Logs · History
Системная: Diagnostics · Settings · About

Оверлеи (ZIndex): OnboardingWizard (20) · TutorialView (30).

Темы

Две «именных» темы, каждая меняет:

  • Акцентный градиент (AccentGradientBrush)
  • Декоративные глифы фона (ThemeBackgroundField)
Тема Описание
DemonessEngineer Рыже-красный градиент
SleepyPrincess Фиолетово-синий градиент

Поверх — Light / Dark / System (Fluent).

Оконный хром

SystemDecorations="None" + собственные элементы:

  • Drag-полоса (32 px сверху, ZIndex 25)
  • 8 прозрачных Border-ручек ресайза (ZIndex 26): 4 угла + 4 стороны
  • Кнопки min/max/close (ZIndex 27)

Разработка

Правила

  1. Вся бизнес-логика — во ViewModel, в .axaml.cs только платформенные обработчики.
  2. Интерфейсы — в CaviCodeVPN.Core, реализации — в CaviCodeVPN.Infrastructure. ViewModel зависит только от интерфейсов.
  3. Все строки UI — через Loc.Get("key"). Никаких хардкодных строк в XAML.
  4. Доступ к SQLite — всегда через await, не блокировать UI-поток.
  5. Платформо-специфичный код — через IPlatformService.
  6. Compiled bindings (AvaloniaUseCompiledBindingsByDefault=true): DataTemplate обязан иметь x:DataType, не DataType.
  7. DataGrid требует явного <StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml" /> в App.axaml — без него рендерится пустым.

Локализация

  • CaviCodeVPN.App/Localization/Strings.resx — RU (по умолчанию)
  • CaviCodeVPN.App/Localization/Strings.en.resx — EN
  • Новый ключ — добавлять в оба файла.
  • Во ViewModel строки-геттеры (get => Loc.Get("key")) пересчитываются по Loc.LanguageChanged.

Добавление новой вкладки

  1. Добавить значение в NavigationItem (Core/Enums).
  2. Создать XxxViewModel : ViewModelBase с HeaderKey = "nav_xxx".
  3. Создать XxxView : UserControl + зарегистрировать в ViewLocator.
  4. Добавить DI-регистрацию в Program.BuildServiceProvider().
  5. Добавить ListBoxItem в MainWindow.axaml и case в MainWindowViewModel.NavigateTo.
  6. Добавить ключи nav_xxx в оба .resx.

Релизы и автообновления

Пайплайн: Windows — Velopack (Setup.exe + delta-nupkg), Linux — системные пакеты .deb/.rpm + pkexec-установка. CI — Forgejo Actions, доставка — rsync на cavicode.tech, раздача — Nginx лендинга.

Пайплайн одного релиза

  1. Поднять версию (передаётся аргументом в pack-скрипты).
  2. git tag v1.2.3 && git push --tags — триггерит .forgejo/workflows/release.yml.
  3. CI параллельно собирает три таргета:
    • win-x64dotnet publishvpk packSetup.exe + *-full.nupkg + *-delta.nupkg.
    • linux-x64-debdotnet publishbuild/pack-linux-deb.sh (раскладка в /opt/cavicode-vpn/, wrapper в /usr/bin/cavicode-vpn, .desktop и иконка в системных путях).
    • linux-x64-rpm — аналогично через build/pack-linux-rpm.sh (rpmbuild spec prebuilt из того же publish-output).
  4. Deploy-job делает rsync в win-x64/, linux-x64-deb/, linux-x64-rpm/ и обновляет стабильные симлинки (cavicode-vpn_latest_amd64.deb, cavicode-vpn-latest.x86_64.rpm, CaviCodeVPN-Setup.exe).
  5. Клиент Windows — UpdateService (Velopack-адаптер) читает RELEASES-stable, качает дельту, ApplyUpdatesAndRestart.
  6. Клиент Linux — LinuxPackageUpdateService читает LATEST, качает нужный пакет (.deb или .rpm по /etc/os-release), запускает pkexec apt install -y / pkexec dnf install -y, после успешной установки detached-helper через setsid sh -c "sleep 2; exec /usr/bin/cavicode-vpn" перезапускает приложение.

Инфраструктура на сервере

  • Корень лендинга: /var/www/vpn-desktop/ — Vue-приложение из соседнего репозитория CaviCode-Landing.
  • Артефакты:
    • /var/www/vpn-desktop/releases/stable/win-x64/RELEASES-stable, *.nupkg, *-Setup.exe, *-Portable.zip + симлинки CaviCodeVPN-Setup.exe / Portable.zip.
    • /var/www/vpn-desktop/releases/stable/linux-x64-deb/*.deb, LATEST, симлинк cavicode-vpn_latest_amd64.deb.
    • /var/www/vpn-desktop/releases/stable/linux-x64-rpm/*.rpm, LATEST, симлинк cavicode-vpn-latest.x86_64.rpm.
  • Nginx MIME/каш-политики для .deb/.rpm — в CaviCode-Landing/deploy/nginx/cavicode-tech-vpn-desktop.conf.

CI Secrets (Forgejo → Repo Settings → Secrets)

Имя Назначение
DEPLOY_SSH_KEY приватный ed25519 для rsync, без passphrase
DEPLOY_HOST FQDN или IP (cavicode.tech)
DEPLOY_USER unix-пользователь с rw на /var/www/vpn-desktop/

Локальная проверка упаковки

# Linux .deb (dpkg-deb встроен в Debian/Ubuntu/Alt/Mint)
./build/pack-linux-deb.sh 1.0.0

# Linux .rpm — требуется rpmbuild: sudo apt install rpm / sudo dnf install rpm-build
./build/pack-linux-rpm.sh 1.0.0

# Windows (Velopack)
pwsh ./build/pack-win.ps1 -Version 1.0.0

Установка и удаление для пользователя (Linux)

# Debian / Ubuntu / Mint / Pop!_OS
sudo apt install ./cavicode-vpn_1.0.0_amd64.deb
sudo apt remove cavicode-vpn

# Fedora / RHEL / openSUSE / Alt
sudo dnf install ./cavicode-vpn-1.0.0-1.x86_64.rpm
sudo dnf remove cavicode-vpn

Пользовательские данные — настройки, логи, SQLite-БД — лежат в ~/.config/CaviCodeVPN/ и не удаляются пакетным менеджером. Для полной очистки: rm -rf ~/.config/CaviCodeVPN/.

Подпись

На старте — без Authenticode (self-signed вариант для Windows) и без GPG (для .deb/.rpm это означает, что apt install попросит --allow-untrusted или dpkg -i). Добавление — отдельная задача: Authenticode через vpk pack --signParams, GPG-подпись .deb/.rpm через dpkg-sig / rpm --addsign в CI после создания пакета.

Клиентские настройки

Секция Updates в appsettings.json (рядом с бинарником):

"Updates": {
    "FeedBaseUrl": "https://cavicode.tech/vpn-desktop/releases",
    "Channel": "stable"
}

Итоговый URL фида:

  • Windows: {FeedBaseUrl}/{Channel}/win-x64/RELEASES-stable (читает Velopack).
  • Linux (.deb-family): {FeedBaseUrl}/{Channel}/linux-x64-deb/LATEST.
  • Linux (.rpm-family): {FeedBaseUrl}/{Channel}/linux-x64-rpm/LATEST.

Лицензия

MIT