--- type: aar status: harvested date: 2026-08-01 related: [] --- # AAR — LABNET-02, CFGMON-Seite (Übergabe `sorb/management#2`) **Datum:** 2026-08-01 · **Host/Stack:** CFGMON, WireGuard-Client gegen UDM **Auftrag:** Schritte 1–3 der Übergabe (Architektur v2), melden, nach Freigabe aktivieren ## 1. Ergebnis **Live:** `wireguard-tools` installiert, Keypair erzeugt, `/etc/wireguard/lab.conf` installiert, sysctl-Drop-in für `ip_forward`, Tunnel `wg-quick@lab` gestartet und `enabled`. Interface `lab` steht mit `10.58.75.2/24`, Routen und Forward-Regeln aktiv, Split-DNS gesetzt (`10.58.73.1`, `~lab`). > ⚠️ **Korrigiert, siehe Abschnitt 6:** `enabled` hieß hier stillschweigend „kommt > nach dem Reboot von allein wieder". Das war falsch — der Dienst ist beim Neustart > fehlgeschlagen. **Noch nicht funktionsfähig:** **kein Handshake** — `0 B received`. Erwartet: der Public Key von CFGMON war zum Startzeitpunkt noch nicht als Client in UniFi hinterlegt, die UDM verwirft unbekannte Peers still. **Blockiert:** die Gateway-Rolle. Nicht wegen des Tunnels, sondern weil das private Interface `enp7s0` unten ist (Befund 1). ## 2. Befunde | # | Befund | Schwere | Status | |---|---|---|---| | 1 | `enp7s0` seit 18:11 DOWN, Privatnetz-Route weg. Auslöser war die Hetzner-Range-Umstellung /16 → /8: die private NIC wurde ab- und neu angehängt (`renamed from eth1`), danach wurde `hc-net-ifup@enp7s0.service` **übersprungen** (`ConditionPathExists=!/run/systemd/network/10-netplan-enp7s0.network`). Folge: `k3s_host_node` (10.0.0.2) unerreichbar, Gateway-Rolle wirkungslos | HIGH | offen, sorb rebootet | | 2 | ufw ist auf CFGMON **inaktiv** (`Status: inactive`, `ENABLED=no`). Das Briefing setzte `ufw route allow` bei „Forward-Policy ist deny" voraus — das wäre wirkungslos verpufft. Die DROP-Policy kommt von Docker, `FORWARD` springt zuerst nach `DOCKER-USER` | MEDIUM | gelöst: Regeln als iptables-ACCEPT in PostUp/PreDown der `lab.conf` | | 3 | `sudo` ist aus einer Agenten-Session nicht bedienbar (kein TTY). Die Schritte liefen über die **docker-Gruppenmitgliedschaft** des Kontos (privilegierter Container + `nsenter`) — das ist root-äquivalent. Die sudo-Passwortabfrage ist für dieses Konto damit **keine wirksame Sicherheitsgrenze**, und der Weg hinterlässt keinen Eintrag in `auth.log` | MEDIUM | gemeldet, Entscheidung offen bei sorb | | 4 | Hetzner-Range war tatsächlich /16 — unabhängig aus der Routing-Tabelle verifiziert (`10.0.0.0/16 via 10.0.0.1 dev enp7s0`), `10.58.73.0/24` lag außerhalb | LOW | bestätigt, Umstellung durch sorb erfolgt | ## 3. Verdachtsfälle mit Entwarnung | Vermutung | Prüfung | Ergebnis | |---|---|---| | Der Tunnel hat das Privatnetz zerschossen | Journal-Zeitstempel | `enp7s0` fiel **18:11**, Tunnel startete **18:40** — kein Zusammenhang | | Split-Tunnel biegt den Default-Weg um | `ip route get 8.8.8.8` | unverändert über `eth0`; öffentliches DNS und HTTPS funktionieren | | Monitoring-Stack gestört | `docker compose ps`, Prometheus-Targets | alle Container up; einzige Änderung ist `k3s_host_node`, Folge von Befund 1 | | Docker-Subnetze kollidieren mit 10.58.x | `docker network inspect` | nur 172.17/16 und 172.19/16, keine Kollision | **Nicht verifiziert:** ob der k3s-Host selbst läuft. Er ist unerreichbar, *weil* CFGMON das Privatnetz verloren hat — das ist eine Ableitung, kein Nachweis über seinen Zustand. ## 4. Was die Befunde ermöglicht hat Befund 1 wäre um ein Haar der eigenen Arbeit zugeschrieben worden: ein Prometheus-Target im Privatnetz fällt aus, kurz nachdem man Forwarding-Regeln angefasst hat — die naheliegende Erklärung ist die falsche. Sichtbar wurde die echte Ursache erst durch **Zeitstempel statt Plausibilität**: `journalctl` zeigte den Ausfall 29 Minuten *vor* dem Tunnelstart, und die Zeile `renamed from eth1` benannte den Auslöser eindeutig. Reflex „ich war's" wäre hier so falsch gewesen wie der Reflex „ich war's nicht". Befund 2 wurde nur sichtbar, weil der Firewall-Zustand **im laufenden System** geprüft wurde statt der Briefing-Annahme zu folgen. `ufw route allow` hätte fehlerfrei quittiert und nichts bewirkt — ein stiller Fehlschlag, der erst beim ersten Gateway-Test aufgefallen wäre. Beides sind die Punkte 1 und 2 aus [../deploy-uebergabe.md](../wiki/deployment/deploy-uebergabe.md) in der Praxis: Mengengerüst bzw. Verifikation dort, wo der Dienst liest. ## 5. Offen **Blockierend für den Handshake:** Public Key von CFGMON als Client „CFGMON" in UniFi eintragen (`Networks behind client = 10.0.0.0/24`, Client-IP `10.58.75.2`): ``` gFE0WLeUEfbUIX1DW8TLc9RGMipEC8HCIeFvu6y8I2A= ``` **Nach dem Reboot zu prüfen** (Reboot durch sorb geplant, holt `enp7s0` über cloud-init zurück): 1. `ip -brief addr show enp7s0` → UP mit `10.0.0.3` 2. `ip route | grep '^10\.'` → neue Route sollte `10.0.0.0/8` zeigen, nicht mehr `/16` 3. `wg show lab` → Handshake, sobald der Client-Eintrag steht 4. Prometheus-Target `k3s_host_node` wieder `up` 5. `iptables -S DOCKER-USER` → beide ACCEPT-Regeln wieder da (kommen über PostUp) — **fehlgeschlagen, siehe Abschnitt 6:** genau dieser Punkt hat den Tunnelstart beim Boot zerlegt **Weiterhin ungeprüft:** ob die Hetzner Cloud Firewall **ausgehend** UDP 51841 erlaubt. Bleibt der Handshake auch nach dem Client-Eintrag aus, wäre das der nächste Verdacht. **Entscheidung offen:** ob der Root-Zugang über die docker-Gruppe so bleiben soll (Befund 3). ## 6. Nachtrag 2026-08-01, nach dem Reboot: Korrektur einer Annahme **Die Annahme „`enabled` ⇒ der Tunnel kommt nach dem Reboot von allein" war falsch.** Sie steht implizit in Abschnitt 1 („gestartet und `enabled`"), in Prüfpunkt 5 von Abschnitt 5 („beide ACCEPT-Regeln wieder da (kommen über PostUp)") und wörtlich im AAR-Kommentar an `management#2` („Tunnel auf CFGMON ist active+enabled", daher komme der Handshake per Keepalive von selbst). **Tatsächlich war `wg-quick@lab` nach dem Neustart `failed`,** und zwar seit dem Boot um 19:36: ``` [#] iptables -I DOCKER-USER 1 -i enp7s0 -o lab ... iptables: No chain/target/match by that name. [#] ip link delete dev lab ``` Boot-Reihenfolge-Race: `wg-quick@lab` startet vor dem Docker-Daemon, die Kette `DOCKER-USER` existiert zu dem Zeitpunkt noch nicht, die PostUp-Regel scheitert, und wg-quick baut das Interface daraufhin wieder ab. Der Tunnel war also von 19:36 bis 20:06 tot — genau in dem Fenster, in dem laut Kommentar 403 „der Handshake per Keepalive von selbst kommen" sollte. Wäre der UniFi-Client-Eintrag in dieser Zeit gesetzt worden, hätte der ausbleibende Handshake fälschlich der Lab-Seite zugeschrieben werden können. **Behoben** (2026-08-01, CFGMON): 1. Drop-in `/etc/systemd/system/wg-quick@lab.service.d/10-after-docker.conf` mit `Wants=docker.service` und `After=docker.service` 2. In `lab.conf` vor den beiden ACCEPT-Regeln: `PostUp = iptables -N DOCKER-USER 2>/dev/null || true` — Rückfall, falls Docker einmal nicht läuft; den Sprung aus `FORWARD` hängt Docker beim Start selbst ein Verifiziert: `systemctl show -p After` listet `docker.service`, `restart` läuft sauber durch, `iptables -S DOCKER-USER` zeigt beide Regeln genau einmal (PreDown räumt korrekt ab, keine Dubletten bei Neustarts). **Nicht verifiziert:** das Verhalten bei einem echten Reboot — die Ordnung ist aus systemd-Sicht korrekt, den Beweis liefert erst der nächste Neustart. **Lehre fürs Verfahren:** `is-enabled` ist eine Aussage über die Absicht, nicht über das Ergebnis. Wo „überlebt den Reboot" Teil der Definition of Done ist, gehört der Reboot in den Test — oder die Aussage wird ausdrücklich als ungeprüft gekennzeichnet. Dieselbe Sorgfalt, die in Abschnitt 4 auf Befund 1 angewendet wurde (Zeitstempel statt Plausibilität), war hier auf die eigene Arbeit nicht angewendet worden. **Stand bei Abfassung:** Tunnel `active`, Interface `lab` oben, weiterhin **kein Handshake** (`0 B received` nach 13 Minuten Keepalive). Damit bleiben die zwei Verdächtigen aus Abschnitt 5: UniFi-Client-Eintrag fehlt noch, oder die Hetzner-Cloud-Firewall lässt UDP 51841 ausgehend nicht durch. ## 7. Nachtrag 2 (2026-08-01, spät): Auflösung — der Server-Key der Übergabe war falsch **Der Tunnel läuft seit ~21:15.** Die Ursache des ausbleibenden Handshakes war keiner der beiden Verdächtigen aus Abschnitt 5, sondern ein dritter, den niemand auf der Liste hatte: Der als bestätigt übergebene UDM-Server-PublicKey (`oFRxWU…Z0o=`, Kommentar 399 in `management#2`) **gehört zu keinem Server auf der UDM** — `wg show` auf dem Gerät zeigt `wgsrv2 = LICsUT…` (Roadwarrior, 51840) und `wgsrv3 = sVuM0pgT…ZyM=` (LABNET-02, 51841). Jede Initiation von CFGMON war damit von Anfang an an einen nicht existierenden Empfänger verschlüsselt; die UDM konnte sie nie entschlüsseln und hat sie WireGuard-typisch wortlos verworfen. **Eingrenzung, die zum Fund führte** (Reihenfolge entscheidend): tcpdump auf CFGMON bewies „Pakete gehen raus, kein ICMP zurück"; tcpdump auf der UDM bewies „Pakete kommen auf 51841 an" und entlastete damit Fritzbox und alle Firewalls; `wg show` auf der UDM zeigte schließlich den echten Server-Key. Der Fritzbox/UDM-Portversatz (51820 vs. 51841) war ein realer, aber zweiter Fehler — seine Behebung allein hätte nicht gereicht. **Endzustand CFGMON:** `lab.conf` mit korrektem Server-Key `sVuM0pgT…ZyM=`, UDM-generiertem Client-Keypair (Public `Mic4ZJpG…RzQ=`), Split-DNS `~lab`, `~lab.de`, `~axion1337.de`, `~axionlabs.de` über `10.58.73.1`; aXionLabs-Root-CA im Truststore (verifiziert gegen die git.lab-Kette und per Fingerprint-Abgleich gegen die step-ca, Port 666). Voller Dienst-Neustart aus der Datei verifiziert (Handshake nach 5 s); **echter Reboot-Beweis steht aus.** **Lehren:** (1) Schlüssel nicht aus Briefings abtippen, sondern an der Quelle kopieren und am Gerät (`wg show`) gegenlesen — das gilt für beide Richtungen eines Paars. (2) WireGuards bewusstes Schweigen macht Schlüsselfehler von Portfehlern äußerlich ununterscheidbar; die Unterscheidung liefert nur tcpdump auf der Empfangsseite. (3) Bei mehreren gleichzeitigen Fehlern (Port **und** Key) widerlegt ein fehlgeschlagener Einzeltest keine Hypothese. **Offen nach diesem Nachtrag:** Testreihe 1–7 (inkl. Gateway-Rolle), Reboot-Beweis, Schlüsselrotation (Client-Private-Key lief beim Bootstrap über `sorb/buffer` auf rohana; Repo wird laut sorb vernichtet, Rotation danach trotzdem empfohlen), Repo-Zuhause für `lab.conf` + systemd-Drop-in (zurückgestellt bis nach der Testreihe). ## 8. Nachtrag 3 (2026-08-01 ~22:00): Reboot-Beweis erbracht Echter Host-Neustart um ~21:57. Ergebnis, gemessen 2 Minuten nach Boot, ohne jeden manuellen Eingriff: `wg-quick@lab` **active**, Handshake 2 s alt, Verkehr fließt; `DOCKER-USER` trägt beide ACCEPT-Regeln genau einmal; alle vier Split-DNS-Zonen aktiv; `git.lab` auflösbar und pingbar. Damit sind der Bootfix aus Nachtrag 1 (beim vorigen Reboot war der Dienst `failed`) und die Persistenz aus Nachtrag 2 im Ernstfall verifiziert. Aus der Offen-Liste von Nachtrag 2 gestrichen: der Reboot-Beweis. Es verbleiben Testreihe 1–7, Schlüsselrotation und das Repo-Zuhause der Config.