# Stealth Mode Setup Stealth mode makes VPN traffic look like normal HTTPS to deep packet inspection systems. The client opens a real TLS 1.3 connection, performs a WebSocket upgrade, and then carries the konduit protocol inside WebSocket binary frames — identical in appearance to any browser-based web app. ``` Client ──TLS 1.3──▶ HAProxy :443 (TCP passthrough) ──▶ Konduit :8443 HTTP/1.1 GET /ws → 101 Switching Protocols WebSocket binary frames (konduit protocol inside) ``` ## Server Requirements - A domain with a valid TLS certificate (Let's Encrypt / certbot) - HAProxy 2.4+ - Konduit server on a non-public port (e.g. `8443`) ## HAProxy Configuration HAProxy acts as a pure TCP proxy — it passes TLS through to the konduit server unchanged. ```haproxy frontend https-ingress bind *:443 mode tcp default_backend konduit-vpn backend konduit-vpn mode tcp timeout tunnel 0 server konduit 127.0.0.1:8443 ``` `timeout tunnel 0` prevents HAProxy from dropping idle connections. Reload after changes: ```bash haproxy -c -f /etc/haproxy/haproxy.cfg # validate first systemctl reload haproxy ``` ## Konduit Server (`server.toml`) ```toml [server] listen_addr = "0.0.0.0" listen_port = 8443 public_addr = "your-domain.com" public_port = 443 tls_cert = "/etc/letsencrypt/live/your-domain.com/fullchain.pem" tls_key = "/etc/letsencrypt/live/your-domain.com/privkey.pem" websocket = true ``` ## Client Configuration (`client.toml`) ```toml [client] server_endpoint = "your-domain.com:443" peer_id = "..." identity_key = "..." server_public_key = "..." [stealth] enabled = true ``` That's it — `stealth = true` activates TLS and WebSocket camouflage automatically. ## Flutter / Mobile App Enable **Stealth Mode** in the app settings. The toggle maps to `[stealth] enabled = true` in the connection config and activates TLS + WebSocket camouflage on all platforms (Linux, Android, Windows). For QR-code-based provisioning, the `t: true` field in the QR payload enables stealth. ## Verify ```bash # TLS cert must be valid — browser must reach your site curl -s https://your-domain.com/ | head -5 # Connect the VPN client sudo ./konduit --config client.toml # Watch HAProxy — you should see the tunnel established journalctl -u haproxy -f ``` ## Common Mistakes | Mistake | Effect | Fix | |---------|--------|-----| | HAProxy terminating TLS (`bind *:443 ssl crt ...`) | konduit receives plain TCP, WebSocket handshake fails | Use `bind *:443` (no `ssl`) — TCP passthrough | | Missing `timeout tunnel 0` | Connection drops after 30 s of silence | Add `timeout tunnel 0` to backend | | Port 8443 exposed to internet | Bypass HAProxy entirely | Firewall port 8443 to localhost only | | Expired/self-signed cert | TLS error on client | Use Let's Encrypt; renew via certbot | | `stealth = false` on client | Plain TCP connection, DPI detects VPN | Set `[stealth] enabled = true` |