Add wireguard-ui-multi core: multi-server DB, WireGuard manager, REST API, UI, installers
Implements the from-scratch multi-server WireGuard management fork per CLAUDE.md spec: sqlite schema (servers/peers/audit_log/users), Curve25519 key generation, per-interface config rendering + wg-quick/systemd control, nftables hook scaffolding, session+CSRF-protected REST API with QR code and config download endpoints, a minimal vanilla-JS web UI, legacy wg0.conf migration, and both a native installer and a Proxmox LXC provisioning script (with auto-detected latest Debian template). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
3d6608ef80
commit
3b3ffd8ebf
@@ -0,0 +1,234 @@
|
||||
# wireguard-ui-multi
|
||||
|
||||
Native Multi-Server-Verwaltungsoberfläche für WireGuard — **ohne Docker**.
|
||||
Im Gegensatz zum ursprünglichen `wireguard-ui`, das genau eine WireGuard-Instanz
|
||||
verwaltet, kann `wireguard-ui-multi` mehrere unabhängige WireGuard-Interfaces
|
||||
gleichzeitig verwalten (z. B. `wg-home`, `wg-rz`, `wg-winter`), jedes mit
|
||||
eigenem Port, eigenem Adressbereich, eigenen Peers und eigenem Status.
|
||||
|
||||
Zielumgebungen: Debian/Ubuntu, Proxmox LXC Container, generisches Linux mit
|
||||
systemd. Betrieb als natives Go-Binary.
|
||||
|
||||
## Features
|
||||
|
||||
- **Multi-Server-Verwaltung**: beliebig viele WireGuard-Server, jeder mit
|
||||
eigenem Interface-Namen, Port, Private/Public Key, Adressbereich, DNS, MTU
|
||||
und Enabled/Disabled-Status (Tabelle `servers` in SQLite).
|
||||
- **Peer-Verwaltung pro Server**: Peers gehören zu genau einem Server
|
||||
(Fremdschlüssel `server_id`), inklusive Name, E-Mail, Public/Private/
|
||||
Preshared Key, Allowed IPs, Endpoint, Persistent Keepalive, Enabled-Status
|
||||
und optionalem Ablaufdatum (`expires_at`).
|
||||
- **Automatische Config-Erzeugung**: Server-Configs werden nach
|
||||
`/etc/wireguard/<interface>.conf` im Standard-`wg-quick`-Format geschrieben.
|
||||
- **Service-Steuerung**: Start/Stop/Reload je Interface über `wg-quick up`,
|
||||
`wg-quick down` und `wg syncconf` (Hot-Reload ohne Verbindungsabbruch),
|
||||
Status-Abfrage über `wg show`.
|
||||
- **QR-Code & Config-Download**: Peer-Konfiguration kann als `.conf`-Datei
|
||||
heruntergeladen oder als QR-Code (PNG) angezeigt werden — Private Keys
|
||||
verlassen den Server nur in dieser generierten Peer-Config, nie über die
|
||||
UI/JSON-API.
|
||||
- **REST-API** für Server- und Peer-Verwaltung (siehe unten) plus
|
||||
Web-Dashboard.
|
||||
- **Firewall-Vorbereitung**: optionale Lifecycle-Hook-Skripte
|
||||
(`server-start`, `server-stop`, `peer-add`, `peer-remove`) in
|
||||
`/etc/wireguard-manager/hooks/` sowie ein Generator für einen
|
||||
Vorschlags-nftables-Ruleset pro Server (Port freigeben, Forwarding
|
||||
Tunnel ↔ LAN-Interface).
|
||||
- **Audit Log**: Tabelle `audit_log` protokolliert Aktionen mit Akteur,
|
||||
Aktion, Ziel und Detail.
|
||||
- **Sitzungsbasierte Authentifizierung** mit CSRF-Schutz: jede mutierende
|
||||
Anfrage (POST/PUT/DELETE) benötigt einen gültigen Session-Cookie plus
|
||||
den Header `X-CSRF-Token`.
|
||||
- Optional HTTPS über `--tls-cert` / `--tls-key`.
|
||||
|
||||
## Installation
|
||||
|
||||
### 1. Aus dem Quellcode bauen
|
||||
|
||||
```bash
|
||||
go build -o wireguard-ui-multi ./cmd/wireguard-ui-multi
|
||||
```
|
||||
|
||||
### 2. Installationsskript ausführen (als root)
|
||||
|
||||
```bash
|
||||
sudo ./scripts/install.sh
|
||||
```
|
||||
|
||||
Das Skript ist idempotent und:
|
||||
|
||||
- kopiert die Binary nach `/usr/local/bin/wireguard-ui-multi`
|
||||
- legt `/etc/wireguard-ui-multi`, `/var/lib/wireguard-ui-multi` und
|
||||
`/etc/wireguard-manager/hooks` an
|
||||
- installiert die systemd-Unit nach
|
||||
`/etc/systemd/system/wireguard-ui-multi.service`
|
||||
- setzt `chmod 0700` auf das Datenverzeichnis (dort liegt die SQLite-DB mit
|
||||
Passwort-Hashes)
|
||||
|
||||
**Wichtig:** Das Skript startet den Dienst nicht automatisch. Danach manuell
|
||||
aktivieren:
|
||||
|
||||
```bash
|
||||
sudo systemctl enable --now wireguard-ui-multi.service
|
||||
sudo systemctl status wireguard-ui-multi.service
|
||||
sudo journalctl -u wireguard-ui-multi.service -f
|
||||
```
|
||||
|
||||
## Konfiguration
|
||||
|
||||
Die Anwendung wird über Kommandozeilen-Flags konfiguriert (siehe
|
||||
`cmd/wireguard-ui-multi/main.go`):
|
||||
|
||||
| Flag | Default | Bedeutung |
|
||||
|----------------|-------------------------------------------------------|-------------------------------------------------------|
|
||||
| `--listen` | `:8443` | Listen-Adresse des Webservers |
|
||||
| `--db` | `/var/lib/wireguard-ui-multi/wireguard-ui-multi.db` | Pfad zur SQLite-Datenbankdatei |
|
||||
| `--config-dir` | `/etc/wireguard` | Zielverzeichnis für generierte `wg-quick`-Configs |
|
||||
| `--hooks-dir` | `/etc/wireguard-manager/hooks` | Verzeichnis mit optionalen Hook-Skripten |
|
||||
| `--lan-iface` | `eth0` | LAN-Interface für die vorgeschlagenen nftables-Forward-Regeln |
|
||||
| `--tls-cert` | (leer) | Pfad zum TLS-Zertifikat (aktiviert HTTPS zusammen mit `--tls-key`) |
|
||||
| `--tls-key` | (leer) | Pfad zum TLS-Private-Key |
|
||||
|
||||
Die in `systemd/wireguard-ui-multi.service` hinterlegte `ExecStart`-Zeile
|
||||
setzt `--db`, `--config-dir` und `--hooks-dir` bereits passend zur
|
||||
Installationsstruktur.
|
||||
|
||||
### Erststart / Admin-Passwort
|
||||
|
||||
Beim allerersten Start (leere `users`-Tabelle) wird automatisch ein
|
||||
`admin`-Benutzer mit einem zufällig erzeugten 32-stelligen Hex-Passwort
|
||||
angelegt. Das Klartext-Passwort wird **genau einmal** auf `stderr`
|
||||
ausgegeben (z. B. sichtbar via `journalctl -u wireguard-ui-multi.service`)
|
||||
und danach nur noch als bcrypt-Hash in der Datenbank gespeichert. Nach dem
|
||||
ersten Login sollte das Passwort umgehend geändert werden.
|
||||
|
||||
## LXC / Proxmox Hinweise
|
||||
|
||||
WireGuard benötigt Zugriff auf das `wireguard`-Kernelmodul des Hosts sowie
|
||||
`CAP_NET_ADMIN` und Zugriff auf `/dev/net/tun` im Container:
|
||||
|
||||
- Auf dem **Proxmox-Host** muss das `wireguard`-Kernelmodul geladen sein
|
||||
(`modprobe wireguard`; bei Bedarf `/etc/modules` ergänzen).
|
||||
- Der LXC-Container sollte entweder **privilegiert** betrieben werden, oder
|
||||
als unprivilegierter Container mit gezielten Lockerungen
|
||||
(`lxc.cap.drop` ohne `net_admin`, `lxc.cgroup2.devices.allow: c 10:200 rwm`
|
||||
für `/dev/net/tun`) konfiguriert werden. In der Praxis ist ein
|
||||
privilegierter Container für WireGuard-Hosting deutlich unkomplizierter.
|
||||
- `/dev/net/tun` muss im Container vorhanden und beschreibbar sein
|
||||
(`ls -l /dev/net/tun`); ggf. per Bind-Mount/`lxc.mount.entry` durchreichen.
|
||||
- Die systemd-Unit läuft als `root` mit `AmbientCapabilities=CAP_NET_ADMIN`,
|
||||
weil sie `wg-quick`, `systemctl` und `nft` aufruft — diese Tools benötigen
|
||||
in der Praxis root-Rechte im Container.
|
||||
- Läuft `nftables` bereits als eigener Dienst im Container/Host, sollte der
|
||||
von `wireguard-ui-multi` vorgeschlagene Ruleset (siehe unten) manuell in
|
||||
die bestehende Regelbasis integriert statt blind angewendet werden, um
|
||||
Konflikte mit vorhandenen Tabellen/Chains zu vermeiden.
|
||||
|
||||
## Server- & Peer-Verwaltung
|
||||
|
||||
**Server anlegen** (UI oder `POST /api/servers`): Name, Interface-Name
|
||||
(z. B. `wg-home`), Listen-Port, Adressbereich (z. B. `10.20.22.0/24`), DNS,
|
||||
MTU angeben. Private/Public Key werden serverseitig automatisch erzeugt.
|
||||
|
||||
**Server starten/stoppen/neuladen**: über die Dashboard-Buttons oder
|
||||
`POST /api/servers/{id}/start|stop|reload`. Start schreibt zunächst die
|
||||
`wg-quick`-Config nach `/etc/wireguard/<interface>.conf` und ruft dann
|
||||
`wg-quick up <interface>` auf; Reload nutzt `wg syncconf` für einen
|
||||
Hot-Reload ohne Tunnelabbruch.
|
||||
|
||||
**Peer hinzufügen** (UI oder `POST /api/server/{id}/peer`): Name, optional
|
||||
E-Mail/Beschreibung und Ablaufdatum angeben — Schlüsselpaar und Preshared
|
||||
Key werden automatisch generiert.
|
||||
|
||||
**Config/QR-Code abrufen**: `GET /api/server/{id}/peer/{peerid}/config`
|
||||
liefert die fertige `.conf`-Datei zum Download, `GET
|
||||
/api/server/{id}/peer/{peerid}/qrcode` liefert denselben Inhalt als
|
||||
PNG-QR-Code zum Scannen mit der WireGuard-App.
|
||||
|
||||
### REST-API-Übersicht
|
||||
|
||||
```
|
||||
POST /api/login
|
||||
POST /api/logout
|
||||
|
||||
GET /api/servers
|
||||
POST /api/servers
|
||||
GET /api/servers/{id}
|
||||
PUT /api/servers/{id}
|
||||
DELETE /api/servers/{id}
|
||||
POST /api/servers/{id}/start
|
||||
POST /api/servers/{id}/stop
|
||||
POST /api/servers/{id}/reload
|
||||
GET /api/servers/{id}/config
|
||||
|
||||
GET /api/server/{id}/peers
|
||||
POST /api/server/{id}/peer
|
||||
DELETE /api/server/{id}/peer/{peerid}
|
||||
GET /api/server/{id}/peer/{peerid}/config
|
||||
GET /api/server/{id}/peer/{peerid}/qrcode
|
||||
```
|
||||
|
||||
Alle Endpunkte außer `/api/login` erfordern einen gültigen Session-Cookie;
|
||||
mutierende Methoden (POST/PUT/DELETE) benötigen zusätzlich den Header
|
||||
`X-CSRF-Token` mit dem beim Login ausgegebenen Token.
|
||||
|
||||
## Backup / Restore
|
||||
|
||||
Ein automatisiertes Backup-/Restore-Werkzeug ist aktuell **nicht**
|
||||
implementiert. Für ein manuelles Backup genügt es, folgende Pfade zu
|
||||
sichern:
|
||||
|
||||
- die SQLite-Datenbank: `/var/lib/wireguard-ui-multi/wireguard-ui-multi.db`
|
||||
(enthält Server, Peers, Keys, Audit Log, Benutzer)
|
||||
- die generierten Interface-Configs: `/etc/wireguard/*.conf`
|
||||
- ggf. eigene Hook-Skripte: `/etc/wireguard-manager/hooks/`
|
||||
|
||||
Beispiel:
|
||||
|
||||
```bash
|
||||
sudo tar czf wireguard-ui-multi-backup-$(date +%F).tar.gz \
|
||||
/var/lib/wireguard-ui-multi/wireguard-ui-multi.db \
|
||||
/etc/wireguard/*.conf \
|
||||
/etc/wireguard-manager/hooks
|
||||
```
|
||||
|
||||
**Restore**: Dienst stoppen, Archiv an denselben Pfaden entpacken,
|
||||
Berechtigungen prüfen (`chmod 0700` auf das Datenverzeichnis) und Dienst
|
||||
wieder starten:
|
||||
|
||||
```bash
|
||||
sudo systemctl stop wireguard-ui-multi.service
|
||||
sudo tar xzf wireguard-ui-multi-backup-YYYY-MM-DD.tar.gz -C /
|
||||
sudo systemctl start wireguard-ui-multi.service
|
||||
```
|
||||
|
||||
## Migration von einer bestehenden wireguard-ui-Installation
|
||||
|
||||
Für den Umstieg von einer klassischen Single-Interface-Installation
|
||||
(`/etc/wireguard/wg0.conf`) ist ein Migrationswerkzeug vorgesehen, das eine
|
||||
bestehende `wg0.conf` einliest und als ersten verwalteten Server samt seiner
|
||||
Peers importiert. Damit lässt sich eine vorhandene WireGuard-Instanz
|
||||
übernehmen, ohne bestehende Clients neu konfigurieren zu müssen. Details zum
|
||||
genauen Ablauf und den Aufrufoptionen siehe die Implementierung im
|
||||
`wireguard`-Package des Repos, sobald verfügbar; grundsätzlich gilt: vor der
|
||||
Migration ein Backup der bestehenden `wg0.conf` anlegen.
|
||||
|
||||
## Sicherheitshinweise
|
||||
|
||||
- **Private Keys werden nie im Frontend/JSON angezeigt** — sie werden
|
||||
ausschließlich serverseitig in generierten `.conf`-Dateien bzw.
|
||||
QR-Codes für einzelne Peers ausgeliefert.
|
||||
- **HTTPS verwenden**: entweder direkt über `--tls-cert`/`--tls-key`, oder
|
||||
die Anwendung hinter einem Reverse Proxy (nginx, Caddy, Traefik) mit
|
||||
TLS-Terminierung betreiben. Ohne TLS gibt der Dienst beim Start eine
|
||||
deutliche Warnung aus.
|
||||
- **Standard-Admin-Passwort sofort ändern**: das beim Erststart einmalig
|
||||
ausgegebene zufällige Passwort sollte direkt nach dem ersten Login
|
||||
geändert werden.
|
||||
- Mutierende API-Aufrufe erfordern einen gültigen Session-Cookie **und**
|
||||
den CSRF-Header `X-CSRF-Token` — Clients/Skripte, die die API direkt
|
||||
ansprechen, müssen sich zunächst über `/api/login` anmelden und den
|
||||
zurückgegebenen Token mitführen.
|
||||
- Die Datenverzeichnisse (`/var/lib/wireguard-ui-multi`) sollten
|
||||
restriktive Berechtigungen (`0700`) behalten, da dort Schlüsselmaterial
|
||||
und Passwort-Hashes liegen.
|
||||
|
||||
Reference in New Issue
Block a user