vpn/docs/architecture.md
2026-09-23 01:19:36 +00:00

102 lines
4.7 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.

# Архитектура
## Scope
Текущий продукт — Android + desktop. iOS исключён. macOS не собирается в первом MVP;
если платформа вернётся, на ней разрешён только proxy-only до отдельного native review.
В приложении две верхние вкладки: `VPN` и `Белые списки`.
- `VPN` использует `SignBox` как один движок для стратегий `Основная` (VLESS) и
`Усиленная` (AmneziaWG 3.1).
- `Белые списки` использует отдельный `FreeTurn` runtime. FreeTurn не является
VPN-стратегией SignBox.
## Boundaries
```text
Flet/Python
models, profiles, UI, theme, payment banner, settings registry
|
| versioned idempotent commands
v
Flet service extension / MethodChannel
|
v
Android native services (separate lifetime from Activity)
VpnRuntimeService (VpnService + foreground)
ProxyRuntimeService (foreground + proxy/hotspot)
|
+-----+--------------------+
| SignBox/libbox adapter | FreeTurn mobile adapter
| TUN/proxy/stats | Start/StartTunnel/Stop/Captcha
```
Python does not start an Android subprocess and does not own VPN lifetime. On desktop,
the SignBox adapter may own a configured executable with `asyncio` process management;
FreeTurn desktop is explicitly unsupported.
Android state is authoritative in native `SharedPreferences`. Reopening the Flet UI must
call `get_runtime_state`; missing Python state never implies that a service is stopped.
The current native bridge already has this contract, but the engine AAR API still must
be pinned before the adapter can report `RUNNING`.
## Engine abstraction
`app/core/interface.py` defines the common lifecycle. `BackendRegistry` and
`EngineManager` select adapters by registry and enforce one active engine. Capabilities
are checked before start. Unsupported combinations raise `UnsupportedEngineError` and
are rendered as `Недоступно`, not as connected.
Internals remain different:
- Once the exact native artifact is supplied, SignBox can expose VLESS and AmneziaWG
packet/TUN plus local SOCKS/HTTP. The current adapter deliberately reports
`UNSUPPORTED` until that API is pinned and implemented.
- FreeTurn uses its own mobile binding and event/CAPTCHA lifecycle. Its `Start` API is
not a generic SOCKS5/HTTP listener; standard sharing remains unsupported until a
separately implemented listener reports actual bound addresses.
- `VOID` is an Android VPN data-path policy and must be enforced before an engine or
direct fallback. It must never be implemented as `addDisallowedApplication`, because
Android then sends that app directly.
## Modes and sharing
Desktop is proxy-only in the first release. Android supports `TUN`, `Proxy`, and
`Both` only when the selected native artifact advertises the matching capability.
Proxy defaults to `127.0.0.1`; Wi-Fi sharing uses `LocalOnlyHotspot`, discovers its
actual interface address, and binds listeners only after the hotspot callback. It never
assumes `192.168.43.1`, does not use `0.0.0.0` as a user default, and does not use
system tethering/NAT. SOCKS5 and HTTP CONNECT share one optional credential pair.
## Backend and devices
The backend has separate operator and device authentication:
- operator CRUD uses one configured admin Bearer token;
- each device gets a UUID4 and a separate random credential, stored server-side only
as SHA-256 hash;
- enrollment is one-time via an admin-created URL; the first request must use
`vpnapp/vMAJOR.MINOR/DEVICE_UUID` and binds that User-Agent;
- subsequent requests use `X-Device-Token` over HTTPS and the same bound User-Agent;
- UUID/User-Agent alone are not secrets and cannot authenticate.
Secrets in SQLite are Fernet-encrypted with `VPNAPP_SECRET_KEY`. The admin HTML never
lists secret fields after creation. A stronger future option is a hardware-backed key
and signed requests with replay protection.
## Theme and UI
The accent is derived from active top-level/strategy context: neutral gray for FreeTurn,
light blue for Basic, red for Enhanced, while `ThemeMode.SYSTEM` respects the device
light/dark mode. Screens register their settings sections in `SettingsRegistry`, so the
settings screen can grow without a universal nullable profile.
## Deliberate non-goals
- iOS, Personal Hotspot automation and iOS per-app routing.
- Android application routing (`DIRECT`/`VOID`) until native UID ownership and the
fail-closed packet drop path are implemented and tested on real devices.
- bundled native cores without pinned source, license, ABI and API evidence.
- management/debug listeners exposed by SignBox.