- Add IPC encryption using ChaCha20Poly1305
- Reduce helper connection timeout from 60s to 15s
- Replace unwrap() with proper error handling in helper connection
- Encrypt all messages between GUI and helper with derived key
- Add ipc_crypto module for secure communication
- Properly decode/encode encrypted messages in IPC loop
When using xhttp (UoT) mode on Android, the underlying TcpStream was
not protected with VpnService.protect(fd). This caused the TCP connection
to be routed back into the TUN interface, creating an infinite routing
loop and failing the connection immediately.
Added Android-specific socket protection to the TcpStream in connect_xhttp.
This fixes xhttp/UoT mode on mobile networks.
The core bug: server sent 5 TLS records in server_hello but client only
read the first one (ServerHello), then passed remaining bytes (CCS + fake
records) into RealityStream. RealityStream saw 0x14 (CCS) != 0x17 and
immediately returned an error, killing the connection.
Changes:
- reality.rs: append ChangeCipherSpec after ClientHello (RFC 8446 D.4)
export REALITY_SERVER_HANDSHAKE_RECORDS=5 constant
- xhttp.rs: drain all 5 server handshake records before creating RealityStream
- uot.rs: rebuild server_hello as proper 5-record TLS 1.3 flight:
ServerHello + CCS + fake EE (108B) + fake Cert (812B) + fake Fin (52B)
drain client CCS from raw stream before wrapping in RealityStream
DPI/TSPU resistance:
- Handshake packets now padded with 32-128 random bytes (prevents size
fingerprinting — previously every handshake was exactly 52 bytes)
- Frame header reserved bytes randomized instead of always 0 (prevents
known-plaintext oracle inside encrypted payload)
- Padding jitter cap increased from 96 to 256 bytes for better traffic
pattern masking
GUI Windows app (tunnel/proxy not starting):
- CRITICAL: Added CREATE_NO_WINDOW flag to all reg.exe calls in sysproxy.rs.
In Tauri GUI context (no console window), Command::new('reg') was silently
failing because there was no attached console. This prevented the Windows
system proxy from being enabled.
- Added ProxyOverride bypass list (localhost;127.*;10.*;192.168.*;<local>)
to prevent proxy loop for local traffic
- Added comprehensive logging for all registry operations
- Set initial connection_state to 1 (connecting) instead of 0 — prevents
UI polling from immediately flipping back to 'disconnected' before the
handshake has a chance to begin
Code quality:
- Fixed log file paths: log_to_core_file() and log_to_file() now write next
to the executable instead of CWD. In GUI context, CWD could be
C:\Windows\System32, causing write failures or misplaced log files.
ostp-gui:
- GUI-01: Config parsing now strips JSONC comments via json_comments
crate, matching CLI behavior. Previously failed on any commented config.
- GUI-02: stop_tunnel now properly aborts the JoinHandle with a 2s
timeout instead of silently dropping it.
ostp-jni (Android SDK):
- JNI-01: Replaced all .unwrap() calls in JNI functions with safe
null_mut fallback. JNI functions must never panic.
- JNI-02: Added missing exclusions, multiplex, debug fields to
Kotlin SDK Config.toNativeJson(). Without these, serde deserialization
on the native side could fail or use wrong defaults.
- JNI-03: Replaced shutdown_background() with shutdown_timeout(3s)
to allow proper task cleanup and port unbinding.
- JNI-04: Updated Kotlin log string matchers to match professionalized
messages (Connection established, TUN tunnel established, etc.)
TUN handlers:
- TUN-01: Windows TUN cleanup guard now resets DNS via netsh. Previously
the custom DNS server remained configured after disconnect, causing
complete DNS resolution failure.
- Unified all remaining [ostp-client] log prefixes to [ostp] across
wintun_handler.rs, linux_handler.rs, and proxy.rs.