proxy/README.md
v.lagerev c3c10c92d6 Initial import: vojo proxy — native Android proxy client
Kotlin + Jetpack Compose VPN proxy client (Shadowsocks AEAD SIP004,
SOCKS5 RFC1928/1929, HTTP/HTTPS CONNECT) with per-app whitelist via
VpnService and the vendored hev-socks5-tunnel engine (JNI). Includes
the post-review fixes to the connection lifecycle, reconnect teardown,
journal, app-filter auto-reconnect, and the tab/timeline layout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 12:51:38 +03:00

75 lines
5 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.

# vojo proxy
Нативный Android-клиент для прокси: **Shadowsocks**, **SOCKS5**, **HTTP**, **HTTPS**.
Per-app whitelist, минимальный расход батареи, маленький размер (release APK ≈ 2.4 МБ).
Дизайн — в стиле мессенджера vojo (Dawn/Fleet: тёмные поверхности, hairline-границы,
один фиолетовый акцент, monospace для технических данных).
## Стек
- **Kotlin + Jetpack Compose + Material3**, Coroutines, DataStore, kotlinx.serialization.
- **VpnService** для создания tun-интерфейса и per-app whitelist (`addAllowedApplication`).
- **tun2socks**: нативный движок [`hev-socks5-tunnel`](https://github.com/heiher/hev-socks5-tunnel)
(C, event-loop, ~320 КБ) — самый экономичный по CPU/батарее способ конвертировать
IP-пакеты из tun в потоки.
- minSdk 28, targetSdk 35, только `arm64-v8a` (Samsung S23).
## Архитектура потока данных
```
Выбранные приложения
│ (per-app whitelist через VpnService.addAllowedApplication)
tun-интерфейс ──fd──► hev-socks5-tunnel (нативный, JNI)
│ говорит SOCKS5 на 127.0.0.1:<port>
LocalSocks5Server (Kotlin, loopback)
│ мост на нужный апстрим
┌─────────────────────┼─────────────────────┬───────────────┐
▼ ▼ ▼ ▼
Shadowsocks SOCKS5 HTTP CONNECT HTTPS CONNECT
(AEAD SIP004) (RFC 1928/1929) (RFC 7231) (TLS + CONNECT)
```
- **TCP** проксируется для всех 4 протоколов. Цель приходит уже как IP/домен в SOCKS5-форме.
- **UDP/DNS**: `hev` отдаёт UDP через SOCKS5 UDP ASSOCIATE. Для SS/SOCKS5 — полноценный
UDP-релей; для HTTP/HTTPS (UDP не поддерживается протоколом) — DNS-over-TCP fallback (порт 53).
- Все апстрим-сокеты защищены `VpnService.protect()`, чтобы не зацикливаться обратно в tun.
## Ключевые модули
| Путь | Назначение |
|------|-----------|
| `core/Tun2Socks.kt`, `jni/tun2socks.c` | JNI-мост к нативному движку |
| `core/crypto/ShadowsocksCrypto.kt`, `ShadowsocksStream.kt` | AEAD (HKDF-SHA1, AES-GCM, ChaCha20-Poly1305), TCP-framing, UDP seal/open |
| `core/socks/LocalSocks5Server.kt` | Локальный SOCKS5-сервер: CONNECT + UDP ASSOCIATE |
| `core/upstream/*` | Апстримы SS / SOCKS5 / HTTP(S) |
| `service/ProxyVpnService.kt` | VpnService, whitelist, foreground-уведомление, статистика, журнал событий |
| `service/ProxyTileService.kt` | Тайл быстрых настроек (вкл/выкл из шторки) |
| `data/ConfigStore.kt`, `AppRepository.kt` | Персист конфигов (DataStore) и список приложений |
| `core/ConfigImport.kt` | Импорт ссылок `ss://` (SIP002/legacy), `socks5://`, `http(s)://` |
| `ui/*` | Compose-экраны: Туннель (журнал событий на timeline rail), Серверы, Приложения, Опции |
## Сборка
```bash
./gradlew :app:assembleRelease # → app/build/outputs/apk/release/app-release.apk (~2.4 МБ)
./gradlew :app:assembleDebug
```
Требуется Android SDK (platform-35, build-tools 35), NDK 27.2.x. Путь к SDK — в `local.properties`.
## Оптимизация батареи
- Нативный event-loop tun2socks вместо userspace TCP/IP-стека на JVM (нет GC-давления на пакет).
- Блокирующий I/O на эластичном пуле потоков — простаивающие соединения паркуют поток (0% CPU).
- `setUnderlyingNetworks` + отслеживание смены сети, `setMetered(false)`.
- Низкоприоритетное foreground-уведомление, поллинг статистики раз в 2 с (без wakelock).
- Секундный тикер UI работает только при CONNECTED и только пока активити RESUMED.
## Безопасность / ограничения
- Не реализованы VLESS/Reality (намеренно).
- Shadowsocks: AEAD-шифры (`aes-128-gcm`, `aes-256-gcm`, `chacha20-ietf-poly1305`).
Legacy stream-шифры и SS-2022 не поддерживаются.
- HTTP/HTTPS-прокси не могут передавать UDP — для них работает только DNS-over-TCP.