Files
management/docs/aar/2026-08-01-labnet02-cfgmon.md
T
Thore CimbalandClaude Fable 5 92b448fe30 feat: slice 3 - wiki, sources and AARs in their neckbeard homes
Gate 4, slice 3: verfahren/, hosts/, vision/ and shared/ moved via git
mv - six AARs to docs/aar/ (four harvested by the 2026-08-09 retro,
two open), procedures and host knowledge to docs/wiki/ (admin,
deployment, architecture, new area vision), the retro protocol and the
commit mapping table to docs/sources/ (protokolle/, migration/). New:
the wiki index linking every page, and the mirror-topology page
carrying the why-two-places reasoning verbatim from the old CLAUDE.md
(F-013 preserved). All moved-path references retargeted; the link
checker drove the sweep to zero.

pruefe_prosa.py added (pattern C+D): SHA citations resolve via repo,
mapping table, optional component clones or a curated exemption list
(documented dead Gitea-force-push commits, a vendor-repo tag, an
Authentik uid that is hex but no git SHA, the external neckbeard
reference); wiki task prose without an issue reference errors, with a
visible pragma for deliberate checklists; the dead-tracker denylist
now covers every mirrored repo's retired Gitea tracker (F-005) - two
links re-verified against live GitLab titles and retargeted, five
defused into honest historical citations.

Verified: validate 0/0, gen_status --check current, drift 0. Demo on
the pre-migration state fires 6 findings (3 orphaned SHAs, 3 task
blocks); on the current tree exactly the 3 F-004 task blocks remain -
they turn green in slice 4 when the issues exist, which is why
pruefe_prosa joins CI only then.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 12:00:00 +00:00

193 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 13 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 17 (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 17, Schlüsselrotation
und das Repo-Zuhause der Config.