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

5 KiB
Raw Blame History

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 (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), Серверы, Приложения, Опции

Сборка

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