clusev/docs/superpowers/runbooks/wireguard-gate-runbook.md

3.7 KiB
Raw Blame History

WireGuard gate (SP1) — manual runbook

The host scripts (docker/wg/clusev-wg.sh, clusev-wg-gate.service, the install.sh additions) cannot be exercised by the PHPUnit suite — the test runner is the app container, with no host WireGuard/firewall/kernel access. This runbook is their real verification.

Run on a throwaway Debian-13 VM with the Clusev prod stack up. Keep an SSH session open the whole time — it is the escape hatch. Tick each step against its expected result.

Pre

  • clusev wg help prints usage; clusev wg status shows wg0 not active, gate off.
  • wireguard-tools + qrencode present (installed by install.sh): command -v wg qrencode.

setup

  • sudo clusev wg setup, enter a subnet that overlaps the VM's LAN (e.g. the VM's own /24) → rejected, re-prompts.
  • Re-run, accept the default 10.99.0.0/24accepted; server keys + first peer created; client config + QR printed; systemctl is-active wg-quick@wg0active.
  • /etc/wireguard/wg0.conf and /etc/clusev/wg.env exist, mode 0600.
  • sudo clusev wg setup again → it warns that wg0.conf exists and does NOT silently clobber it (aborts unless you type reconfigure).

tunnel (gate still OFF)

  • Import the printed client (QR) into the WireGuard app; connect.
  • Over the tunnel: http://<server-tunnel-ip> reaches the panel.
  • Public http://<public-ip> still reachable (gate is off).

gate up

  • sudo clusev wg up → prints the escape reminder; refuses (non-zero) if wg0 is down.
  • Public http://<public-ip> 80/443 now refused / times out; the tunnel still serves the panel.
  • SSH still works (port 22 untouched).
  • clusev wg status shows the peer + gate on (marker /etc/clusev/wg-gate.enabled present, chain CLUSEV-WG-GATE present).
  • Add a manual rule: sudo iptables -I DOCKER-USER -s 203.0.113.0/24 -j RETURN. Run clusev wg down then clusev wg up → the manual rule survives (only CLUSEV-WG-GATE and its jump are touched). Remove it afterwards.

persistence

  • Reboot → wg0 + the gate come back (public still refused, tunnel still serves).
  • Restart Docker: sudo systemctl restart docker → the gate is re-applied (Docker flushes DOCKER-USER, the clusev-wg-gate.service re-runs via WantedBy=docker.service). Public still refused.
  • Force wg0 to fail on boot (sudo systemctl disable wg-quick@wg0 + reboot) → the gate is NOT applied (ConditionPathExists=/sys/class/net/wg0 fails the unit), the panel is publicly reachable (NOT bricked); SSH + clusev wg down recover. Re-enable wg0 afterwards.

peers + down

  • clusev wg add-peer client-2 → new config + QR; the split-vs-full-tunnel note is shown.
  • clusev wg remove-peer client-2 → peer gone from wg show wg0 AND from /etc/wireguard/wg0.conf.
  • A peer name with a space or odd character round-trips (add then remove) without corrupting wg0.conf.
  • clusev wg down → public open again; marker + CLUSEV-WG-GATE chain gone (clusev wg status).

Known SP1 limitations (by design — not bugs)

  • Peer-IP allocation + the subnet collision check assume the default /24 (next_free_ip scans .2.254; the collision check matches the first three octets). Non-/24 subnets work for the tunnel but allocation is /24-shaped. Wider prefixes are SP2 territory.
  • The collision check is a heuristic (first-three-octets match against host routes/addresses), not a formal CIDR-overlap proof — it catches the common LAN clash, which is the point.
  • Peers are stored only in wg0.conf (no DB). SP2 adds the dashboard status page + peer models.