52e629ac02
- Add WGRplane component documentation to AGENTS.md - Update README.md with combined WireGuard Policy + WGRplane docs - Fix .gitignore (remove .gitea/ from ignore)
5.6 KiB
5.6 KiB
WireGuard Policy Firewall + WGRplane (03.wireguard-policy)
This repository contains two components:
- WireGuard Policy Firewall - Shell script-based dynamic iptables/ipset policy engine
- 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.shmonitorswg0.confviainotifywaitand debounces changes to re-run the sync and engine.
Critical Parsing Rules & Design Constraints
- Target IPs Parsing (
#Access): The firewall script uses the custom#Accesscomment inwg0.confto define egress/firewall whitelists for clients. - Why
#Accessis mandatory: WireGuard's nativeAllowedIPson a Server dictates routing towards the client. If we put target destinations in the Server'sAllowedIPs, the Server would wrongly route traffic destined for those IPs into the client tunnel. Therefore, a custom#Accesscomment 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 fromAllowedIPs. 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: Validatespolicy.jsonwithout applying.wg-policy-ctl rules: View the applied iptables rules in the active chain (WG_POLICY).wg-policy-ctl reload: Forces a re-sync fromwg0.confand re-applies iptables.
Script Constraints & Gotchas
- Atomic Operations: Always use atomic writes (
mv -f tmp target) forpolicy.jsonto prevent the policy engine from reading partial files. - Locking:
wg-sync-policy.shuses file-based locking (flock) to prevent race conditions during updates. - Rollback:
wg-policy-engine.shcreates a backup chain (WG_POLICY_BAK) and uses a trap onERRto rollback if applying rules fails halfway. - Dependencies: Requires
jqandinotify-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 fromapp/frontend/dist/. - Hybrid Mode:
forward- Directly applies nftables rules on the local machinestandalone- Acts as a control plane that triggers webhooks to remote WireGuard servers
- 2-Column Policy: Each peer has
AllowAccess(CIDR whitelist) andAllowInternet(boolean toggle)
Key File Locations
app/main.go- Bootstrap server, routing, init DBapp/handlers.go- REST API route handlersapp/models.go- GORM models (Server, Peer, Webhook, SMTP)app/auth.go- JWT, TOTP, API key auth middlewareapp/nftables.go- nftables rule management (mode forward)app/webhook.go- Webhook engine with retry/backoffapp/scheduler.go- Cron jobs (expiry, data limit, reset)app/stats.go- WebSocket Hub for real-time statsapp/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 |
| jordan-wright/email (SMTP) |
Authentication Methods
WGRplane supports three authentication methods:
| Method | Header | Notes |
|---|---|---|
| API Key | wg-rplane-datadunia: <KEY> |
Set via env var WG_API_KEY. Default: test-api-key |
| JWT | Authorization: Bearer <TOKEN> |
Expires in 15 minutes. Secret via env var JWT_SECRET |
| TOTP | X-TOTP: <CODE> |
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 onhttp://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
#Accesscomment parsing logic. - When working on WGRplane, remember it's a single binary serving both API and frontend on port 10087.