A transport that hides in plain sight.
rVPN runs over WebSocket/TLS on port 443, the same port and protocol as ordinary HTTPS. To network observers, the tunnel looks like normal web browsing.
It replaces static key exchanges with the Double Ratchet Algorithm, giving forward secrecy and post-compromise security. All traffic multiplexes through a small set of WebSocket connections on port 443.
Desktop, CLI, and Android clients use BoringSSL to mimic a Chrome TLS 1.3 ClientHello fingerprint, helping evade deep-packet inspection. iOS clients use pure-Rust rustls; Apple's Network Extension sandbox constrains BoringSSL's memory model, so iOS trades fingerprint mimicry for stability. The server also uses rustls for inbound WebSocket connections, and obtains and renews its own Let’s Encrypt certificate via ACME TLS-ALPN-01 on the same :443 listener, with no external tooling or renewal timers.
// TLS 1.3 Chrome fingerprint fn build_chrome_connector() { let mut builder = SslConnector::builder(); builder.set_min_proto_version(TLS1_3); builder.set_cipher_list( "TLS_AES_128_GCM_SHA256: TLS_AES_256_GCM_SHA384: TLS_CHACHA20_POLY1305" ); builder.set_alpn_protos(b"\x08http/1.1"); builder.build() }
A small, stable connection shape.
Since v1.3.5 the CLI and desktop clients multiplex all proxy flows over a pool of long-lived WebSocket/TLS connections instead of opening a new connection per flow. Mobile direct-TUN mode has always multiplexed over a single connection; pooling brings the same property to SOCKS5/HTTP mode without giving up parallelism.
2.1. Why pool connections
Connection-per-flow pays a full TCP, TLS 1.3, WebSocket and X3DH handshake for every flow. Under load, a client holds hundreds of parallel TLS sessions to a single server: slow to establish, and a connection shape that stands out to traffic analysis. The pool (default 4 connections per exit server, configurable) keeps the shape small and constant no matter how many flows are active.
2.2. Credit-based flow control
Each flow has a per-direction byte-credit window (256 KiB initial). The sender consumes one credit per payload byte and stops reading at zero, so ordinary TCP backpressure throttles the producer; the receiver grants delta credits as it drains. A flow parked at zero credits for 60 seconds is closed: a defensive valve, not a normal path. Control frames travel on a separate priority channel, so bulk data can never delay flow lifecycle messages.
2.3. Wire order is cryptographic order
The Double Ratchet numbers messages at encrypt time and drops frames that arrive out of order, so a shared connection must never reorder frames across concurrent flows. A per-connection send lock serialises the whole encrypt→enqueue span, keeping wire order identical to ratchet order under contention. The ratchet lock itself is released before any send await, so a backpressured connection never stalls decryption.
2.4. Resumption and pre-warming
Every connection caches TLS 1.3 session tickets, so a reconnect completes in a single round trip with no certificate flight, and the pool pre-warms replacement connections in the background when a connection drops. Each new connection still performs a fresh X3DH handshake against the pinned server identity (§4.4); resumption never weakens authentication.
What rVPN defends against.
Each row maps a threat to the mechanism that mitigates it.
A dynamic, self-healing cryptographic state.
rVPN does not use static handshakes like OpenVPN or WireGuard. Its cryptographic state evolves throughout the session.
4.1. X3DH key agreement
Initial handshakes use Extended Triple Diffie-Hellman. The client retrieves the server's signed prekey, computes four DH shared secrets, and derives the root key via HKDF-SHA256.
4.2. Double Ratchet
After the handshake, the Double Ratchet Algorithm governs the connection. The symmetric ratchet evolves chain keys per message for forward secrecy, while the DH ratchet rotates asymmetric keys for post-compromise security.
4.3. Out-of-order handling
TCP streams can deliver messages out of order. The Double Ratchet state stores skipped message keys so that late or reordered frames can be decrypted without advancing the chain, keeping the connection intact without a separate reorder buffer.
4.4. Server identity verification (TOFU)
Key agreement alone proves nothing about who holds the keys. On first connect the client pins the server’s Ed25519 identity fingerprint (canonical ik:1:<base32> form), SSH-style trust on first use. Every subsequent handshake must match the pin, verified independently of the TLS certificate chain: a compromised CA or forced certificate reissue cannot impersonate a pinned server. A mismatch refuses the connection; rotating a server’s identity key requires explicit re-pinning, exactly like an SSH host-key change. Multi-server profiles pin each exit server separately.
An advanced routing engine, built in.
The client includes a routing engine that decides which traffic enters the tunnel, which stays local, and which is blocked.
IP CIDR lookup
IP network tables resolve CIDR routes in logarithmic time for split-tunnel bypass and force-tunnel networks.
Domain rules
Hierarchy-aware matching for tunnel, bypass, and force-tunnel domain lists.
Ad & tracker lists
Fast exact and parent-domain lookups against compiled-in and user-supplied ad/tracker lists.
Deferred DNS
Zero DNS leaks, with near-zero initial connection latency.
Multi-server routing
A profile can carry additional exit servers, each with its own route domains (suffix-matched: google.com covers *.google.com) and route IPs/CIDRs. Matched traffic egresses through that exit and never silently falls back to the default server. On mobile, the resolver runs inside the tunnel extension itself: each exit resolves names through its own DNS-over-HTTPS channel, and every answer is recorded in a shared route map with the answer’s TTL, so follow-up connections to those IPs take the same exit automatically. Exits connect lazily on first use and reconnect independently, each with its own TOFU identity pin.
Fast rule loading at startup.
The client loads compiled-in routing and block lists, plus optional user-supplied lists, into memory at startup. This keeps per-connection lookups fast.
How it works
Domains are matched in HashSet collections, with parent-domain checks. IP ranges are stored in a longest-prefix-match table. Everything loads into memory at startup; zero-copy serialization and delta updates are planned for very large enterprise rule sets.
No management interface to exploit.
Exposing HTTP/REST management APIs, RPC interfaces, or admin sockets creates attack surface for credential theft, privilege escalation, and zero-day exploits.
rVPN has no management interface. All parameters, routing rules, and key mappings are set in static TOML files read at startup. No admin APIs, dashboards, or control sockets exist, so an adversary cannot alter runtime state.
No management API
No HTTP endpoints, no RPC interfaces, no admin sockets. Nothing to exploit at runtime.
Static config (TOML)
All parameters defined at startup. Immutable at runtime, with no dynamic reconfiguration surface.