# WireGuard Policy Firewall + WGRplane (`03.wireguard-policy`) This repository contains two components: 1. **WireGuard Policy Firewall** - Shell script-based dynamic iptables/ipset policy engine 2. **WGRplane** - Go-native control plane with Vue 3 frontend --- ## Component 1: WireGuard Policy Firewall ## Architecture & Configuration Flow - **Goal:** Dynamic iptables/ipset rules based on WireGuard configuration (`wg0.conf`). - **Data Flow:** `wg0.conf` -> `wg-sync-policy.sh` -> `policy.json` -> `wg-policy-engine.sh` -> `iptables`/`ipset` - **File Watcher:** `wg-sync-watch.sh` monitors `wg0.conf` via `inotifywait` and debounces changes to re-run the sync and engine. ## Critical Parsing Rules & Design Constraints - **Target IPs Parsing (`#Access`):** The firewall script uses the custom `#Access` comment in `wg0.conf` to define egress/firewall whitelists for clients. - **Why `#Access` is mandatory:** WireGuard's native `AllowedIPs` on a Server dictates *routing* towards the client. If we put target destinations in the Server's `AllowedIPs`, the Server would wrongly route traffic destined for those IPs *into* the client tunnel. Therefore, a custom `#Access` comment is the only correct way to define firewall whitelist destinations without breaking WireGuard's Cryptokey Routing. - **Do not remove `#Access`:** Future agents MUST NOT attempt to refactor the script to parse targets from `AllowedIPs`. It is architecturally incorrect for this use case. ## Testing & Verifying - `wg-policy-ctl status`: Check the overall health, including interface status, JSON validity, lock files, and iptables rules counts. - `wg-policy-ctl validate`: Validates `policy.json` without applying. - `wg-policy-ctl rules`: View the applied iptables rules in the active chain (`WG_POLICY`). - `wg-policy-ctl reload`: Forces a re-sync from `wg0.conf` and re-applies iptables. ## Script Constraints & Gotchas - **Atomic Operations:** Always use atomic writes (`mv -f tmp target`) for `policy.json` to prevent the policy engine from reading partial files. - **Locking:** `wg-sync-policy.sh` uses file-based locking (`flock`) to prevent race conditions during updates. - **Rollback:** `wg-policy-engine.sh` creates a backup chain (`WG_POLICY_BAK`) and uses a trap on `ERR` to rollback if applying rules fails halfway. - **Dependencies:** Requires `jq` and `inotify-tools`. ## Development Commands - Restart the watcher service: `systemctl restart wg-policy.service` - Check service logs: `journalctl -u wg-policy.service -f` --- ## Component 2: WGRplane (Go App in `/app`) ## Architecture Overview WGRplane is a Go-native WireGuard control plane application with a Vue 3 frontend, providing a modern web dashboard for WireGuard management. - **Single Binary:** The Go binary (`app/main.go`) serves both the REST API (port 10087) and the built Vue frontend from `app/frontend/dist/`. - **Hybrid Mode:** - `forward` - Directly applies nftables rules on the local machine - `standalone` - Acts as a control plane that triggers webhooks to remote WireGuard servers - **2-Column Policy:** Each peer has `AllowAccess` (CIDR whitelist) and `AllowInternet` (boolean toggle) ## Key File Locations - `app/main.go` - Bootstrap server, routing, init DB - `app/handlers.go` - REST API route handlers - `app/models.go` - GORM models (Server, Peer, Webhook, SMTP) - `app/auth.go` - JWT, TOTP, API key auth middleware - `app/nftables.go` - nftables rule management (mode forward) - `app/webhook.go` - Webhook engine with retry/backoff - `app/scheduler.go` - Cron jobs (expiry, data limit, reset) - `app/stats.go` - WebSocket Hub for real-time stats - `app/frontend/` - Vue 3 SPA (TypeScript, TailwindCSS 4) ## Tech Stack | Component | Technology | |-----------|------------| | **Backend** | Go, Gorilla Mux, GORM (SQLite via glebarez/sqlite) | | **Frontend** | Vue 3, TypeScript, Vite, TailwindCSS 4, vue-i18n 9 | | **Auth** | JWT (golang-jwt/v5), TOTP (pquerna/otp), API Key | | **WebSockets** | gorilla/websocket | | **Webhooks** | Go net/http with retry + exponential backoff | | **Scheduling** | robfig/cron v3 | | **QR Code** | skip2/go-qrcode | | **Email** | jordan-wright/email (SMTP) | ## Authentication Methods WGRplane supports three authentication methods: | Method | Header | Notes | |--------|--------|-------| | API Key | `wg-rplane-datadunia: ` | Set via env var `WG_API_KEY`. Default: `test-api-key` | | JWT | `Authorization: Bearer ` | Expires in 15 minutes. Secret via env var `JWT_SECRET` | | TOTP | `X-TOTP: ` | Required if user enables TOTP | ## Development Commands - Build Go binary: `cd app && go build -o ../wgrplane .` - Build frontend: `cd app/frontend && npm install && npm run build` - Run locally: `./wgrplane` (serves on `http://localhost:10087`) - Restart service: `systemctl restart wgrplane.service` - Check service logs: `journalctl -u wgrplane.service -f` ## Testing & Verifying - Test auth (no header): `curl http://localhost:10087/api/servers` (expect 401) - Test auth (correct): `curl -H "wg-rplane-datadunia: test-api-key" http://localhost:10087/api/servers` - View Swagger docs: Visit `http://localhost:10087/swagger/` - WebSocket test: Connect to `ws://localhost:10087/ws/stats` ## References - For detailed WGRplane documentation: See `app/README.md` - For WGRplane-specific AI agent guidance: See `app/AGENTS.md` --- ## Notes for AI Agents - The `.sisyphus/` directory contains planning artifacts and may be cleaned up after plan completion. - When working on Policy Firewall scripts, always preserve `#Access` comment parsing logic. - When working on WGRplane, remember it's a single binary serving both API and frontend on port 10087.