# WireGuard Policy Firewall + WGRplane Control Plane A complete WireGuard management solution combining two powerful components: 1. **WireGuard Dynamic Policy Firewall** - A lightweight, robust iptables/ipset policy engine that restricts and controls WireGuard peer traffic directly from `wg0.conf` using custom `#Access` comments. 2. **WGRplane** - A Go-native control plane application with Vue 3 frontend, providing a modern web dashboard for WireGuard management with real-time monitoring, peer CRUD, and hybrid firewall enforcement. --- ## πŸ“‘ Table of Contents ### Policy Firewall (Shell Scripts) - [Architecture & Data Flow](#-architecture--data-flow) - [Installation](#-installation) - [Prerequisites](#-prerequisites) - [wg0.conf Integration](#-integrasi-ke-wg0conf) - [CLI Usage](#-wg-policy-ctl-cli-usage) - [Systemd Integration](#-systemd-integration-watcher-daemon) ### WGRplane (Go App) - [WGRplane Overview](#-wgrplane-overview) - [WGRplane Architecture](#-wgrplane-architecture) - [WGRplane Features](#-wgrplane-features) - [WGRplane Tech Stack](#-wgrplane-tech-stack) - [WGRplane API Endpoints](#-wgrplane-api-endpoints) - [WGRplane Installation](#-wgrplane-installation) --- ## 🎯 Architecture & Data Flow 1. **`wg0.conf`**: The standard WireGuard configuration. Contains standard `[Peer]` configs alongside a custom `#Access` tag. 2. **`wg-sync-policy.sh`**: Safely parses `wg0.conf` and generates a structured `/etc/wireguard/policy.json` atomically. 3. **`wg-policy-engine.sh`**: Reads `policy.json` to generate robust rules, applying `iptables` and `ipset` directly to the system. 4. **Watcher Daemon**: Monitors `wg0.conf` for changes via `inotifywait` and triggers the pipeline seamlessly when updates are made. --- ## πŸ“ Installation The easiest way to install is using the provided `install.sh` script, which automatically installs dependencies, copies all scripts to `/usr/local/bin/`, sets up the systemd daemon, and enables the service. ```bash # Install everything sudo ./install.sh install # Uninstall everything sudo ./install.sh uninstall ``` ### Building the Installer (For Developers) If you modify any of the source `.sh` or `.service` files, you must rebuild the `install.sh` script using the provided builders. **On Linux (Bash):** ```bash ./build.sh ``` **On Windows (CMD/PowerShell):** ```cmd build.bat ``` --- ## πŸ“¦ Prerequisites | Package | Required | Install | |---------|----------|---------| | `jq` | **Yes** | `apt install jq` | | `inotify-tools` | **Yes** (for watcher daemon) | `apt install inotify-tools` | | `ipset` | Optional | `apt install ipset` | If `ipset` is not installed, the engine will automatically fall back to per-rule `iptables` whitelist entries. This works fine for small deployments. For large numbers of clients/targets, `ipset` is recommended for O(1) lookup performance. --- ## βš™οΈ Integrasi ke `wg0.conf` To integrate the engine, you need to append hooks into your `wg0.conf` interface block, and declare the `#Access` tags under each peer. ### 1. Interface Block (Hooks) Add the `PostUp` and `PostDown` scripts so the engine initializes correctly during VPN startup and removes traces upon shutdown. > **⚠️ WireGuard does NOT support multiline values.** Every command must be on a `PostUp = ...` or `PostDown = ...` line. Bare commands without the `PostUp =` prefix will cause `Configuration parsing error`. ```ini [Interface] Address = 10.0.0.1/24 ListenPort = 51820 PrivateKey = # Policy engine: auto-handles NAT, IP forwarding, and dynamic firewall rules PostUp = /usr/local/bin/wg-sync-policy.sh; /usr/local/bin/wg-policy-engine.sh # Policy engine: cleanup all firewall and routing traces PostDown = /usr/local/bin/wg-policy-cleanup.sh ``` ### 2. Peer Block (`#Access` Tags) For each client, use the `#Access` comment line. Define the destinations (targets) the peer is allowed to access. You can separate multiple IPs or CIDRs with commas or semicolons. > **⚠️ WARNING: Do NOT use `SaveConfig = true`!** > WireGuard's `SaveConfig` feature overwrites `wg0.conf` directly and **strips all comments**, which will permanently delete all `#Access` tags. If you are using a Web UI/Dashboard, make sure it does not strip unknown comments when saving. ```ini [Peer] PublicKey = AllowedIPs = 10.0.0.2/32 #Access 192.168.1.10/32, 192.168.12.0/24 [Peer] PublicKey = AllowedIPs = 10.0.0.3/32 #Access = 10.0.0.1/32 [Peer] PublicKey = AllowedIPs = 10.0.0.4/32 #Access # ^ (Empty Access implies internet-only, client isolation applies) ``` **⚠️ Important constraint:** Why `#Access` instead of just using `AllowedIPs` directly? WireGuard uses `AllowedIPs` for Cryptokey Routing (deciding which tunnel interface to route outbound packets). If you put an internal server IP inside the server's `wg0.conf` AllowedIPs block, WireGuard will aggressively capture and redirect packets bound for that internal server into the VPN client's tunnel. The `#Access` comment separates routing parameters from firewall parameters cleanly. --- ## πŸ›  `wg-policy-ctl` CLI Usage You don't need to manually interact with `iptables` or `.json` files. Use the `wg-policy-ctl` wrapper. ```bash # View the health of the firewall engine and active locks wg-policy-ctl status # View the raw, parsed JSON policy wg-policy-ctl policy # Inspect active iptables rules wg-policy-ctl rules # Check memory sets mapping IP targets (ipset) wg-policy-ctl ipset # Manually re-sync rules immediately wg-policy-ctl reload # Inspect dropped packets (rate-limited log output) wg-policy-ctl log # See connection statistics, how many targets loaded wg-policy-ctl stats # Force validation of the policy schema wg-policy-ctl validate ``` --- ## πŸ”§ Systemd Integration (Watcher Daemon) If you use the `install.sh` script, the daemon is automatically installed, enabled, and started for you. It monitors `wg0.conf` for changes and triggers the pipeline seamlessly. ### Manual File Installation (If not using install.sh) Place the three provided systemd unit files into `/etc/systemd/system/`. | Systemd File | Location | Description | |--------------|----------|-------------| | `wg-policy.service` | `/etc/systemd/system/wg-policy.service` | The main daemon that runs `wg-sync-watch.sh` | | `wg-policy-health.timer` | `/etc/systemd/system/wg-policy-health.timer` | Triggers the health check every 5 minutes | | `wg-policy-health.service`| `/etc/systemd/system/wg-policy-health.service`| Executes the actual health check logic | ```bash # Example copy command cp wg-policy.service wg-policy-health.timer wg-policy-health.service /etc/systemd/system/ ``` ### 2. Enable & Start Services After copying the files, reload systemd to recognize them, then enable and start the services. ```bash systemctl daemon-reload systemctl enable wg-policy.service systemctl enable wg-policy-health.timer systemctl start wg-policy.service systemctl start wg-policy-health.timer ``` Check the watcher logs: ```bash journalctl -u wg-policy.service -f ``` --- ## πŸš€ WGRplane Overview **WGRplane** is a Go-native WireGuard control plane application with a Vue 3 frontend, providing a modern web dashboard for WireGuard management. It features a single Go binary backend, SPA frontend, dynamic policy firewall integration, and glassmorphism UI design. The application lives in the `/app` directory. For full documentation, see [`app/README.md`](app/README.md). --- ## πŸ— WGRplane Architecture ``` wg0.conf (with/without #Access) ↓ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ WGRplane (Go Binary :10087) β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Gorilla β”‚ β”‚ GORM β”‚ β”‚ nftables β”‚ β”‚ β”‚ β”‚ Mux Routerβ”‚ β”‚ SQLite β”‚ β”‚ Engine β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Webhook β”‚ β”‚ Schedulerβ”‚ β”‚ WebSocketβ”‚ β”‚ β”‚ β”‚ Engine β”‚ β”‚ Cron β”‚ β”‚ Hub β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Auth β”‚ β”‚ SMTP β”‚ β”‚ Plugins β”‚ β”‚ β”‚ β”‚ JWT/TOTP β”‚ β”‚ Email β”‚ β”‚ TG/Slack β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ↓ HTTP/WebSocket β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Frontend (Vue 3 + TypeScript + Tailwind) β”‚ β”‚ Glassmorphism UI, i18n, Dark/Light mode β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### Hybrid Mode WGRplane supports two server modes: - **`forward`** - Directly applies nftables rules on the local machine. Peer policies are enforced via `nft` commands. - **`standalone`** - Acts as a control plane that triggers webhooks to remote WireGuard servers. Policy enforcement happens on the remote side. ### 2-Column Policy Each peer has two independent policy columns: | Column | Function | |--------|----------| | **AllowAccess** | List of CIDRs the peer can access (internal targets) | | **AllowInternet** | Boolean flag. If `true`, peer gets unlimited internet access (MASQUERADE) | Peers without any rules are isolated from other peers and the internet by default. --- ## ✨ WGRplane Features - **Go-Native Architecture**: Single Go binary handles all API, database, webhooks, scheduler, and nftables. No Python/Flask needed. - **Complete Peer CRUD**: Add, edit, delete peers. Generate QR codes for mobile client import. Export `.conf` configuration files. - **Hybrid Mode**: `forward` mode (local nftables) or `standalone` mode (webhook to remote servers). - **2-Column Policy UI**: "Allow Access" column (firewall whitelist CIDR) and "Allow Internet" toggle per peer. - **Real-time Monitoring**: WebSocket broadcasts peer statistics and traffic every 5 seconds. - **Automated Scheduling**: Daily cron jobs to delete expired peers, restrict over-limit peers, and reset monthly data usage. - **Security**: API Key authentication (`wg-rplane-datadunia`), JWT Bearer tokens, and TOTP (2FA). - **Webhook Engine**: Integration with remote servers (Mikrotik, etc.). Retry with exponential backoff, custom headers, Go templates. - **Plugin System**: Telegram, Slack, and Traffic Logger notifications. - **i18n & Themes**: Multi-language (English, Indonesian, Chinese). Dark/Light/Auto mode. - **Glassmorphism UI**: Futuristic design with frosted glass cards, buttons, and inputs. --- ## πŸ›  WGRplane 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) | | **Firewall** | Bash, iptables, ipset, nftables, inotify-tools, jq | | **Container** | Docker (multi-stage build), docker-compose | --- ## 🌐 WGRplane API Endpoints Summary All endpoints are served on port **10087**. For complete API documentation with request/response details, see [`app/README.md`](app/README.md) or visit `/swagger/` on your running instance. ### Authentication | 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 | ### Main Endpoints | Endpoint | Method | Description | |----------|--------|-------------| | `/api/servers` | `GET/POST` | List all servers / Create new server | | `/api/servers/{id}` | `GET/PUT/DELETE` | Get/Update/Delete server | | `/api/servers/{id}/peers` | `GET/POST` | List peers / Create new peer | | `/api/peers/{id}` | `PUT/DELETE` | Update/Delete peer | | `/api/peers/{id}/config` | `GET` | Download WireGuard `.conf` file | | `/api/peers/{id}/qrcode` | `GET` | Generate QR code PNG for mobile import | | `/api/servers/{id}/webhooks` | `GET/POST` | List/Create webhooks | | `/api/stats` | `GET` | Global statistics | | `/ws/stats` | WebSocket | Real-time stats broadcast (5s interval) | | `/swagger/` | - | Interactive Swagger UI documentation | --- ## πŸ“¦ WGRplane Installation ### Option 1: Docker Compose (Recommended) ```bash # Clone repository git clone https://git.datadunia.com/hainzero/WGRplane.git cd 03.wireguard-policy # Start WGRplane and WireGuard docker compose up -d # Access dashboard at http://localhost:10087 ``` ### Option 2: Install Script ```bash # Run automated installer (Ubuntu/Debian/CentOS) sudo ./install.sh install # Uninstall sudo ./install.sh uninstall ``` ### Option 3: Manual Build ```bash # Build Go binary cd app go build -o ../wgrplane . cd .. # Build frontend cd app/frontend npm install && npm run build cd ../.. # Run ./wgrplane # Server starts on :10087 ``` ### Option 4: Systemd Service ```bash # Install service file sudo cp wgrplane.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable wgrplane.service sudo systemctl start wgrplane.service # View logs journalctl -u wgrplane.service -f ``` --- ## πŸ“ Project Structure ``` 03.wireguard-policy/ β”œβ”€β”€ app/ # Go backend + Vue frontend β”‚ β”œβ”€β”€ main.go # Bootstrap server, routing, init DB β”‚ β”œβ”€β”€ handlers.go # REST API route handlers β”‚ β”œβ”€β”€ models.go # GORM models (Server, Peer, Webhook, SMTP) β”‚ β”œβ”€β”€ auth.go # JWT, TOTP, API key auth middleware β”‚ β”œβ”€β”€ nftables.go # nftables rule management (mode forward) β”‚ β”œβ”€β”€ webhook.go # Webhook engine with retry/backoff β”‚ β”œβ”€β”€ scheduler.go # Cron jobs (expiry, data limit, reset) β”‚ β”œβ”€β”€ stats.go # WebSocket Hub for real-time stats β”‚ β”œβ”€β”€ frontend/ # Vue 3 SPA (TypeScript, TailwindCSS) β”‚ └── docs/ # Swagger documentation β”œβ”€β”€ wg-sync-policy.sh # Parse wg0.conf β†’ policy.json β”œβ”€β”€ wg-policy-engine.sh # Apply policy.json β†’ iptables/ipset β”œβ”€β”€ wg-sync-watch.sh # inotifywait watcher daemon β”œβ”€β”€ wg-policy-ctl # CLI wrapper for policy management β”œβ”€β”€ wg-policy-cleanup.sh # Cleanup script for PostDown β”œβ”€β”€ wg-policy.service # Systemd unit for watcher daemon β”œβ”€β”€ wgrplane.service # Systemd unit for Go backend β”œβ”€β”€ install.sh # Automated installer (Docker + services) β”œβ”€β”€ Dockerfile # Multi-stage Docker build β”œβ”€β”€ docker-compose.yml # Docker Compose stack └── README.md # This file ``` For detailed WGRplane documentation including webhooks, plugins, scheduler, and frontend details, refer to [`app/README.md`](app/README.md).