103 lines
3.0 KiB
Markdown
103 lines
3.0 KiB
Markdown
# 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` |
|