# Windows Proxy Client: Product And Technology Brief

Дата: 2026-07-03

Цель документа: описать, как должно выглядеть и работать Windows-приложение для управления proxy/VPN-маршрутизацией приложений, и какой стек лучше использовать для реализации.

Этот документ можно отдать другой модели или команде как исходное ТЗ.

## Коротко

Нужно Windows-приложение, которое разделяет систему на три независимые части:

1. **Control App**: маленькое desktop-приложение для настройки, статуса, профилей, логов и запуска операций.
2. **Proxyfier Layer**: отдельный компонент, который заставляет выбранные Windows-приложения ходить через SOCKS5/HTTP proxy, даже если они сами не умеют proxy.
3. **Local sing-box**: опциональный локальный VPN/proxy runtime. Его можно установить, не устанавливать, остановить, заменить внешним proxy target.

Главный принцип: пользователь не обязан ставить все сразу. Если у него уже есть proxy, ему нужны только Control App + Proxyfier. Если нужен локальный VPN-клиент, он отдельно ставит `sing-box`.

## Как это должно выглядеть

Приложение должно выглядеть как компактная системная утилита, а не как сайт.

Главный экран:

- верхняя строка: общий статус маршрута;
- три карточки компонентов: `Control App`, `Proxyfier`, `Local sing-box`;
- список активных профилей;
- кнопка `Apply changes`;
- короткая лента последних событий.

Пример главного статуса:

```text
Selected apps -> ProxiFyre -> Local sing-box 127.0.0.1:1080 -> VPN
```

или:

```text
Selected apps -> ProxiFyre -> Existing proxy 192.168.50.111:8080
```

Если `sing-box` не установлен, это не ошибка. Карточка должна показывать:

```text
Local sing-box
Not installed
Install if you want this PC to run its own local VPN proxy.
```

Если Proxyfier не установлен, профили можно редактировать, но apply должен быть заблокирован:

```text
Proxyfier is required to route selected apps.
Install Proxyfier
```

## Основные экраны

### 1. Overview

Показывает:

- текущий route line;
- статус Control App;
- статус Proxyfier;
- статус Local sing-box;
- активный proxy target;
- сколько приложений сейчас включено в routing;
- последние 5-10 событий.

Действия:

- restart Proxyfier;
- restart local sing-box, если установлен;
- open logs;
- copy diagnostics.

### 2. Profiles

Профиль - главный объект настройки.

Профиль содержит:

- название;
- enabled/disabled;
- proxy target;
- протоколы: TCP, UDP;
- список приложений.

Типы элементов:

- `process`: имя процесса, например `Discord`, `Telegram`, `Code`;
- `folder`: папка, приложение сканирует `.exe` внутри;
- `exe`: конкретный путь к `.exe`.

UI профиля:

- слева список профилей;
- справа детали выбранного профиля;
- поле выбора target;
- кнопки добавления: `Process`, `Folder`, `EXE`;
- preview resolved apps;
- `Save`;
- `Apply changes`.

Важно: пользователь должен видеть понятные исходные элементы, а не только сгенерированный конфиг Proxyfier.

### 3. Targets

Proxy target - это куда Proxyfier отправляет трафик выбранных приложений.

Типы targets:

- `Local sing-box`: `127.0.0.1:1080`, доступен только если local sing-box установлен и запущен;
- `Existing SOCKS5 proxy`: например `127.0.0.1:8080` или `192.168.50.111:8080`;
- `Existing HTTP proxy`, если выбранный proxyfier поддерживает HTTP.

На экране targets:

- список targets;
- проверка соединения;
- имя, host, port, protocol;
- статус last checked;
- кнопка set default.

### 4. Components

Отдельный экран или часть Overview.

Компоненты:

- Control App;
- Proxyfier;
- Local sing-box.

Для каждого:

- installed / not installed;
- running / stopped;
- version;
- path;
- service/task status;
- actions.

Actions должны быть явными:

- `Install`;
- `Repair`;
- `Start`;
- `Stop`;
- `Restart`;
- `Open folder`;
- `View logs`.

Нельзя делать скрытую установку `sing-box` при сохранении профиля.

### 5. Logs / Diagnostics

Должно быть две зоны:

- activity: действия пользователя и результат apply;
- runtime logs: proxyfier logs, sing-box logs, helper logs.

Кнопка `Copy diagnostics` должна собирать:

- версии компонентов;
- paths;
- running status;
- активные profiles;
- targets без секретов;
- последние ошибки;
- путь к сгенерированному proxyfier config.

## Пользовательские сценарии

### Сценарий A: у пользователя уже есть proxy

1. Пользователь устанавливает Control App.
2. Открывает приложение.
3. Видит, что Proxyfier не установлен, а sing-box отсутствует.
4. Нажимает `Install Proxyfier`.
5. Добавляет target `192.168.50.111:8080`.
6. Создает профиль `Discord`.
7. Добавляет process `Discord`.
8. Нажимает `Apply changes`.
9. Приложение генерирует config для Proxyfier и перезапускает proxyfier service.

Результат: Discord ходит через внешний proxy. Local sing-box не нужен.

### Сценарий B: пользователь хочет локальный VPN proxy

1. Пользователь устанавливает Control App.
2. Устанавливает Proxyfier.
3. Устанавливает Local sing-box.
4. Вводит subscription/VLESS link.
5. Выбирает сервер.
6. Local sing-box поднимает SOCKS5/HTTP endpoint на `127.0.0.1:1080`.
7. Профили используют target `Local sing-box`.

Результат: выбранные приложения ходят через локальный sing-box.

### Сценарий C: временно отключить VPN

1. Пользователь открывает профиль.
2. Меняет target с `Local sing-box` на внешний proxy или `Direct/Disabled`.
3. Нажимает `Apply changes`.

Результат: Proxyfier перегенерирован, local sing-box можно остановить отдельно.

## Рекомендуемый стек

### Desktop shell: Tauri 2

Рекомендация: **Tauri 2 + React + TypeScript + Rust backend**.

Почему:

- Tauri ориентирован на маленькие desktop-приложения и использует системный web renderer, поэтому приложение легче Electron.
- Можно писать UI на обычном web stack: React/TypeScript/Vite.
- Backend-часть на Rust хорошо подходит для Windows APIs, файлов, процессов, sidecar binaries и безопасных команд.
- Tauri поддерживает sidecar binaries, но требует явно выдать permissions на запуск sidecar, что полезно для security boundary.

Frontend:

- React;
- TypeScript;
- Vite;
- TanStack Query для загрузки/кэша status/API;
- Zustand или Jotai для локального UI state;
- Zod для валидации JSON-моделей;
- CSS modules или Tailwind. Для этой утилиты лучше сдержанный Windows-like UI, без тяжелой дизайн-системы.

Backend внутри Tauri:

- Rust commands для простых операций;
- отдельный `core` crate с доменной логикой;
- отдельный `windows-helper` binary для elevated/privileged действий.

Не рекомендую начинать с Electron, если нет жесткой причины. Electron проще для web-команды, но тяжелее по размеру и памяти. Для маленькой системной утилиты Tauri подходит лучше.

### Privileged helper

Нужно отделить обычное приложение от операций администратора.

Рекомендуемая модель:

```text
Tauri UI
  -> Rust app backend
    -> unprivileged status/read operations
    -> explicit elevated helper for install/repair/service operations
```

Privileged helper может быть:

- Rust CLI, который запускается elevated только для конкретной операции;
- Rust Windows service/helper, если нужен постоянный privileged agent;
- PowerShell scripts только как thin installer layer, не как основная бизнес-логика.

Для MVP можно сделать проще:

- installers запускаются отдельно от имени администратора;
- Control App работает обычным пользователем;
- service start/stop/restart идет через helper command;
- helper возвращает JSON, UI не парсит текст PowerShell.

Контракт helper:

```json
{
  "action": "proxyfier.apply",
  "payload": {
    "configPath": "C:\\Tools\\ProxiFyre\\app-config.json",
    "config": {}
  }
}
```

Ответ:

```json
{
  "success": true,
  "action": "proxyfier.apply",
  "changed": true,
  "message": "Proxyfier config applied and service restarted"
}
```

Ошибки:

```json
{
  "success": false,
  "action": "proxyfier.apply",
  "error": "Proxyfier service is not installed",
  "details": {}
}
```

### Service/runtime management

Для `sing-box` как background runtime:

- использовать `sing-box check` перед применением config;
- хранить config отдельно;
- запускать как Windows service или scheduled task;
- для service wrapper можно использовать WinSW, если не хочется писать собственный Windows service wrapper.

Практичный вариант:

- v1: WinSW wraps `sing-box.exe`;
- v2: собственный Rust service/helper, если понадобится полный контроль.

Control App не должен напрямую владеть процессом `sing-box`. Он должен управлять service/task через helper.

### Local sing-box

`sing-box` - опциональный runtime.

Его роль:

- принять subscription/VLESS/sing-box config;
- поднять локальный mixed SOCKS/HTTP inbound;
- слушать только `127.0.0.1`, например `127.0.0.1:1080`;
- маршрутизировать трафик через выбранный outbound.

Config генерируется из source state приложения и проверяется:

```powershell
sing-box check -c C:\Tools\VpnProxy\sing-box\config.json
```

Local sing-box не должен быть обязательным. Если profile target указывает на внешний proxy, `sing-box` может отсутствовать.

### Proxyfier layer

Рекомендуемый стартовый backend: **ProxiFyre**.

Почему:

- open-source;
- Windows-focused;
- маршрутизирует TCP и UDP;
- работает per-application;
- использует `app-config.json`;
- может работать как Windows Service.

Важное ограничение: ProxiFyre лицензируется как AGPL-3.0. Если продукт должен быть закрытым коммерческим приложением, нужно заранее решить юридический вопрос или сделать adapter layer, чтобы можно было заменить engine на:

- коммерческий Proxifier;
- ProxyBridge;
- собственный WinDivert/NDIS/WFP-based engine;
- другой per-app proxy router.

Интерфейс должен называться не `ProxiFyreConfig`, а шире:

```text
ProxyRouterAdapter
```

Первый adapter:

```text
ProxiFyreAdapter
```

Это позволит поменять engine без переделки UI и профилей.

### Data storage

Для MVP лучше использовать простые JSON-файлы с schema validation.

Причина:

- настройки легко читать и бэкапить;
- можно быстро отлаживать;
- config portable;
- подходит для profile/target/source state.

Рекомендуемые файлы:

```text
C:\ProgramData\VpnProxy\config\profiles.json
C:\ProgramData\VpnProxy\config\targets.json
C:\ProgramData\VpnProxy\config\components.json
C:\ProgramData\VpnProxy\state\activity.json
C:\ProgramData\VpnProxy\state\last-status.json
C:\ProgramData\VpnProxy\generated\proxifyre-app-config.json
C:\ProgramData\VpnProxy\generated\sing-box-config.json
```

Если нужна большая история событий, статистика трафика или сложные миграции, тогда добавить SQLite:

- `rusqlite` или `sqlx` в Rust;
- миграции;
- таблицы `activity`, `component_status`, `traffic_events`.

Но source of truth для профилей можно оставить JSON даже при наличии SQLite.

### Installer strategy

Нужны три явных installer entrypoints:

```text
Install Control App
Install Proxyfier Layer
Install Local sing-box
```

Они могут быть кнопками в UI, но каждая операция должна быть отдельной и понятной.

CLI/script names:

```text
install-control-app.ps1
install-proxyfier.ps1
install-singbox.ps1
```

Или в packaged app:

```text
VpnProxySetup.exe /component control-app
VpnProxySetup.exe /component proxyfier
VpnProxySetup.exe /component sing-box
```

Каждый installer:

- idempotent;
- делает backup перед overwrite;
- не удаляет чужие файлы без подтверждения;
- проверяет admin rights;
- пишет machine-readable install result;
- не трогает остальные компоненты без явного выбора.

### Security model

Правила:

- UI работает без admin rights.
- Admin elevation только для install/repair/service/config apply, если это реально нужно.
- Local API, если будет, слушает только `127.0.0.1`.
- Лучше использовать Tauri commands / named pipe, чем открытый HTTP port.
- Если нужен loopback HTTP, включить token или origin check.
- Секреты subscription URLs не показывать в diagnostics.
- Generated configs не редактируются вручную из UI.
- Every apply creates backup.

## Архитектура

```text
+-------------------------------+
| Tauri Control App              |
| React/TypeScript UI            |
+---------------+---------------+
                |
                v
+-------------------------------+
| Rust App Backend               |
| profiles, targets, validation  |
| component status aggregation   |
+-------+---------------+-------+
        |               |
        v               v
+---------------+   +-------------------+
| Proxy Router  |   | Local sing-box     |
| Adapter       |   | Adapter            |
| ProxiFyre v1  |   | config + service   |
+-------+-------+   +---------+---------+
        |                     |
        v                     v
+---------------+   +-------------------+
| ProxiFyre     |   | sing-box.exe       |
| Windows svc   |   | Windows svc/task   |
+---------------+   +-------------------+
```

## Модель данных

### Profile

```json
{
  "id": "discord",
  "name": "Discord",
  "enabled": true,
  "targetId": "local-singbox",
  "protocols": ["TCP", "UDP"],
  "items": [
    { "type": "process", "value": "Discord" },
    { "type": "folder", "value": "%LOCALAPPDATA%\\Discord", "recursive": true },
    { "type": "exe", "value": "C:\\Games\\Game\\game.exe" }
  ]
}
```

### Target

```json
{
  "id": "local-singbox",
  "name": "Local sing-box",
  "type": "local",
  "protocol": "socks5",
  "host": "127.0.0.1",
  "port": 1080,
  "requiresComponent": "singbox"
}
```

External target:

```json
{
  "id": "home-gateway",
  "name": "Home gateway",
  "type": "external",
  "protocol": "socks5",
  "host": "192.168.50.111",
  "port": 8080
}
```

### Component status

```json
{
  "id": "proxyfier",
  "name": "Proxyfier",
  "installed": true,
  "running": true,
  "version": "2.3.0",
  "path": "C:\\Tools\\ProxiFyre",
  "serviceName": "ProxiFyreService",
  "problems": [],
  "actions": ["restart", "repair", "openLogs"]
}
```

## Apply behavior

Apply должен делать одно понятное действие:

1. Прочитать profiles.
2. Прочитать targets.
3. Проверить, что выбранные targets доступны.
4. Проверить, что Proxyfier установлен.
5. Разрешить folder/exe в process names.
6. Сгенерировать proxyfier config.
7. Сделать backup старого config.
8. Записать новый config.
9. Перезапустить Proxyfier service.
10. Записать activity entry.

Если profile использует `local-singbox`, дополнительно:

- проверить, что `sing-box` установлен;
- проверить, что service running;
- проверить, что `127.0.0.1:1080` отвечает.

Если `local-singbox` не установлен, но profile target внешний, apply должен работать.

## Что не делать

- Не делать глобальную смену Windows proxy settings.
- Не делать `sing-box` обязательным.
- Не смешивать installer и profile apply.
- Не хранить generated ProxiFyre config как source of truth.
- Не привязывать UI напрямую к ProxiFyre, нужен adapter layer.
- Не запускать privileged операции без явного согласия пользователя.
- Не делать большой dashboard с лишней статистикой в первой версии.

## MVP

Самый правильный первый slice:

1. Tauri app shell.
2. Profiles UI.
3. Targets UI.
4. Component status UI.
5. ProxiFyre adapter.
6. External SOCKS5 target.
7. Apply profile -> generate ProxiFyre config -> restart service.

В MVP `sing-box` может быть только карточкой `Not installed / Install`.

После этого добавить:

1. Local sing-box installer.
2. Subscription import.
3. Server selection.
4. Generate sing-box config.
5. Start/stop/restart local sing-box service.

## Acceptance criteria

Приложение считается успешным, если:

- можно установить только Control App;
- можно установить Proxyfier отдельно;
- можно не устанавливать sing-box;
- можно добавить внешний SOCKS5 target;
- можно создать профиль для Discord;
- можно применить профиль;
- generated ProxiFyre config не редактируется пользователем вручную;
- UI показывает, что local sing-box отсутствует, но это не ломает внешний proxy flow;
- после установки sing-box появляется target `Local sing-box`;
- пользователь может переключить профиль с внешнего target на local sing-box.

## Prompt For Another AI

Build a Windows desktop proxy management app.

Use Tauri 2 with React, TypeScript, Vite, and a Rust backend. The app must manage three independent components: the Control App, a proxyfier layer, and optional local sing-box. Do not make sing-box mandatory.

The UI must be a compact Windows utility with these screens: Overview, Profiles, Targets, Components, Logs. Profiles contain process/folder/exe entries and choose a proxy target. Targets can be local sing-box or external SOCKS5/HTTP proxies. Proxyfier is the layer that routes selected apps through the chosen target.

Start with ProxiFyre as the first proxy router adapter, but design an adapter boundary so it can later be replaced. Store source configuration as JSON with schema validation. Generated ProxiFyre and sing-box configs are derived artifacts, not source truth.

Privileged operations must be isolated in an explicit helper/installer flow. The main UI should run without admin rights. Install Control App, Install Proxyfier, and Install Local sing-box must be separate operations. Applying a profile must not silently install missing components.

MVP: external SOCKS5 target + ProxiFyre profile apply. Then add optional local sing-box installation, subscription import, server selection, and local sing-box service control.

## References

- Tauri 2: https://v2.tauri.app/
- Tauri sidecar permissions: https://v2.tauri.app/develop/sidecar/
- sing-box configuration: https://sing-box.sagernet.org/configuration/
- ProxiFyre repository: https://github.com/wiresock/proxifyre
- WinSW service wrapper: https://github.com/winsw/winsw
- Microsoft Windows Service with Worker Service: https://learn.microsoft.com/en-us/dotnet/core/extensions/windows-service

