# 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.
