Files
infrastructure/docs/GNAI-006-SEC_VPN.md
T
2026-09-19 15:55:58 +02:00

21 KiB
Raw Blame History

Technische Architekturbeschreibung – WireGuard-Gateway

Dokumenten-ID: GNAI-006-SEC
Status: Dokumentation bereinigt; technische Umsetzung und Abnahme teilweise offen
Referenzen: Zielarchitektur, Zugriffskonzept, GUI-SOP, Implementation-Log

Änderungsverlauf

Datum Version Autor Änderung
2026-09-09 1.0–1.5 spektr Aufbau und Migration von v14 auf v15; historische Details im Implementation-Log
2026-09-15 2.0 spektr Rollen Familie/Server Admin/LLM Admin; bestätigtes LXC und Hooks; NAT-Abhängigkeit; v15-Bereinigung; getrennte SOPs und belastbarer Abnahmestatus
2026-09-18 2.1 spektr Lesenden Gateway-Abgleich, iptables-legacy-Befund und DNS-Abgleich ergänzt; Betriebshinweise entsprechend korrigiert.

1. Zweck und dokumentierter Stand

Das Gateway ermöglicht administrativen und familiären Fernzugriff auf das Heimnetz. WireGuard authentifiziert Geräte durch Schlüssel; die Zielsysteme verlangen weiterhin ihre eigene Anmeldung. Ein Peer wird pro Gerät vergeben. Eine gemeinsame Konfiguration für mehrere gleichzeitig verwendete Geräte ist nicht vorgesehen.

Das WireGuard-Gateway läuft bereits. Die nachfolgende Installation beschreibt seinen reproduzierbaren Aufbau; neue Sicherheitsmaßnahmen sind als Soll gekennzeichnet. Grundlage sind die Quellen, die Tests vom 12.09.2026, die vom Betreiber bereitgestellte Konfiguration und der lesende Gateway-Abgleich vom 18.09.2026. Es wurden keine Systemkonfigurationen geändert und keine neuen Client- oder Rollentests durchgeführt.

Wesentliche offene Umsetzung: Per-Client Firewall ist deaktiviert. Die bisherige breite Forward-Regel erzwingt keine Rollenisolierung. HTTPS für die wg-easy-GUI ist noch nicht eingerichtet. Der dokumentierte Endpoint vpn.ghostnet.selfhost.eu stimmte am 18.09.2026 mit der ausgehenden IPv4 des Gateways überein; die DynDNS-Aktualisierung nach einem Adresswechsel ist noch nicht nachgewiesen.

2. Architektur und Adressplan

Komponente Adresse / Konfiguration
Fritzbox 7530 10.0.0.1, Gateway, DNS und DynDNS-Updater
Proxmox / Mediaserver 10.0.0.2
NPM, CT 103 10.0.0.10; TCP 80/443 öffentlich, TCP 81 administrativ
WireGuard, CT 105 10.0.0.15/24, Hostname wireguard
KI-Server 10.0.0.90, Hostname ghostnet-ki
Statischer Server-/LXC-Adressbereich bis .99; konkrete Belegung siehe GNAI-003
DHCP-Clients 10.0.0.100–10.0.0.200
VPN-Netz / Gateway 10.8.0.0/24 / 10.8.0.1
WireGuard-Port UDP 51820
wg-easy-GUI, Ist http://10.0.0.15:51821

Die Fritzbox leitet TCP 80/443 an 10.0.0.10 und UDP 51820 an 10.0.0.15 weiter. NPM ist nicht am WireGuard-Datenpfad beteiligt. Es gibt keine Fritzbox-Rückroute zum VPN-Netz; wg-easy verwendet deshalb MASQUERADE auf dem LAN-Ausgang.

flowchart TD
    W["Externe Clients"] --> F["Fritzbox 7530"]
    F -->|"TCP 80/443"| N["NPM · 10.0.0.10"]
    F -->|"UDP 51820"| V["wg-easy · 10.0.0.15"]
    N --> A["Öffentliche Anwendungen"]
    V --> R["Peer-Firewall · Soll; NAT · Ist"]
    R --> S["Proxmox, LXCs und KI-Server"]
    R -->|"nur Familie"| C["Heimnetz-PCs und Clients"]

Die Adressgruppierung im selben /24 bildet keine Netzwerksegmentierung. Server-, Heim- und Gästenetz können später in einem eigenen Netzwerk-Sprint durch separate Netze, Routing und passende Hardware geordnet werden. Für diesen Sprint werden weder neue Subnetze noch VLAN-IDs angenommen.

2.1 Rollen und Durchsetzung

Rolle Erlaubte Ziele Client-Routing und serverseitige Firewall
Familie gesamtes Heimnetz einschließlich PCs und Clients Heimnetz 10.0.0.0/24; Zugriff auf das Gateway zusätzlich nach Bedarf explizit festlegen
Server Admin Proxmox, aktuelle Service-LXCs und KI-Server; wg-easy-GUI eingeschlossen einzelne freigegebene Hostadressen aus dem Inventar; kein pauschales Heimnetz-/24
LLM Admin KI-Server 10.0.0.90 10.0.0.90/32; keine Freigabe für Proxmox, NPM oder wg-easy

Diese Vorgaben erlauben Netzwerkzugriff auf die genannten Hosts. Anwendungs-, SSH- und Betriebssystemrechte werden separat vergeben. Ein statischer Adressbereich ist kein ausreichender Nachweis, dass jede Adresse darin ein Server ist: Erweiterungen benötigen einen Inventareintrag und die passende Peer-Freigabe.

Soll: In wg-easy die Per-Client Firewall aktivieren und für jeden Peer Firewall Allowed IPs ausdrücklich setzen. Allowed IPs im exportierten Profil steuert weiter das Split-Tunnel-Routing. Server Allowed IPs bezeichnet die Netze, die der Server zum Peer routet; für ein einzelnes Endgerät bleibt das dessen eigene VPN-IP /32. Diese drei Felder dürfen nicht miteinander verwechselt werden. Client-Felder

Die Funktion ist laut offizieller Dokumentation experimentell. Abnahme muss absichtliche Erweiterungen der clientseitigen AllowedIPs auf gesperrte Ziele einschließen. Insbesondere muss der Zugriff auf lokale Gateway-Dienste geprüft werden, da dieser die INPUT- statt FORWARD-Chain durchläuft. Per-Client Firewall

3. Installation im Proxmox-LXC

3.1 LXC erstellen und Netzwerk konfigurieren

In Proxmox ein unprivileged Debian-13-LXC mit diesen Werten erstellen:

Parameter bestätigter Wert
CT-ID / Hostname 105 / wireguard
Betriebssystem / Architektur Debian 13 Trixie / amd64
CPU / RAM / Swap 1 Core / 512 MiB / 512 MiB
RootFS 4 GiB, local-lvm
Features nesting=1,keyctl=1
Netz eth0, vmbr0, 10.0.0.15/24, Gateway 10.0.0.1
Start / Zeitzone onboot: 1 / Europe/Berlin
Proxmox-Version, Quellenstand 9.2.11; bei Reproduktion installierte Version festhalten

Auf dem Proxmox-Host in /etc/pve/lxc/105.conf ergänzen, ohne vorhandene Einträge doppelt anzulegen:

lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file

Nach einer Änderung CT 105 neu starten. Im LXC prüfen:

ls -l /dev/net/tun
ip -4 addr show eth0
ip -4 route show

WireGuard im Kernel verwendet ein WireGuard-Netzinterface. TUN ist Teil der bestätigten LXC-Baseline und unterstützt mögliche Userspace-Implementierungen; sein Vorhandensein allein beweist keine funktionierende WireGuard-Kernelunterstützung. Fehlende Kernelmodule werden auf dem Proxmox-Host untersucht, nicht durch pauschale SYS_MODULE- oder privileged-Freigaben im LXC ersetzt.

3.2 Pakete, Administrator und persistente Verzeichnisse

Im LXC als root bzw. mit sudo installieren:

sudo apt update
sudo apt install podman nftables iptables iproute2 procps curl sudo openssh-server
sudo install -d -m 700 /opt/wg-easy/data
sudo install -d -m 755 /etc/containers/systemd
sudo install -m 600 /dev/null /opt/wg-easy/environment

Der letzte Befehl ist ausschließlich für eine Neuinstallation: ein vorhandenes Environment-File nicht überschreiben. Dokumentiert ist Podman 5.4.2. Die durch Debian bereitgestellte Version mit podman --version festhalten und Quadlet-Unterstützung prüfen.

Den Benutzer admin nur anlegen, wenn er noch nicht existiert. SSH-Key hinterlegen und Rechte testen. Für die SSH-Härtung die allgemeinen Prüfschritte aus GNAI-002 auf diesen LXC übertragen; dessen KI-Server-Konten und Netzwerte nicht übernehmen. Im bestehenden WireGuard-LXC ist admin ALL=(ALL) NOPASSWD: ALL eingerichtet; das ist der bestätigte Ist-Stand und keine allgemeine Vorgabe für alle LLM-Benutzer. Änderungen an SSH immer mit einer offenen zweiten Sitzung oder Proxmox-Konsole absichern.

3.3 IP-Forwarding

/etc/sysctl.d/99-ipforward.conf:

net.ipv4.ip_forward=1

Anwenden und prüfen:

sudo sysctl --system
sysctl net.ipv4.ip_forward

Erwartet: net.ipv4.ip_forward = 1. Die bestätigten LXC-Routen sind:

default via 10.0.0.1 dev eth0 proto kernel onlink
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.15
10.8.0.0/24 dev wg0 proto kernel scope link src 10.8.0.1

Die VPN-Route entsteht erst mit dem Interface. Bei Neuinstallation vor dem ersten wg-easy-Start ist sie noch nicht vorhanden.

3.4 nftables-Baseline: Ist und erforderliche Erweiterung

Die Quellen dokumentieren folgende Baseline in /etc/nftables.conf. Ein lesender Live-Abgleich der entscheidenden INPUT- und FORWARD-Regeln am 18.09.2026 bestätigt weiterhin die breite VPN→LAN-Freigabe; das vollständige Regelwerk ist im Implementation-Log nicht als neue Gesamtabnahme ausgewiesen:

#!/usr/sbin/nft -f
flush ruleset

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;
        iifname "lo" accept
        ct state invalid drop
        ct state established,related accept
        icmp type { echo-request, echo-reply, destination-unreachable, time-exceeded } accept
        udp dport 51820 accept
        ip saddr 10.0.0.0/24 tcp dport { 22, 51821 } accept
        limit rate 4/second burst 8 packets log prefix "nft-input-dropped: "
        drop
    }
    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state invalid drop
        ct state established,related accept
        iifname "wg0" ip daddr 10.0.0.0/24 ct state new accept
        oifname "wg0" ip saddr 10.0.0.0/24 ip daddr 10.8.0.0/24 ct state new accept
        drop
    }
    chain output {
        type filter hook output priority filter; policy accept;
    }
}

Diese Baseline ist keine fertige Rollen-Firewall. Die breite FORWARD-Freigabe muss gemeinsam mit Per-Client Firewall getestet werden. Die INPUT-Regel erlaubt LAN-Quellen, aber noch keine neuen Verbindungen von VPN-Quellen 10.8.0.x auf TCP 22/51821. Für Familie und Server Admins muss am Gateway eine ausdrückliche INPUT-Freigabe anhand ihrer zugewiesenen VPN-IP oder einer gepflegten Peer-IP-Menge hinzukommen. LLM Admins dürfen diese Ports auch nach einer lokalen Routingänderung nicht erreichen. Die Rollenzuordnung vorhandener Peers ist noch offen; daher wird keine angeblich fertige IP-Regel erfunden.

flush ruleset löscht dynamisch angelegte nftables-/iptables-nft-Regeln. Der Live-Abgleich am 18.09.2026 zeigte jedoch wg-easy-Hooks in iptables-legacy; diese werden durch einen nftables-Flush nicht automatisch mit gelöscht. Beide Regelwerke und ihre gemeinsame Wirkung müssen nach Reload oder Neustart geprüft werden. Bei einer Neuinstallation zuerst die Baseline laden, danach wg-easy starten. Im laufenden Betrieb vor einem Reload Regelzustand sichern und Änderung über die Proxmox-Konsole ausführen. Dauerhafte Regeln und dynamische Regeln brauchen eine getestete Start-/Reload-Reihenfolge; diese Abnahme steht noch aus.

sudo nft -c -f /etc/nftables.conf
sudo nft -f /etc/nftables.conf
sudo systemctl enable nftables.service
sudo nft list ruleset

Diese Befehle sind Installationsschritte, keine Empfehlung zum ungeprüften Reload einer laufenden Umgebung. IPv6 im LXC und am Perimeter separat prüfen. DISABLE_IPV6=true in wg-easy ersetzt keine Prüfung der IPv6-Erreichbarkeit anderer Dienste.

3.5 Rootful Podman-Quadlet

Bestätigter /opt/wg-easy/environment-Stand aus dem v15-Hauptdokument; bei Installation mit dem tatsächlichen Environment abgleichen:

INSECURE=true
DISABLE_IPV6=true
DISABLE_VERSION_CHECK=true

INSECURE=true erlaubt derzeit HTTP. Die VPN-Konfiguration und Administratoranmeldung liegen in v15 in der SQLite-Datenbank, nicht in den alten v14-Variablen WG_HOST, WG_ALLOWED_IPS oder PASSWORD_HASH. Ein fester Image-Pin verhindert unkontrollierte Versionswechsel; eine dauerhafte Aussage über den veränderlichen latest-Tag wird nicht vorausgesetzt. Konfiguration

Bestätigter /etc/containers/systemd/wg-easy.container:

[Container]
Image=ghcr.io/wg-easy/wg-easy:15.4.0
ContainerName=wg-easy
Network=host
AddCapability=NET_ADMIN
AddCapability=NET_RAW
EnvironmentFile=/opt/wg-easy/environment
Volume=/opt/wg-easy/data:/etc/wireguard:rw

[Service]
Restart=on-failure

[Install]
WantedBy=multi-user.target

Network=host bezieht sich auf den Netzwerknamespace des LXC, nicht auf den Proxmox-Host. Das Quadlet läuft rootful im LXC. Quadlet generiert wg-easy.service; die generierte Unit wird nicht direkt bearbeitet oder wie eine normale statische Unit enabled.

sudo systemctl daemon-reload
sudo systemctl start wg-easy.service
sudo systemctl status wg-easy.service
sudo podman ps
sudo journalctl -u wg-easy.service -n 100 --no-pager

Nach Quadlet-Änderungen daemon-reload und restart ausführen. Autostart von LXC, nftables und wg-easy sowie persistentes Forwarding gemeinsam durch einen geplanten Reboot testen. Die bisherige Dokumentation ist kein Nachweis dieser vollständigen Wiederanlaufprüfung.

4. wg-easy erstmalig konfigurieren

  1. Aus dem vertrauenswürdigen LAN http://10.0.0.15:51821 öffnen. Im vorhandenen System ist der Wizard bereits abgeschlossen.
  2. Bei Neuinstallation Administrator-Benutzername und Passwort im Wizard setzen. Zugangsdaten im Passwortmanager hinterlegen; keine Secrets in Dokumente kopieren.
  3. Für Neuinstallation kein vorhandenes v14-Backup importieren. Der historische v14→v15-Import ist ausschließlich im Implementation-Log dokumentiert.
  4. Als Host vpn.ghostnet.selfhost.eu und als Port 51820 eintragen; vor Ausgabe neuer Profile DNS-Auflösung und aktuelle WAN-IP erneut vergleichen.
  5. Interface-Adressraum 10.8.0.0/24, Gateway 10.8.0.1 und IPv4-Betrieb prüfen. In Admin Panel → Interface das LAN-Ausgangsgerät eth0 prüfen.
  6. Neue Client-Defaults so wählen, dass neue Peers keine ungeprüften Vollzugriffsrechte erhalten. Für jede Freigabe gilt die separate GUI-SOP; ein Default ist keine Rollenzuordnung.
  7. DNS rollenabhängig setzen: Familie kann die Fritzbox 10.0.0.1 über das Heimnetz erreichen. Server Admins und LLM Admins verwenden zunächst System-DNS, sofern keine gesonderte DNS-Freigabe beschlossen wird. Historischer Laptop-DNS 10.0.0.1 ist kein pauschaler neuer Default.
  8. Per-Client Firewall für die neue Rollenpolitik aktivieren und abnehmen. Vor Aktivierung vorhandene Peers erfassen, Änderungen über LAN durchführen und unzugeordnete Peers während der Umstellung gesperrt halten.

Offizieller Setup-Ablauf

4.1 Bestätigte Server-Hooks und NAT-Abhängigkeit

PreUp und PreDown sind leer. Bestätigter PostUp:

iptables -t nat -A POSTROUTING -s {{ipv4Cidr}} -o {{device}} -j MASQUERADE; iptables -A INPUT -p udp -m udp --dport {{port}} -j ACCEPT; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT;

Bestätigter PostDown:

iptables -t nat -D POSTROUTING -s {{ipv4Cidr}} -o {{device}} -j MASQUERADE; iptables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT;

Das sind wg-easy-Templates; nicht unverändert als Terminalbefehle ausführen. Prüfen, dass die Platzhalter auf 10.8.0.0/24, eth0 und 51820 aufgelöst werden. MASQUERADE wird beibehalten, solange keine getestete Rückroute eingerichtet ist. Das Entfernen aller Hooks würde den dokumentierten LAN-Zugriff gefährden. Die ACCEPT-Regeln sind breit; ihre Reihenfolge und Wirkung mit den Per-Client-Regeln müssen geprüft werden.

sudo podman exec wg-easy iptables -V
sudo podman exec wg-easy iptables -S
sudo podman exec wg-easy iptables -t nat -S
sudo nft list ruleset
sudo iptables-legacy -S FORWARD
sudo iptables-legacy -t nat -S POSTROUTING
sudo podman exec wg-easy wg show wg0

Mit iptables-nft werden Regeln in nftables sichtbar; bei iptables-legacy zusätzlich dessen eigenen Zustand berücksichtigen. Der Standardaufruf iptables -S zeigte am 18.09.2026 nur die nft-Ansicht und warnte vor vorhandenen Legacy-Tabellen. Ein ACCEPT in einer Base-Chain garantiert keine Freigabe gegenüber anderen Base-Chains; ein DROP ist abschließend. Eine pauschale Aussage „kein Konflikt“ ist deshalb kein Ersatz für Regel- und Verkehrstests. nftables-Verarbeitung

5. HTTPS und Erreichbarkeit der Verwaltungs-GUI

Ist: HTTP auf TCP 51821, laut Baseline nur aus LAN-Quellen. Soll: Zugriff nur für Familie und Server Admins; Administrator erstellt und verteilt alle Profile.

HTTPS über einen internen, zugriffsbeschränkten NPM-Proxy Host ist eine mögliche Erweiterung. Hostname, Zertifikatsverfahren und interne Namensauflösung sind noch festzulegen. Keine öffentliche Freigabe allein wegen HTTPS oder eines internen DNS-Namens annehmen. Bei Proxy-Betrieb den direkten Port 51821 auf die benötigten Quellen begrenzen und LLM-Admin-Zugriffe über den Gateway-INPUT-Pfad separat sperren. Hinter einem HTTP-Backend-Proxy kann INSECURE=true weiterhin nötig sein; externe TLS-Terminierung verschlüsselt den NPM→wg-easy-Pfad nicht automatisch.

MASQUERADE lässt LAN-Dienste VPN-Verkehr unter der Quelladresse 10.0.0.15 sehen. Eine NPM-Freigabe für diese Adresse unterscheidet Familie, Server Admin und LLM Admin nicht. Rollentrennung muss vor NAT am Gateway funktionieren. Eine pauschale LAN-Freigabe gewährt außerdem lokalen Heimnetz-Clients Zugriff; eine gruppengenaue Beschränkung lokaler Geräte erfordert zusätzliche Zuordnung oder Authentifizierung und ist noch offen.

6. Betrieb, Backup und Wiederherstellung

Artefakt Zweck
/etc/pve/lxc/105.conf LXC-Konfiguration auf Proxmox
/etc/containers/systemd/wg-easy.container Quadlet
/opt/wg-easy/environment allgemeine Container-Schalter, root, Modus 600
/opt/wg-easy/data/wg-easy.db v15-Konfiguration, Clients und Secrets
/opt/wg-easy/data/wg0.conf erzeugte Serverkonfiguration; nicht manuell bearbeiten
/etc/nftables.conf lokale Firewall
/etc/sysctl.d/99-ipforward.conf Forwarding

Vor Änderungen ein konsistentes Proxmox-Backup erstellen. Ein Snapshot allein ist kein unabhängiges Backup. Für ein Dateibackup wg-easy in einem Wartungsfenster stoppen, das gesamte Datenverzeichnis einschließlich etwaiger SQLite-WAL-Dateien sowie Quadlet, Environment, Firewall und sysctl sichern; anschließend Dienst wieder starten. Backups enthalten PrivateKeys und PresharedKeys und sind entsprechend zu schützen. Wiederherstellung einschließlich Rollenregeln, NAT, externem Handshake und gesperrten Zielen testen. Restore kann inzwischen widerrufene Peers wieder aktivieren; Widerrufsliste abgleichen.

7. Abnahme und Evidenz

Prüfung Ergebnis / Status
Laptop-Handshake von WAN bestanden am 12.09.2026
Laptop → 10.8.0.1 und Ping 10.0.0.2 bestanden am 12.09.2026
Laptop-Internet bleibt direkt IPv4-Test bestanden am 12.09.2026
Zugriff auf KI-Server offen; im letzten Test ausgeschaltet
Proxmox-GUI / SSH-Diensttests offen; Ping ersetzt keinen Diensttest
Familie → Heimnetz-PC offen, einschließlich Host-Firewall und Authentifizierung
Server Admin → Server erlaubt, DHCP-Client gesperrt offen, Per-Client Firewall noch aus
LLM Admin → KI-Server erlaubt, Proxmox/NPM/Gateway-GUI gesperrt offen, auch bei erweiterten lokalen AllowedIPs prüfen
WAN → TCP 22/51821 und IPv6-Exposure offen
Reboot / Firewall-Reload / Restore offen

Tests von einem fremden Netz ausführen, nicht nur aus dem Heimnetz. Für Isolation zuerst sicherstellen, dass das gesperrte Ziel von einem erlaubten Peer tatsächlich erreichbar ist. Handshake und VPN-Routen prüfen, dann bewusst clientseitiges Routing zu einem gesperrten Ziel ergänzen. Timeout allein ist ohne aktiven Zielservice und nachvollziehbare Firewallwirkung kein ausreichender Isolationsnachweis. Ergebnisse mit Datum, Quellnetz, Peer, Ziel, Port und Regelzählern dokumentieren; Secrets auslassen.

8. Offene Angaben und Abschlussbedingungen

Punkt erforderliche Klärung / Umsetzung
VPN-DynDNS Am 18.09.2026 löste vpn.ghostnet.selfhost.eu zur ausgehenden Gateway-IPv4 93.208.161.126 auf; vpn.ghostnet.dyndns.eu zeigte auf 83.169.40.234. Profile nutzen den selfhost-Namen. Automatische Aktualisierung nach WAN-IP-Wechsel und tatsächliche Fritzbox-DynDNS-Einstellung noch prüfen.
Vorhandene Peers Laptop-FullAdmin (10.8.0.2) und Android-LLMAdmin (10.8.0.3) sind historisch. Laptop der neuen Familie-/Server-Admin-Rolle ausdrücklich zuordnen; Android bleibt außerhalb der neuen Client-SOPs.
Gateway-Management INPUT-Regeln für zugeordnete Familie-/Server-Admin-Peers ergänzen; lokale Zugangsgruppen festlegen.
Per-Client Firewall aktivieren, erzeugte Regeln samt Hooks prüfen, negative Tests und Wiederanlauf abnehmen.
GUI-HTTPS Hostname, Zertifikat und Namensauflösung entscheiden und implementieren.