5.9 KiB
5.9 KiB
AGENTS.md -- WireGuard Policy Firewall + WGRplane
Generated: 2026-05-08 Project: 03.wireguard-policy
OVERVIEW
Hybrid project: (1) WireGuard Policy Firewall -- shell script iptables/ipset engine driven by wg0.conf #Access comments. (2) WGRplane -- Go binary (port 10087) serving REST API + Vue 3 SPA for WireGuard control plane management.
STRUCTURE
03.wireguard-policy/
├── app/ # WGRplane: Go backend + Vue 3 frontend (see app/AGENTS.md)
│ ├── *.go # 13 Go files, flat package (no subdirs)
│ ├── frontend/ # Vue 3 SPA (see app/frontend/src/AGENTS.md)
│ └── docs/ # Swagger auto-generated (DO NOT EDIT)
├── wg-sync-policy.sh # Parses wg0.conf → policy.json (atomic write + flock)
├── wg-policy-engine.sh # Reads policy.json → iptables/ipset WG_POLICY chain
├── wg-sync-watch.sh # inotifywait daemon, debounces wg0.conf changes
├── wg-policy-lib.sh # Shared shell library (source only, never execute directly)
├── wg-policy-ctl # CLI wrapper for operator use
├── wg-policy-cleanup.sh # PostDown cleanup (run by WireGuard)
├── *.service / *.timer # systemd units for daemon + health check
├── install.sh # Unified installer (embeds all scripts, built by build.sh)
├── build.sh / build.bat # Rebuilds install.sh from source scripts
├── Dockerfile # Multi-stage: Go build + frontend build
└── README.md # Full user documentation
WHERE TO LOOK
| Task | Location |
|---|---|
| Policy firewall logic | wg-sync-policy.sh, wg-policy-engine.sh, wg-policy-lib.sh |
| Firewall rule chain | wg-policy-engine.sh -- WG_POLICY iptables chain |
| Policy JSON schema | wg-sync-policy.sh output / wg-policy-engine.sh input |
| WGRplane API handlers | app/handlers.go |
| WGRplane DB models | app/models.go |
| Auth middleware | app/auth.go (CAUTION: see known issues) |
| nftables rules (forward mode) | app/nftables.go |
| Webhook delivery | app/webhook.go |
| Vue frontend | app/frontend/src/ |
| i18n translations | app/frontend/src/i18n/locales/ (en, id, zh) |
| Backend i18n | app/active.{en,id,zh}.json |
| Systemd service config | wg-policy.service, wgrplane.service |
CRITICAL DESIGN RULES
Policy Firewall -- #Access MUST NOT be changed
- WireGuard
AllowedIPson the server side = Cryptokey Routing, not firewall whitelist - Putting destination IPs in server's
AllowedIPsbreaks routing (WG tunnels those packets INTO client) #Accesscomment is the ONLY correct way to declare firewall destinations per-peer- NEVER refactor to parse targets from
AllowedIPs-- architecturally incorrect
Atomic Writes
- Always
mv -f tmp targetforpolicy.json-- never write directly wg-sync-policy.shusesflock-- never bypass locking
Rollback
wg-policy-engine.shcreatesWG_POLICY_BAKchain; trapsERRfor rollback
No SaveConfig
- WireGuard
SaveConfig = truestrips ALL comments including#Access-- NEVER enable
KNOWN ISSUES / GOTCHAS
- AuthMiddleware NOT applied:
auth.godefinesAuthMiddlewarebut it is NOT wired to any routes inmain.go. All API endpoints currently unprotected (auth header still checked inside handlers via manual if-check, but middleware chain is absent). - TOTP secrets in-memory:
totpSecretsmap inauth.gois not persisted; lost on restart. - WebSocket stats are MOCK:
stats.gobroadcasts randomly generated numbers, not real WireGuard traffic. - Plugin system is stub:
plugins.goTelegramNotifier/SlackNotifier just print to stdout. - Binary + DB in app/:
wgrplanebinary andwgrplane.dblive inapp/(non-standard, intentional). - Duplicate i18n:
app/active.*.json(backend i18n) andapp/frontend/src/i18n/locales/(frontend i18n) are separate systems.
ANTI-PATTERNS
- Never parse firewall targets from
AllowedIPs-- use#Accessonly - Never write
policy.jsonwithout atomic mv + flock - Never run
wg-policy-lib.shdirectly (source-only library) - Never enable
SaveConfig = truein wg0.conf - Do NOT edit
app/docs/docs.go-- auto-generated by swaggo - Do NOT put business logic in
app/main.go-- it's bootstrap only
COMMANDS
Policy Firewall
wg-policy-ctl status # Health: interface, JSON validity, rule counts
wg-policy-ctl validate # Validate policy.json without applying
wg-policy-ctl rules # Show active WG_POLICY iptables rules
wg-policy-ctl reload # Force re-sync from wg0.conf + re-apply
wg-policy-ctl policy # Show raw policy.json
wg-policy-ctl log # Show dropped packet logs (rate-limited)
systemctl restart wg-policy.service
journalctl -u wg-policy.service -f
WGRplane (Go App)
cd app && go build -o ../wgrplane . # Build Go binary
cd app/frontend && npm install && npm run build # Build Vue frontend
./wgrplane # Run (serves :10087)
systemctl restart wgrplane.service
journalctl -u wgrplane.service -f
curl -H "wg-rplane-datadunia: test-api-key" http://localhost:10087/api/servers
Installer
./build.sh # Rebuild install.sh from source scripts (Linux)
./build.bat # Rebuild install.sh from source scripts (Windows)
sudo ./install.sh install # Full install (deps + scripts + systemd + service)
sudo ./install.sh uninstall # Remove all
DEPENDENCIES
- Shell:
jq,inotify-tools(required);ipset(optional, O(1) lookup) - Go: 1.25.1, SQLite (glebarez/sqlite), Gorilla Mux, GORM, JWT, TOTP, WebSocket
- Frontend: Vue 3, TypeScript, Vite, TailwindCSS 4, vue-i18n 9
- Auth headers:
wg-rplane-datadunia: <KEY>(API key) |Authorization: Bearer <JWT>|X-TOTP: <CODE> - Env vars:
WG_API_KEY(default: test-api-key),JWT_SECRET,WG_RPLANE_MODE(forward|standalone),APP_FRONTEND_DIR