diff --git a/README.md b/README.md index 81d7d8b..d69f05a 100644 --- a/README.md +++ b/README.md @@ -40,20 +40,36 @@ Most VPNs treat TCP as a fallback. Konduit is designed for TCP from the ground u ## Download -Releases are published on the [Releases](../../releases) page. +Releases are published on the [Releases](../../releases) page. Each release includes: + +| Binary | Purpose | +|---|---| +| `konduit-server` | VPN server | +| `konduit` | CLI client (Linux) | +| `konduit-ctl` | Server provisioning tool | ### Linux (CLI) ```bash -# Download konduit-cli from the Releases page, then: -chmod +x konduit-cli -./konduit-cli connect --server vpn.example.com:443 --peer-id mydevice --psk YOUR_PSK +# Download konduit and konduit-ctl from the Releases page, then: +chmod +x konduit konduit-ctl + +# Bootstrap a server +echo "your secret mantra" | ./konduit-ctl bootstrap -l vpn.example.com:443 -p - + +# Connect a client +./konduit connect --config client.toml ``` ### macOS · Android · iOS Coming soon. +## Server Setup + +- [Server Quickstart](docs/server-quickstart.md) — install, provision, NAT setup for iptables and firewalld +- [Stealth Mode Setup](docs/stealth-setup.md) — HAProxy TCP passthrough + camouflage configuration + ## Architecture ``` diff --git a/docs/server-quickstart.md b/docs/server-quickstart.md new file mode 100644 index 0000000..7240870 --- /dev/null +++ b/docs/server-quickstart.md @@ -0,0 +1,105 @@ +# Konduit Server Quickstart + +## 1. Prerequisites + +### IP Forwarding + +```bash +sudo sysctl -w net.ipv4.ip_forward=1 +# Persist: add 'net.ipv4.ip_forward=1' to /etc/sysctl.conf +``` + +### Capabilities + +Konduit needs permission to create TUN devices and bind privileged ports without running as root. + +```bash +sudo setcap cap_net_admin,cap_net_bind_service=+ep ./konduit-server +sudo setcap cap_net_admin=+ep ./konduit +``` + +## 2. Bootstrap + +Konduit derives its identity key from a **mantra** (secret phrase) using Argon2id. Keep the mantra safe — it lets you recover the same identity if the config file is lost. + +**Standard (konduit binds on 443):** + +```bash +echo "your secret mantra phrase here" | ./konduit-ctl bootstrap -l vpn.example.com:443 -p - +``` + +**Behind a reverse proxy (HAProxy on 443, konduit on 8443):** + +```bash +echo "your secret mantra phrase here" | ./konduit-ctl bootstrap -l vpn.example.com:8443 --public-port 443 -p - +``` + +`--public-port` sets the port written into client configs, so they connect to 443 even though konduit listens on 8443. See [stealth-setup.md](stealth-setup.md) for the full HAProxy configuration. + +## 3. Add a Client + +```bash +./konduit-ctl add-client my-laptop +``` + +Creates `my-laptop.client.toml` and appends the peer to `server.toml`. Transfer the `.client.toml` to the client device, or scan the QR payload with the mobile app. + +## 4. TUN Interface Name + +Set a fixed TUN interface name so firewall rules are stable: + +```toml +# server.toml +[network] +tun_name = "konduit0" +``` + +Without this, konduit picks the first available `tunN`, which shifts if other VPN interfaces exist. + +## 5. Run + +```bash +./konduit-server --config server.toml +``` + +For persistent operation, use the provided systemd unit (`setup/server/konduit-server.service`). + +## 6. NAT / Masquerade + +VPN clients send packets with source IP `10.10.0.x`. Masquerade rewrites this to the server's public IP so internet hosts can reply. + +### firewalld (RHEL, Fedora, recent Ubuntu) + +```bash +# Trust the VPN interface +sudo firewall-cmd --zone=trusted --add-interface=konduit0 --permanent + +# Enable masquerade on the public zone +sudo firewall-cmd --zone=public --add-masquerade --permanent + +sudo firewall-cmd --reload +``` + +> **Important:** `iptables` commands are silently ignored on firewalld systems. Always use `firewall-cmd`. + +### iptables (Debian/Ubuntu without firewalld) + +```bash +IFACE=$(ip route get 1.1.1.1 | awk '{print $5; exit}') +sudo iptables -t nat -I POSTROUTING 1 -s 10.10.0.0/24 -o $IFACE -j MASQUERADE +sudo iptables -I FORWARD 1 -i konduit0 -o $IFACE -j ACCEPT +sudo iptables -I FORWARD 2 -i $IFACE -o konduit0 -m state --state RELATED,ESTABLISHED -j ACCEPT + +# Persist +sudo apt install iptables-persistent && sudo netfilter-persistent save +``` + +## 7. Verify + +```bash +# Should return your website (camouflage) not an error +curl -sk https://your-server/ + +# Check konduit logs +journalctl -u konduit-server -f +``` diff --git a/docs/stealth-setup.md b/docs/stealth-setup.md new file mode 100644 index 0000000..0cf0de6 --- /dev/null +++ b/docs/stealth-setup.md @@ -0,0 +1,105 @@ +# Stealth Mode: HAProxy + Konduit + +Konduit's stealth mode makes the VPN server indistinguishable from a normal HTTPS site. It implements a fake TLS handshake — embedding the client's ephemeral key inside the TLS `SessionID` field. For this to work, **konduit must see the raw TCP stream from the client**. Any proxy that terminates TLS before konduit breaks stealth mode. + +## Architecture + +``` +Client + │ raw TCP (looks like TLS to observers) + ▼ +HAProxy :443 ── TCP passthrough ──► konduit-server :8443 + │ + valid handshake │ handshake fails (real browser) + │ ▼ + │ HAProxy :4443 (SSL termination) + │ │ + │ ▼ + │ real HTTPS backend + VPN tunnel +``` + +## HAProxy Configuration + +```haproxy +# VPN ingress — raw TCP passthrough, no SSL termination +frontend vpn-ingress + bind *:443 + mode tcp + option tcplog + default_backend konduit-vpn + +backend konduit-vpn + mode tcp + server konduit 127.0.0.1:8443 + +# Camouflage backend — receives failed handshakes from konduit via PROXY protocol +# SSL is terminated here, not on the ingress +frontend camouflage + bind *:4443 ssl crt /etc/haproxy/ssl/your-domain.pem accept-proxy + mode http + http-request set-header X-Real-IP %[src] + http-request set-header X-Forwarded-Proto https + default_backend web + +backend web + mode http + server web1 127.0.0.1:80 check +``` + +## Konduit server.toml + +```toml +[server] +listen_addr = "0.0.0.0" +listen_port = 8443 +public_addr = "your-domain.com" +public_port = 443 # port clients connect to (HAProxy front) + +[stealth] +enabled = true +camouflage = "127.0.0.1:4443" # where to proxy non-konduit connections +``` + +Bootstrap with `--public-port` so generated client configs reference port 443: + +```bash +echo "your mantra" | ./konduit-ctl bootstrap -l your-domain.com:8443 --public-port 443 -p - +``` + +## How It Works + +**Konduit client (stealth handshake):** +1. Client sends fake TLS ClientHello with identity proof embedded +2. HAProxy passes raw TCP to konduit on port 8443 +3. Konduit verifies identity, completes handshake, establishes VPN tunnel +4. Traffic looks like TLS Application Data to any observer + +**Real browser or censor probe:** +1. Browser sends a real TLS ClientHello +2. HAProxy passes it raw to konduit +3. Konduit cannot verify identity — proxies the connection to `127.0.0.1:4443` with a PROXY protocol header preserving the real client IP +4. HAProxy at 4443 terminates TLS and serves your website +5. Observer sees a normal HTTPS site + +## Common Mistakes + +``` +# WRONG — TLS terminated by HAProxy before konduit, fake handshake never works +Client → HAProxy SSL termination → konduit + +# CORRECT — raw TCP passed through, konduit handles the fake TLS +Client → HAProxy TCP passthrough → konduit → HAProxy SSL termination (on failure) +``` + +The camouflage frontend uses `accept-proxy` — do not use it as the VPN ingress. + +## Verify + +```bash +# Browser should see your real website, not an error +curl -sk https://your-domain.com/ + +# Check konduit logs for stealth handshakes +journalctl -u konduit-server -f | grep -E "Stealth|Authenticated|camouflage" +```