Hi @Flowseal,
First of all — thank you for the excellent tg-ws-proxy and the clever DPI-bypass architecture you built. It works incredibly well on desktop.
We wanted to bring the same functionality to Android, so we created a Kotlin port that runs as a foreground service with a native UI:
Repository: https://github.com/ComradeSwarog/tg-ws-proxy-android
License: MIT (same as upstream)
Language: Kotlin / Android SDK 34
What was ported
| Original Python |
Kotlin/Android |
proxy/tg_ws_proxy.py |
TgWsProxy.kt |
proxy/raw_websocket.py |
RawWebSocket.kt |
proxy/doh_resolver.py |
DoHResolver.kt |
proxy/balancer.py |
Balancer.kt |
proxy/fake_tls.py |
handleFakeTLS, FakeTlsInputStream |
proxy/stats.py |
ProxyStats.kt |
Stability fixes discovered during real-world testing
We tested the port extensively on Samsung devices under active DPI (1+ hour continuous sessions) and fixed several issues that also likely affect the Python version:
| Issue |
Cause |
Fix |
| App crash on connect |
ConcurrentHashMap.put(null) in connectParallel() when raw socket connect fails |
Null-guard before map insertion |
| Service killed / restart loop |
ForegroundServiceDidNotStartInTimeException on Android 12+ sticky restart |
Moved startForeground() to the very top of onStartCommand() |
| Socket FD exhaustion |
Parallel connect left loser's sockets open |
Track Socket per-thread in ConcurrentHashMap<Thread, Socket> and close all losers after winner is chosen |
| Global SSL factory poisoning |
DoHResolver mutated HttpsURLConnection.setDefaultSSLSocketFactory(...) |
Isolated SSLContext per-connection, never touching global defaults |
| Client read timeout |
soTimeout = 10s was shorter than MTProto handshake silence under DPI |
Raised to 30s |
| CF hammering / 429 rate-limit |
No backoff for rejected CF Workers |
Adaptive blacklist TTL (2min for 429, 5min for TCP refuse) |
Additional features
- Foreground service with persistent notification + optional background restart
- GUI settings (Host, Port, Secret, DC:IP, bypass toggles) instead of config files
- In-app log viewer with export/share to
.txt (live buffer + file rotation)
- Auto-generated
tg://proxy link with one-tap "Open in Telegram" button
- Connection pool with warmup, refill, and age-based eviction
- Pre-warmed CF pool — tests CF fallback domains before first real connection
Attribution
Please feel free to mention tg-ws-proxy-android in your README if you find it useful. We'd also love feedback or cross-referencing if anything here is helpful for the Python upstream.
Once again — thanks for the original idea and the clean architecture! 🙏
Hi @Flowseal,
First of all — thank you for the excellent
tg-ws-proxyand the clever DPI-bypass architecture you built. It works incredibly well on desktop.We wanted to bring the same functionality to Android, so we created a Kotlin port that runs as a foreground service with a native UI:
Repository: https://github.com/ComradeSwarog/tg-ws-proxy-android
License: MIT (same as upstream)
Language: Kotlin / Android SDK 34
What was ported
proxy/tg_ws_proxy.pyTgWsProxy.ktproxy/raw_websocket.pyRawWebSocket.ktproxy/doh_resolver.pyDoHResolver.ktproxy/balancer.pyBalancer.ktproxy/fake_tls.pyhandleFakeTLS,FakeTlsInputStreamproxy/stats.pyProxyStats.ktStability fixes discovered during real-world testing
We tested the port extensively on Samsung devices under active DPI (1+ hour continuous sessions) and fixed several issues that also likely affect the Python version:
ConcurrentHashMap.put(null)inconnectParallel()when raw socket connect failsForegroundServiceDidNotStartInTimeExceptionon Android 12+ sticky restartstartForeground()to the very top ofonStartCommand()Socketper-thread inConcurrentHashMap<Thread, Socket>and close all losers after winner is chosenDoHResolvermutatedHttpsURLConnection.setDefaultSSLSocketFactory(...)SSLContextper-connection, never touching global defaultssoTimeout = 10swas shorter than MTProto handshake silence under DPIAdditional features
.txt(live buffer + file rotation)tg://proxylink with one-tap "Open in Telegram" buttonAttribution
Please feel free to mention
tg-ws-proxy-androidin your README if you find it useful. We'd also love feedback or cross-referencing if anything here is helpful for the Python upstream.Once again — thanks for the original idea and the clean architecture! 🙏