GNAI-006: WG_ALLOWED_IPS Split-Tunnel Befund + Konfig gesetzt (Android /32-Limitierung, Step 8 aufgeteilt)

This commit is contained in:
2026-09-19 15:53:25 +02:00
parent 5a5f7aca40
commit 8a81f92ac1
2 changed files with 29 additions and 19 deletions
+19 -10
View File
@@ -4,7 +4,7 @@
**Titel:** Homelab / Infrastructure – WireGuard VPN Gateway (LXC) Setup & Access Control
**Version:** 1.1
**Version:** 1.2
**Status:** In Umsetzung (Schritt 1–4 & 7 fertig, Step 5/6/9 offen)
@@ -50,7 +50,13 @@ Dieses Dokument beschreibt die verbindliche Einrichtung, Härtung und Verifikati
* **AllowedIPs Client-Seitig:** `10.0.0.90/32`
* **Erlaubte Ziele:** Exklusiv LLM-Server (`10.0.0.90`, z. B. SSH Port 22)
> **Hinweis wg-easy / AllowedIPs (Umsetzung 2026-09-09):** Die **serverseitige** `AllowedIPs`-Eintragung wird von wg-easy beim Konfig-Generate hartkodiert als `client.address/32` (`/app/lib/WireGuard.js`, `__saveConfig()`). Es existiert **kein API-Endpoint**, um die serverseitigen AllowedIPs abweichend zu setzen. Für die gewünschte Architektur ist dies korrekt: Serverseitig darf ein Peer nur aus seiner eigenen VPN-IP kommen; das **Routing (Split-Tunneling) wird clientseitig** über die AllowedIPs im heruntergeladenen Profil bestimmt (FullAdmin: `10.0.0.0/24, 10.8.0.0/24`; LLMAdmin: `10.0.0.90/32, 10.8.0.0/24`). **Offen:** Verifikation, dass die exportierten Client-Profile diese clientseitigen AllowedIPs enthalten (wg-easy bietet hierzu je nach Version nur eingeschränkte Konfiguration – siehe Implementation-Log, Punkt „allowedIPs-Limitation“).
> **Hinweis wg-easy / AllowedIPs (Umsetzung 2026-09-09):** Die **serverseitige** `AllowedIPs`-Eintragung wird von wg-easy hartkodiert als `client.address/32` (`/app/lib/WireGuard.js`, `__saveConfig()`) – korrekt für diese Architektur (Peer kommt nur aus seiner eigenen VPN-IP). Das **clientseitige Routing** (Split-Tunneling) wird in den heruntergeladenen Profilen aus der Env-Variable **`WG_ALLOWED_IPS`** generiert (`/app/lib/WireGuard.js`, `getClientConfiguration()`). Default von wg-easy wäre `0.0.0.0/0, ::/0` (Full-Tunnel!) – **umgestellt auf Split-Tunnel** via `/opt/wg-easy/environment`:
>
> ```
> WG_ALLOWED_IPS=10.0.0.0/24,10.8.0.0/24,10.0.0.2/32,10.0.0.10/32,10.0.0.90/32
> ```
>
> ⚠️ **Android-Limitierung:** WireGuard für Android akzeptiert in `AllowedIPs` nur `/32`-Einträge (keine `/24`-CIDRs). Die zusätzlichen `/32`-Einträge (Fritzbox, Proxmox, NPM, LLM-Server) existieren daher **ausschließlich** für Android-LLMAdmin; Laptop-FullAdmin nutzt die `/24`-Netzwerke. Konsequenz: Neue LAN-Hosts müssen **beide** Einträge pflegen (CIDR + `/32`) – kein per-Client-Override in wg-easy möglich (eine Env-Variable für alle Profile).
---
@@ -201,15 +207,17 @@ Peers über die wg-easy-API erstellt (UI unter `http://10.0.0.15:51821`, Login `
Server-Config `wg0.conf` enthält beide Peers mit `PresharedKey`; serverseitig `AllowedIPs = 10.8.0.2/32` bzw. `10.8.0.3/32` (wg-easy-Hardcode, siehe Hinweis in Sektion 2).
Verifikation ausstehend: ⏳ heruntergeladene Client-Profile auf clientseitige `AllowedIPs`, `Endpoint vpn.ghostnet.selfhost.eu:51820` und `PersistentKeepalive = 25` kontrollieren (abhängig von Step 5/6).
Verifikation ausstehend: ⏳ heruntergeladene Client-Profile auf clientseitige `AllowedIPs` (aus `WG_ALLOWED_IPS`) und `Endpoint vpn.ghostnet.selfhost.eu:51820` kontrollieren (abhängig von Step 5/6). Hinweis: `WG_PERSISTENT_KEEPALIVE` ist nicht gesetzt (Default `0`) – bei NAT/Router-Wechsel-Problemen auf `25` setzen.
### 8. Split-Tunneling-Routing verifizieren ⏳
### 8. Split-Tunneling-Routing verifizieren ⏳ (Konfig gesetzt, End-to-End offen)
Abhängig von Step 7. Falls die exportierten wg-easy-Profile die clientseitigen AllowedIPs nicht wie gewünscht enthalten, sind Alternativen zu evaluieren:
✅ **Erledigt (2026-09-09):** `WG_ALLOWED_IPS` in `/opt/wg-easy/environment` gesetzt (Split-Tunnel statt wg-easy-Default Full-Tunnel), `wg-easy.service` neu gestartet, Env im Container verifiziert.
* wg-easy-Einstellungen/Version prüfen (neuere Versionen unterstützen clientseitige `AllowedIPs`-Overrides, z. B. über `WG_ALLOWED_IPS`-Template oder Peer-Settings)
* Manuelle Client-Configs als Fallback (QR/Datei direkt aus `wg0.conf`-Daten + clientseitiger Keys)
* Direct-Edit von `/opt/wg-easy/data/wg0.json` nur für serverseitige Exceptions (hier **nicht** erforderlich)
⏳ **Offen (abhängig von Step 5/6 + Endgerät):**
* Heruntergeladenes Profil Laptop-FullAdmin: `AllowedIPs = 10.0.0.0/24,10.8.0.0/24,…` + `Endpoint vpn.ghostnet.selfhost.eu:51820` prüfen, LAN-Hosts durch VPN erreichbar, Internet-Traffic bleibt **außerhalb** des Tunnels
* Android-LLMAdmin: Routing nur auf `10.0.0.90` (LLM-Server) + VPN-Subnetz; andere LAN-Hosts nicht über VPN erreichbar
* DNS `10.0.0.1` via `WG_DEFAULT_DNS` (nur innerhalb Tunnelsolutions relevant – prüfen, ob Android DNS-Einstellung akzeptiert)
### 9. Penetrationstest & Ingress-Verifikation über Mobilfunk ⏳
@@ -247,8 +255,8 @@ Deaktiviere WLAN auf beiden Testgeräten (reiner 4G/5G-Pfad), VPN aktivieren:
| 4 | wg-easy Quadlet + wg0 | ✅ |
| 5 | Fritzbox Portforward | ⏳ User |
| 6 | NPM-Subdomain `vpn.ghostnet.selfhost.eu` | ⏳ User |
| 7 | Peers Laptop-FullAdmin / Android-LLMAdmin | ✅ (Client-Config-Verifikation offen) |
| 8 | Split-Tunnel-Routing verifizieren | ⏳ |
| 7 | Peers Laptop-FullAdmin / Android-LLMAdmin | ✅ |
| 8 | Split-Tunnel-Konfig (`WG_ALLOWED_IPS`) | ✅ (End-to-End-Verifikation ⏳ mit Step 9) |
| 9 | Penetrationstest Mobilfunk | ⏳ |
Details & Entscheidungen: siehe `GNAI-006-SEC_VPN_Implementation-Log.md`.
@@ -261,3 +269,4 @@ Details & Entscheidungen: siehe `GNAI-006-SEC_VPN_Implementation-Log.md`.
| --- | --- | --- |
| 1.0 | – | Erster Draft |
| 1.1 | 2026-09-09 | Umsetzung dokumentiert: Hostname `wireguard` (nicht `wireguard-gateway`); Testmatrix auf „Ausstehend“ (keine Tests über Mobilfunk gelaufen); `PASSWORD_HASH` = bcrypt (wg-easy/bcryptjs), nicht Argon2; Quadlet mit `EnvironmentFile=`; nftables-Konfig & ip_forward dokumentiert; wg-easy-allowedIPs-Limitation vermerkt; Umsetzungszustand-Tabellen & Implementation-Log ergänzt |
| 1.2 | 2026-09-09 | Split-Tunneling konkretisiert: clientseitige AllowedIPs kommen aus Env-Variable `WG_ALLOWED_IPS` (Default `0.0.0.0/0` = Full-Tunnel!); `WG_ALLOWED_IPS` in `/opt/wg-easy/environment` gesetzt, Container neu gestartet, Env im Container verifiziert; Android-/24-Limitierung dokumentiert (nur `/32`-Einträge); Schritt 8 in „Konfig gesetzt / End-to-End offen“ zerlegt; `WG_PERSISTENT_KEEPALIVE`-Hinweis ergänzt |
+10 -9
View File
@@ -2,6 +2,7 @@
**Bezug:** GNAI-006-SEC_VPN.md
**Session:** 2026-09-09 (Agent-Session, Arbeit per SSH auf LXC 105)
**Letzte Aktualisierung:** 2026-09-09 16:50 – `WG_ALLOWED_IPS`-Befund (Sektion 3.3), Split-Tunnel-Konfig auf LXC gesetzt, O3/O4 aktualisiert
**Zweck:** Nachvollziehbare Dokumentation der Umsetzungsschritte, Abweichungen vom Draft, technischen Befunde und Fehlerbehebungen.
---
@@ -87,13 +88,13 @@ Client-UUIDs (LXC): `Laptop-FullAdmin` = `2e9ed910-36dc-4fbd-8694-8d904670ea19`,
* **Serverseitig:** `__saveConfig()` in `/app/lib/WireGuard.js` (Container) generiert pro Peer `AllowedIPs = ${client.address}/32` – hartkodiert. Das Feld `allowedIPs` im internen `wg0.json` existiert, wird vom Create-Endpoint aber **nie** befüllt (stets `None`).
* **Konsequenz:** Es gibt keinen API-Path, um serverseitige AllowedIPs freier zu konfigurieren (z. B. ein Peer aus mehreren VPN-IPs).
* **Architektonische Bewertung:** Für unser Modell ist das serverseitige `/32`-Verhalten **korrekt und gewünscht**: Ein Peer darf nur Traffic aus seiner eigenen VPN-IP senden. Das eigentliche Routing (Split-Tunneling) ist **clientseitig** bestimmt – die AllowedIPs im installierten Client-Profil entscheiden, welche Zielnetzwerke über den Tunnel laufen.
* **Offene Frage / nächste Verifikation:** ob die via wg-easy heruntergeladenen Client-Profile die gewünschten clientseitigen AllowedIPs enthalten:
* FullAdmin: `10.0.0.0/24, 10.8.0.0/24`
* LLMAdmin: `10.0.0.90/32` (ggf. `10.8.0.0/24` zusätzlich, damit Peer-seitiges Routing sauber bleibt)
* **Falls nicht:** Optionen (in dieser Reihenfolge):
1. wg-easy-Einstellungen/Version prüfen – neuere Releases bieten Peer-spezifische `allowedIPs`-Overrides bzw. Template-Erweiterung (z. B. `WG_ALLOWED_IPS` / `allowedIPs` im JSON + Config-Regeneration)
2. Client-Profile manuell aus den generierten `wg0.conf`-Daten + den clientseitigen Keys basteln (einmalige Aktion, dokumentierbar)
3. Direct-Edit `/opt/wg-easy/data/wg0.json` + `wg-quick`-Reload – **nicht** für den hier relevanten Fall (serverseitig ist `/32` korrekt)
* **Clientseitig (gelöst 2026-09-09):** `getClientConfiguration()` in `/app/lib/WireGuard.js` generiert in den herunterladbaren Profilen `AllowedIPs = ${WG_ALLOWED_IPS}` – eine **globale** Env-Variable (kein per-Client-Override). Default: `0.0.0.0/0, ::/0` = **Full-Tunnel** (alle Traffic durch VPN) – nicht gewünscht.
* **Aktion:** `WG_ALLOWED_IPS` in `/opt/wg-easy/environment` ergänzt (Backup `environment.bak.<ts>`), `wg-easy.service` neu gestartet, Env im Container verifiziert:
```
WG_ALLOWED_IPS=10.0.0.0/24,10.8.0.0/24,10.0.0.2/32,10.0.0.10/32,10.0.0.90/32
```
* **Android-Limitierung:** WireGuard für Android akzeptiert in `AllowedIPs` nur `/32` (keine `/24`-CIDRs). Die `/32`-Einträge (Fritzbox `.1`, Proxmox `.2`, NPM `.10`, LLM-Server `.90`) existieren daher explizit für Android-LLMAdmin; Laptop-FullAdmin nutzt die `/24`-Netzwerke. **Pflege-Konsequenz:** Neue LAN-Hosts müssen beide Varianten erhalten (CIDR + `/32`), danach `wg-easy.service` neu starten.
* **End-to-End-Verifikation (O4) bleibt offen:** heruntergeladene Profile prüfen (AllowedIPs + Endpoint), dann Routing-Tests auf den Endgeräten.
---
@@ -118,8 +119,8 @@ Client-UUIDs (LXC): `Laptop-FullAdmin` = `2e9ed910-36dc-4fbd-8694-8d904670ea19`,
| --- | --- | --- | --- |
| O1 | Fritzbox 7530: Portforward **UDP 51820 → 10.0.0.15** | 👤 User | – |
| O2 | NPM (10.0.0.10): Subdomain `vpn.ghostnet.selfhost.eu` anlegen | 👤 User | – |
| O3 | Client-Profile herunterladen (Laptop + Android), AllowedIPs/`Endpoint`/`PersistentKeepalive=25` prüfen | Agent + User | O1, O2 |
| O4 | Split-Tunnel-Routing end-zu-end verifizieren (Step 8 SOP) | Agent + User | O3 |
| O3 | Client-Profile herunterladen (Laptop + Android), `AllowedIPs` (aus `WG_ALLOWED_IPS`) + `Endpoint vpn.ghostnet.selfhost.eu:51820` prüfen | Agent + User | O1, O2 |
| O4 | Split-Tunnel-Routing end-zu-end verifizieren (Step 8 SOP; Konfig steht, s. 3.3) | Agent + User | O3 |
| O5 | Penetrationstest Mobilfunk (Testmatrix Sektion 4 SOP) | gemeinsam | O1, O2, O3 |
| O6 | Entscheidung: wg-easy-`PostUp`-iptables-Regeln via `WG_POST_UP`/`WG_PRE_DOWN` deaktivieren (hygiene) oder belassen (redundant, kein Konflikt) | Agent | O5 (nach Tests) |
| O7 | Projekt-Kontext in `MEMORY.md` / Memory-Store persistieren | Agent | – |