WGRplane - WireGuard Remote Plane Control
WGRplane adalah aplikasi WireGuard Control Plane berbasis Go-native dengan frontend Vue 3. Single binary untuk backend, SPA untuk frontend, dilengkapi dynamic policy firewall dan glassmorphism UI.
Fitur Utama
- Arsitektur Go-Native: Single Go binary (
main.go) menangani semua API, database, webhook, scheduler, dan nftables. Tidak ada Python/Flask. - Peer CRUD Lengkap: Tambah, edit, hapus peer. Generate QR code untuk import ke mobile client. Export file konfigurasi
.conf. - Hybrid Mode: Mode
forward(nftables lokal) ataustandalone(webhook ke server remote). - 2-Column Policy UI: Kolom "Allow Access" (firewall whitelist CIDR) dan "Allow Internet" (MASQUERADE toggle) per peer.
- Real-time Monitoring: WebSocket broadcast statistik peer dan trafik setiap 5 detik.
- Automated Scheduling: Cron job harian untuk hapus peer expired, restriksi peer over-limit, dan reset data usage bulanan.
- Security: Autentikasi API Key (
wg-rplane-datadunia), JWT Bearer token, dan TOTP (2FA). - Webhook Engine: Integrasi dengan server remote (Mikrotik, dll). Retry dengan exponential backoff, custom headers, Go template.
- Plugin System: Notifikasi Telegram, Slack, dan Traffic Logger.
- i18n & Themes: Multi-bahasa (English, Indonesian, Chinese). Dark/Light/Auto mode.
- Glassmorphism UI: Desain futuristik dengan frosted glass cards, buttons, dan inputs.
Arsitektur
wg0.conf (dengan/tanpa #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 │
└─────────────────────────────────────────────┘
Data Flow Policy Firewall
wg0.conf (#Access comments)
↓ inotifywait detects change
wg-sync-watch.sh (debounced trigger)
↓
wg-sync-policy.sh (parses wg0.conf → policy.json, atomic write)
↓
wg-policy-engine.sh (reads policy.json → iptables/ipset rules)
↓
Active firewall rules (WG_POLICY chain)
Tech Stack
| Komponen | Teknologi |
|---|---|
| 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 dengan retry + exponential backoff |
| Scheduling | robfig/cron v3 |
| QR Code | skip2/go-qrcode |
| jordan-wright/email (SMTP) | |
| Firewall | Bash, iptables, ipset, nftables, inotify-tools, jq |
| Container | Docker (multi-stage build), docker-compose |
Port & Autentikasi
| Service | Port | Autentikasi |
|---|---|---|
| WGRplane (Go API + Frontend) | 10087 | API Key (wg-rplane-datadunia) atau JWT Bearer + TOTP opsional |
Metode Autentikasi
| Metode | Header | Catatan |
|---|---|---|
| API Key | wg-rplane-datadunia: <KEY> |
Diatur via env var WG_API_KEY. Default: test-api-key. |
| JWT | Authorization: Bearer <TOKEN> |
Expired 15 menit. Secret via env var JWT_SECRET. |
| TOTP | X-TOTP: <CODE> |
Wajib jika user mengaktifkan TOTP. |
API Endpoints
Semua endpoint dilayani di port 10087.
Servers
| Endpoint | Method | Deskripsi |
|---|---|---|
/api/servers |
GET |
Daftar semua server WireGuard. |
/api/servers |
POST |
Buat server baru. Body: {name, mode, publicKey, endpoint}. |
/api/servers/{id} |
GET |
Ambil satu server berdasarkan ID. |
/api/servers/{id} |
PUT |
Update server (name, mode, publicKey, endpoint). |
/api/servers/{id} |
DELETE |
Hapus server beserta peer dan webhook-nya. |
Peers
| Endpoint | Method | Deskripsi |
|---|---|---|
/api/servers/{id}/peers |
GET |
Daftar semua peer untuk satu server. |
/api/servers/{id}/peers |
POST |
Buat peer baru. Body: {publicKey, ip, allowAccess, allowInternet}. Mode forward langsung apply nftables, mode standalone trigger webhook. |
/api/peers/{id} |
PUT |
Update peer. Hitung diff dan apply perubahan nftables incremental. |
/api/peers/{id} |
DELETE |
Hapus peer. Bersihkan rule nftables dan trigger webhook. |
/api/peers/{id}/config |
GET |
Download file konfigurasi WireGuard .conf. |
/api/peers/{id}/qrcode |
GET |
Generate QR code PNG untuk import ke mobile client. |
Webhooks
| Endpoint | Method | Deskripsi |
|---|---|---|
/api/servers/{id}/webhooks |
GET |
Daftar webhook untuk satu server. |
/api/servers/{id}/webhooks |
POST |
Buat webhook. Body: {name, url, template, customBody, customHeaders, subscribedActions, isEnabled, verifySSL}. |
/api/webhooks/{id} |
DELETE |
Hapus webhook. |
SMTP Settings
| Endpoint | Method | Deskripsi |
|---|---|---|
/api/settings/smtp |
GET |
Ambil konfigurasi SMTP saat ini. |
/api/settings/smtp |
POST |
Simpan/update pengaturan SMTP untuk notifikasi email. |
Statistics
| Endpoint | Method | Deskripsi |
|---|---|---|
/api/stats |
GET |
Statistik global: total server, peer, webhook. |
/api/servers/{id}/stats |
GET |
Statistik per server: jumlah peer, webhook, detail server. |
WebSocket
| Endpoint | Protokol | Deskripsi |
|---|---|---|
/ws/stats |
WebSocket | Broadcast statistik real-time (interval 5 detik). |
TOTP Setup
| Endpoint | Method | Deskripsi |
|---|---|---|
/auth/setup-totp?user=<USER> |
GET |
Generate TOTP secret dan provisioning URI untuk user. |
Swagger Documentation
| Endpoint | Deskripsi |
|---|---|
/swagger/ |
Swagger UI untuk dokumentasi API interaktif. |
Hybrid Mode
Backend Go mendukung dua mode server:
forward-- Instance WGRplane langsung apply rule nftables di mesin lokal. Policy peer enforced langsung via perintahnft.standalone-- Instance bertindak sebagai control plane yang trigger webhook ke server WireGuard remote. Policy enforcement terjadi di sisi remote.
2-Column Policy
Setiap peer memiliki dua kolom policy independen:
| Kolom | Fungsi |
|---|---|
| AllowAccess | Daftar CIDR yang bisa dijangkau peer (target internal). |
| AllowInternet | Boolean flag. Jika true, peer mendapat akses internet tanpa batas (MASQUERADE). |
Peer yang tidak punya rule apapun terisolasi dari peer lain dan dari internet secara default.
Instalasi
Opsi 1: Docker Compose (Direkomendasikan)
# Clone repository
git clone https://git.datadunia.com/hainzero/WGRplane.git
cd 03.wireguard-policy
# Start WGRplane dan WireGuard
docker compose up -d
# Akses dashboard
# http://localhost:10087
Stack compose menjalankan:
- WGRplane di port
10087(Go API + Vue frontend) - WireGuard container dengan host networking untuk akses kernel module
Opsi 2: Install Script
# Jalankan installer otomatis (Ubuntu/Debian/CentOS)
sudo ./install.sh install
# Uninstall
sudo ./install.sh uninstall
Install script menangani instalasi Docker, cloning repository, pembuatan .env, dan startup service.
Opsi 3: Manual Build
# Build binary Go
cd app
go build -o ../wgrplane .
cd ..
# Build frontend
cd app/frontend
npm install && npm run build
cd ../..
# Jalankan
./wgrplane
# Server start di :10087
Opsi 4: Systemd Service
# Install service file
sudo cp wgrplane.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable wgrplane.service
sudo systemctl start wgrplane.service
# Lihat log
journalctl -u wgrplane.service -f
Konfigurasi
Environment Variables
| Variable | Default | Deskripsi |
|---|---|---|
WG_API_KEY |
test-api-key |
API key untuk autentikasi header-based. |
JWT_SECRET |
secret |
Secret untuk signing JWT token. |
APP_FRONTEND_DIR |
/var/www/frontend |
Path ke asset frontend yang sudah di-build. |
WG_RPLANE_MODE |
forward |
Mode server default (forward atau standalone). |
Database
WGRplane menggunakan SQLite secara default (wgrplane.db). Model auto-migrate saat startup:
- Server -- Entry server WireGuard dengan mode dan endpoint.
- Peer -- Entry peer dengan IP, rule akses, limit data, expiry.
- Webhook -- Konfigurasi webhook dengan template dan filter aksi.
- SMTPSettings -- Konfigurasi server SMTP untuk notifikasi email.
Scheduler
Backend Go menjalankan tiga cron job:
| Jadwal | Job | Aksi |
|---|---|---|
| Setiap hari 02:00 | deleteExpiredPeers |
Hapus peer yang sudah melewati ExpiresAt. |
| Setiap hari 03:00 | restrictOverLimitPeers |
Disable peer yang melebihi DataLimitGB. |
| Tanggal 1 setiap bulan | resetMonthlyUsage |
Reset CurrentDataUsageBytes ke nol untuk semua peer. |
Webhook Payload
Webhook trigger pada event lifecycle peer (peer_created, peer_updated, peer_deleted, policy_changed). Engine mendukung tiga mode template: default (JSON mentah), mikrotik (format RouterOS), dan custom (Go template).
Fitur Webhook
- Retry dengan backoff: Delivery gagal retry hingga 3 kali dengan exponential backoff (2s, 4s, 8s).
- Verifikasi SSL: Bisa di-toggle per-webhook via
verifySSL. - Custom headers: Inject header per-webhook via
customHeadersJSON. - Global webhooks: Set
isGlobal: trueuntuk trigger di semua server. - Filter aksi: Subscribe ke event spesifik via array
subscribedActions.
UI Frontend
Frontend adalah Vue 3 + TypeScript SPA dengan desain glassmorphism.
Design System
- Glassmorphism: Frosted glass cards, buttons, dan inputs dengan efek backdrop blur.
- TailwindCSS 4: Utility-first styling dengan dukungan dark mode penuh via
dark:variants. - Responsive: Layout mobile-first yang adaptif di semua ukuran layar.
Fitur UI
| Fitur | Deskripsi |
|---|---|
| Multi-bahasa (i18n) | English, Indonesian, dan Chinese via vue-i18n 9. Locale auto-detect dari browser. |
| Theme Switching | Dark / Light / Auto (ikuti preferensi sistem) via @vueuse/core. |
| Real-time Stats | Koneksi WebSocket broadcast jumlah peer dan data trafik setiap 5 detik. |
| Charts | Visualisasi trafik via Chart.js + vue-chartjs. |
| Toast Notifications | Alert non-intrusif via vue-sonner. |
| QR Code Import | Generate QR code yang bisa di-scan untuk setup mobile WireGuard client. |
Struktur Frontend
app/frontend/src/
├── App.vue # Root component dengan provider theme/i18n
├── main.ts # Bootstrap app (Vue, Router, i18n)
├── router/ # Definisi Vue Router
├── i18n/ # File locale (en.json, id.json, zh.json)
├── components/ # Komponen Glass UI (Card, Button, Input, Toggle)
├── composables/ # Vue composables (useTheme, useWebSocket)
├── views/ # Page components (Dashboard, Servers, Peers, Settings, Webhooks)
└── types/ # Definisi tipe TypeScript
Policy Firewall (#Access)
Engine policy berbasis shell enforcing rule firewall per-peer langsung dari wg0.conf.
Cara Kerja
- Tambahkan komentar
#Accessdi bawah setiap blok[Peer]diwg0.conf. - Watcher daemon (
wg-sync-watch.sh) mendeteksi perubahan file viainotifywait. wg-sync-policy.shparse config dan tulispolicy.jsonsecara atomik.wg-policy-engine.shbaca JSON dan apply rule iptables/ipset.
Contoh wg0.conf
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>
PostUp = /usr/local/bin/wg-sync-policy.sh; /usr/local/bin/wg-policy-engine.sh
PostDown = /usr/local/bin/wg-policy-cleanup.sh
[Peer]
PublicKey = <CLIENT_1_PUBKEY>
AllowedIPs = 10.0.0.2/32
#Access 192.168.1.10/32, 192.168.12.0/24
[Peer]
PublicKey = <CLIENT_2_PUBKEY>
AllowedIPs = 10.0.0.3/32
#Access 10.0.0.1/32
[Peer]
PublicKey = <CLIENT_3_PUBKEY>
AllowedIPs = 10.0.0.4/32
#Access
# Access kosong = internet-only, isolasi client berlaku
Mengapa #Access Bukan AllowedIPs?
WireGuard menggunakan AllowedIPs untuk Cryptokey Routing. Memasukkan IP destinasi di AllowedIPs server akan menyebabkan WireGuard meroute traffic untuk IP tersebut ke dalam tunnel client. Komentar #Access memisahkan konfigurasi firewall dari routing secara bersih.
CLI: wg-policy-ctl
wg-policy-ctl status # Health check, status lock, jumlah rule
wg-policy-ctl policy # Lihat raw policy.json
wg-policy-ctl rules # Inspect rule iptables aktif
wg-policy-ctl ipset # Lihat mapping ipset
wg-policy-ctl reload # Force re-sync dan re-apply
wg-policy-ctl log # Lihat log packet dropped
wg-policy-ctl stats # Statistik koneksi
wg-policy-ctl validate # Validasi schema policy.json
Prerequisites
| Package | Diperlukan | Install |
|---|---|---|
jq |
Ya | apt install jq |
inotify-tools |
Ya (watcher daemon) | apt install inotify-tools |
ipset |
Opsional | apt install ipset |
Tanpa ipset, engine fallback ke entry iptables per-rule. Ini bekerja untuk deployment kecil. Untuk jumlah peer besar, ipset memberikan performa lookup O(1).
Plugins
Sistem plugin menyediakan interface notifikasi sederhana. Plugin bawaan:
- TelegramNotifier -- Kirim pesan Telegram saat event.
- SlackNotifier -- Kirim pesan Slack saat event.
- TrafficLogger -- Log event traffic untuk debugging.
Plugin dimuat saat startup via PluginManager.LoadPlugins() dan menerima event melalui Trigger(event, payload).
Struktur Proyek
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 dengan retry/backoff
│ ├── scheduler.go # Cron jobs (expiry, data limit, reset)
│ ├── stats.go # WebSocket Hub untuk real-time stats
│ ├── email.go # Notifikasi email SMTP
│ ├── plugins.go # Plugin system (Telegram, Slack, Logger)
│ ├── validation.go # Input validators (IP, CIDR, PublicKey)
│ ├── wg.go # WireGuard key generation, config export
│ ├── i18n.go # Backend i18n (en/id/zh)
│ ├── docs/ # Swagger documentation
│ └── frontend/ # Vue 3 SPA (TypeScript, TailwindCSS)
├── 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 untuk manajemen
├── wg-policy-cleanup.sh # Cleanup script untuk PostDown
├── wg-policy.service # Systemd unit untuk watcher daemon
├── wgrplane.service # Systemd unit untuk Go backend
├── install.sh # Automated installer (Docker + services)
├── Dockerfile # Multi-stage Docker build
├── docker-compose.yml # Docker Compose stack
├── build.sh / build.bat # Script rebuild installer
└── README.md # Dokumentasi ini
Testing
Manual QA
# Test auth (tanpa header)
curl http://localhost:10087/api/servers
# Expected: 401 Unauthorized
# Test auth (header salah)
curl -H "wg-rplane-datadunia: wrong" http://localhost:10087/api/servers
# Expected: 401 Unauthorized
# Test auth (header benar)
curl -H "wg-rplane-datadunia: test-api-key" http://localhost:10087/api/servers
# Expected: 200 OK, daftar server
# Test buat server
curl -X POST \
-H "Content-Type: application/json" \
-H "wg-rplane-datadunia: test-api-key" \
-d '{"name":"wg-01","mode":"forward","publicKey":"<PUBKEY>","endpoint":"vpn.example.com:51820"}' \
http://localhost:10087/api/servers
# Test buat peer
curl -X POST \
-H "Content-Type: application/json" \
-H "wg-rplane-datadunia: test-api-key" \
-d '{"publicKey":"<PEER_PUBKEY>","ip":"10.0.0.2","allowAccess":["192.168.1.0/24"],"allowInternet":true}' \
http://localhost:10087/api/servers/1/peers
# Test QR code
curl -H "wg-rplane-datadunia: test-api-key" http://localhost:10087/api/peers/1/qrcode --output peer-qr.png
# Verifikasi rule iptables
wg-policy-ctl rules
Dokumentasi Tambahan
- Plan File:
plan.md(detail rencana implementasi) - AGENTS.md: Panduan untuk AI agent dalam mengembangkan proyek ini
- Parent Repo:
https://git.datadunia.com/hainzero/WGRplane.git(submodule di/app)
Lisensi
Proyek ini membangun konsep dari WGDashboard (donaldzou/WGDashboard) dengan modifikasi untuk integrasi policy.json API dan dynamic firewall enforcement.