diff --git a/CLAUDE.md b/CLAUDE.md index e64724d..4784f50 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -75,6 +75,8 @@ GW je VLAN = `.1` (crs326-core L3) · Mgmt VLAN99: core `.99.1`, branch `.99.2`, - 🔴 **Messfalle: unter CAPsMAN führt der MANAGER die Tabellen.** `/interface/wifi/registration-table` und die `wireless`-Logs sind auf ap1/ap2 **leer**, obwohl das WLAN läuft. **Immer am Manager zählen.** - 🔴 **Die CAPs finden den Manager per Layer-2-Discovery** (`discovery-interfaces=vlan99`, `current-caps-man-address` ist eine **MAC**, keine IP). Deshalb müssen **MNDP (udp/5678)** und **CAPWAP (udp/5246-5247)** in der `input`-Kette des Core erlaubt bleiben — sonst kommt das WLAN nach dem nächsten AP-Reboot nicht zurück, während laufende Sessions unauffällig weiterlaufen (Fund 2026-08-18, TP5 Etappe 4). - **Local Forwarding ist keine Einstellung mehr:** im neuen `/interface/wifi` gibt es kein zentrales Forwarding, `datapath` existiert dort nicht. + - 🔴🔴 **`/interface wifi cap slaves-datapath` MUSS auf beiden APs gesetzt sein** (`dp-caps-slaves`, ein lokales datapath-Objekt mit `bridge=bridge` und **ohne** `vlan-id`). Es ist das Einzige, was die vom Manager erzeugten **Slave-VAPs** lokal in die Bridge haengt: der Manager schickt `datapath.bridge=bridge` mit, **der CAP uebernimmt davon nur die `vlan-id`**. Fehlt es, assoziieren Clients auf `-iot`/`-media`/`-untrusted`/`-guest` sauber und bekommen **nie DHCP**, waehrend `dirtyvader-main` weiterlaeuft — dessen Master-Radios `wifi1`/`wifi2` sind statische Bridge-Ports. Genau so lagen IOT+MEDIA am 2026-08-18 rund 14 Stunden (Ursache: CAPsMAN-Cutover 08-17, nicht die TP5-Haertung). **Abnahme fuer jeden WLAN-Umbau ist eine frische DHCP-Lease pro SSID — NICHT die Registration-Table**, die zeigte waehrend des Ausfalls 25 zufriedene IOT-Clients. + - 🔎 **Merkregel „connect ok, kein DHCP":** zuerst `torch` auf dem betroffenen VLAN am Core UND den TP5-Drop-Log lesen. Sind **beide leer**, wird nichts verworfen — es kommt nichts an, und die Firewall ist entlastet. Dann liegt es an L2 (Bridge-Mitgliedschaft/Tagging), nicht am Regelwerk. - mgmt-VLAN-Wechsel am Switch = Lockout-Risiko: VLAN muss existieren + Port muss es tragen, in einem Schritt. - 🔥 **Die Firewall ist seit 2026-08-18 deny-by-default — in BEIDEN Ketten.** Ein neuer Dienst über eine VLAN-Grenze braucht ab jetzt eine explizite Regel, sonst funktioniert er einfach nicht. Diagnosewerkzeug ist die **Log-Regel direkt vor dem Drop** (`TP5-WOULD-DROP` / `TP5-INPUT-WOULD-DROP`), die weiterläuft und in den Kollektor `10.40.20.18:514` schreibt (Dateien auf dem Docker-LXC unter `/opt/tp5-syslog/log/`). **Erst dort nachsehen, bevor irgendwo anders gesucht wird.** Ad-hoc-Zugriff aus MAIN in ein anderes VLAN (Scannen, IoT anlernen) läuft über die selbstverfallende Liste: `/ip firewall address-list add list=jit-admin address= timeout=1h`. - ⏰ **Zeitquelle ist der Core** (`/system ntp server`, seit 2026-08-18), ausgeliefert per **DHCP-Option 42** (`ntp-server=` in jedem der 7 Netze) und drift-überwacht (ComplianceRule `system-ntp`). Vorher lief **nirgends** eine Synchronisation: die anderen drei Geräte zeigten auf `10.40.99.1`, wo kein Server lief, und der Core selbst hatte gar keinen NTP-Client — ap2 war dadurch **17 Stunden** versetzt. 🔴 **Zwei Fallen dabei:** (a) ein NTP-Server mit `use-local-clock=no` und unsynchronisiertem Client liefert **Stratum 16**, das jeder Client verwirft — Server einschalten allein reicht nicht; (b) wird der Server eingeschaltet, *bevor* sein Client synchron ist, hält er diesen Zustand fest → **`enabled=no`/`=yes` nach der Synchronisation**. Merkregel: bei widersprüchlichen Zeitstempeln zwischen Geräten zuerst `/system ntp client get status` lesen, und zum Eingrenzen einen Client testweise auf eine öffentliche Quelle zeigen lassen. diff --git a/docs/teilprojekte.md b/docs/teilprojekte.md index 83cb998..c3d0d87 100644 --- a/docs/teilprojekte.md +++ b/docs/teilprojekte.md @@ -1358,7 +1358,33 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung". liefert das Entscheidungskriterium). ⚠️ **Berührt TP5:** der Mesh-Verkehr braucht bei deny-by-default eine explizite `forward`-Zeile — s. TP5 Etappe 2. -### TP28 — WLAN über CAPsMAN auf `crs326-core` ▸ ✅ **KOMPLETT (2026-08-18): Cutover + GC-Modell nachgezogen** +### TP28 — WLAN über CAPsMAN auf `crs326-core` ▸ ✅ **KOMPLETT (2026-08-18)** — mit Nachtrag: **`slaves-datapath` fehlte, IOT+MEDIA lagen ~14 h** + +- 🔴🔴 **POST-MORTEM 2026-08-18 (gemeldet von Christoph: „die -iot-geräte sind offline … connect möglich, aber kein dhcp"):** + Seit dem Cutover hingen **alle Slave-VAPs in gar keiner Bridge**. `/interface wifi cap slaves-datapath` + war auf beiden APs leer — und genau dieses Feld ist das Einzige, was die vom Manager erzeugten + Slave-VAPs lokal in die Bridge haengt. Der Manager schickt `datapath.bridge=bridge` zwar mit, + **der CAP uebernimmt davon nur die `vlan-id`.** Betroffen: `dirtyvader-iot`, `-media`, `-untrusted`, + `-guest`. Nicht betroffen: `dirtyvader-main` — dessen Master-Radios `wifi1`/`wifi2` sind + **statische** Bridge-Ports und liefen deshalb weiter. Genau das machte den Ausfall unsichtbar. + - **Fix (live 2026-08-18 auf ap1 + ap2, seither Soll im Template):** + `/interface wifi datapath add name=dp-caps-slaves bridge=bridge` + + `/interface wifi cap set slaves-datapath=dp-caps-slaves`. Das Objekt traegt **bewusst keine + `vlan-id`** — die liefert der Manager pro VAP. Danach erscheinen die VAPs als **dynamische + Bridge-Ports mit `pvid`=30/40/50/90**, und DHCP laeuft sofort wieder. + - 🔴 **Die Diagnose-Lehre: „Client assoziiert" beweist gar nichts.** Am Manager standen 25 IOT- + Registrations — das WLAN sah perfekt aus. Erst zwei Reads trennten die Faelle: + `torch` auf `vlan30` am Core (**leer**) und der TP5-Drop-Log (**kein einziger DHCP-Eintrag**). + Beides leer heisst: es wird nichts verworfen, es **kommt** nichts. Damit war die Firewall + — der naheliegende Verdaechtige nach der Haertung derselben Nacht — in zwei Minuten entlastet. + - ⚠️ **Die Abnahme „✅ Ohne jeden Aussetzer" weiter unten war falsch.** Sie zaehlte Registrations + (30 Clients, beide CAPs `Ok`, 7 VAPs je AP) — also genau die Metrik, die hier luegt. Keiner + dieser Werte beruehrt die Bridge. Ein Abnahmekriterium fuer WLAN-Umbauten ist ab jetzt eine + **frische DHCP-Lease pro SSID**, nicht die Registration-Table. + - **`routeros/tp28-ap-wifi-reste-abraeumen.rsc` hat den Ausfall nicht ausgeloest, aber zementiert:** + mit den geloeschten datapath-Objekten gab es lokal nichts mehr, worauf `slaves-datapath` haette + zeigen koennen. Der Ein-Zeilen-Fix war damit weg. Nachtrag steht im Skript. + - ✅ **Der offene GC-Rest ist erledigt (2026-08-18).** Die fuenf `wifi-*`-ComplianceFeatures haengen jetzt am **Core**, der AP-Zweig des Templates ist auf eine einzige Zeile eingedampft (`/interface wifi cap set discovery-interfaces=vlanXX enabled=yes`). diff --git a/nautobot/mikrotik_routeros.j2 b/nautobot/mikrotik_routeros.j2 index d1109f4..60bd2fa 100644 --- a/nautobot/mikrotik_routeros.j2 +++ b/nautobot/mikrotik_routeros.j2 @@ -326,7 +326,7 @@ # Referenz: routeros/state-backups/ap1-gc-backup-scrubbed-20260813.cfg # ===================================================================================== -# [1] WLAN — ein CAP haelt KEINE eigene WLAN-Config. +# [1] WLAN — ein CAP haelt keine eigenen SSIDs, aber sehr wohl den lokalen Anschluss. # Bis 2026-08-18 rendert dieser Zweig Kanaele, Datapaths, Security, Configurations # und Steering. Das war der Standalone-Stand von TP3; seit dem CAPsMAN-Cutover # (TP28, 2026-08-17) kommen all diese Objekte vom Manager `crs326-core` und werden @@ -336,11 +336,29 @@ # den defconf-Firewallregeln in TP26). Sie sind am 2026-08-18 abgeraeumt worden. # # Die fuenf wifi-*-ComplianceFeatures greifen jetzt am Core, s. dort [6b]. -# Hier bleibt genau eine Zeile: der CAP muss wissen, wo er suchen soll. +# Hier bleiben zwei Zeilen: wo der CAP seinen Manager suchen soll, und WOHIN er +# die vom Manager erzeugten Slave-VAPs haengt. # ⚠️ `discovery-interfaces` ist Layer-2-Discovery — der Manager wird ueber seine # MAC gefunden, nicht ueber eine IP. Deshalb muessen MNDP (udp/5678) und CAPWAP # (udp/5246-5247) in der input-Kette des Core offen bleiben (TP5 Etappe 4). -/interface wifi cap set discovery-interfaces=vlan{{ ap.mgmt.vlan }} enabled=yes +# +# 🔴 `slaves-datapath` IST NICHT OPTIONAL — Ausfall 2026-08-18, rund 14 h IOT+MEDIA: +# Der Manager schickt `datapath.bridge=bridge` zwar mit, der CAP uebernimmt davon +# aber NUR die vlan-id — die Bridge-Mitgliedschaft ist und bleibt lokal. Die +# Master-Radios wifi1/wifi2 sind statische Bridge-Ports (s. [4b]) und liefen +# deshalb weiter; die dynamischen Slave-VAPs (iot/media/untrusted/guest) haengen +# dagegen in GAR KEINER Bridge, solange `slaves-datapath` auf kein lokales +# datapath-Objekt zeigt. Beim Cutover (2026-08-17) wurde das Feld nie gesetzt — +# der Ausfall beginnt dort, nicht bei der TP5-Haertung und nicht beim Abraeumen +# der Standalone-Reste am 2026-08-18 (das hat ihn nur unreparierbar gemacht). +# Symptom: Client assoziiert sauber (am Manager als Registration sichtbar!), +# bekommt aber nie DHCP; am Core kommt auf dem VLAN kein einziges Frame an — +# `torch` leer UND Drop-Log leer, es wird also nichts verworfen, es kommt nichts. +# Das Objekt traegt bewusst KEINE vlan-id: die liefert der Manager pro VAP. +/interface wifi cap set discovery-interfaces=vlan{{ ap.mgmt.vlan }} enabled=yes slaves-datapath=dp-caps-slaves +# ⚠️ Export-Reihenfolge != Deploy-Reihenfolge: RouterOS exportiert `cap` VOR `datapath`, +# beim Push muss das datapath-Objekt aber ZUERST existieren. +/interface wifi datapath add bridge={{ ap.bridge }} comment="TP28-fix: bridge fuer CAPsMAN-Slave-VAPs" name=dp-caps-slaves # [4b] BRIDGE-PORTS — ether2 fehlt bewusst: seit der Uplink-Umstellung auf ether1 (PoE) # ist er KEIN Bridge-Port mehr. ether1 traegt kein comment=defconf (beim Rebuild @@ -353,8 +371,11 @@ {% endfor %} /interface bridge port add bridge={{ ap.bridge }} interface={{ uplink }} -# [5] BRIDGE-VLAN — Nur Master-Radios sind Bridge-Ports (Slave-VAPs forwarden darueber), -# deshalb muessen wifi1/wifi2 tagged-Member je Client-VLAN sein. Die frueheren +# [5] BRIDGE-VLAN — wifi1/wifi2 sind tagged-Member je Client-VLAN. Die Begruendung von +# 2026-08-17 ("Slave-VAPs forwarden ueber den Master") war falsch: mit gesetztem +# `slaves-datapath` haengt jeder Slave-VAP als eigener DYNAMISCHER Bridge-Port mit +# pvid = seiner Manager-vlan-id in der Bridge. Die tagged-Zeilen bleiben trotzdem +# stehen — sie kosten nichts und tragen den Uplink-Trunk. Die frueheren # "Ausnahmen" fallen hier aus den Daten heraus: IOT hat bands=["2g"] -> nur wifi2. /interface bridge vlan add bridge={{ ap.bridge }} untagged={{ ap.bridge }},{{ uplink }} vlan-ids={{ ap.native_vlan }} {% for z in ap.zones %} diff --git a/routeros/tp28-ap-wifi-reste-abraeumen.rsc b/routeros/tp28-ap-wifi-reste-abraeumen.rsc index 296ee63..7450f7d 100644 --- a/routeros/tp28-ap-wifi-reste-abraeumen.rsc +++ b/routeros/tp28-ap-wifi-reste-abraeumen.rsc @@ -32,3 +32,32 @@ :do { /interface wifi channel remove [find] } on-error={ :log info "tp28c: channel warf" } :log info ("tp28c: ENDE cfg=" . [:tostr [:len [/interface wifi configuration find]]] . " sec=" . [:tostr [:len [/interface wifi security find]]] . " dp=" . [:tostr [:len [/interface wifi datapath find]]] . " ch=" . [:tostr [:len [/interface wifi channel find]]] . " st=" . [:tostr [:len [/interface wifi steering find]]] . " cap-enabled=" . [:tostr [/interface wifi cap get enabled]]) + +# --------------------------------------------------------------------------- +# 🔴 NACHTRAG 2026-08-18, nach rund 14 h Ausfall von IOT + MEDIA: +# Die Annahme oben ("Client-Verbindungen bleiben unberuehrt") stimmte — das +# Skript hat den Ausfall NICHT ausgeloest. Die Bruchstelle liegt frueher, im +# CAPsMAN-Cutover selbst (2026-08-17): dabei wurde `/interface wifi cap +# slaves-datapath` nie gesetzt. Genau dieses Feld ist das EINZIGE, was die vom +# Manager erzeugten Slave-VAPs lokal in die Bridge haengt; der Manager schickt +# `datapath.bridge=bridge` zwar mit, der CAP uebernimmt davon aber nur die +# vlan-id. Seit dem Cutover assoziierten IOT-/MEDIA-Clients also sauber, ihre +# Frames gingen nirgendwo hin — am Core kam auf vlan30/vlan40 kein einziges +# Paket an. Die Master-Radios (wifi1/wifi2 = dirtyvader-main) sind statische +# Bridge-Ports und liefen weiter, deshalb sah das WLAN von aussen "halb ok" aus. +# Belege: `slaves-datapath` kommt in keiner Provisionierungs-Referenz vor +# (routeros/.secrets/ap*-prov-base.rsc), und die letzten IOT-/MEDIA-Leases +# stammen vom Abend des 2026-08-17. +# +# Dieses Skript hat den Schaden aber ZEMENTIERT: mit den geloeschten datapath- +# Objekten gab es lokal nichts mehr, worauf `slaves-datapath` haette zeigen +# koennen. Der naheliegende Ein-Zeilen-Fix war damit nicht mehr moeglich. +# +# Reparatur (ap1 und ap2, live 2026-08-18, seither im Template als Soll): +# /interface wifi datapath add name=dp-caps-slaves bridge=bridge +# /interface wifi cap set slaves-datapath=dp-caps-slaves +# Das Objekt traegt bewusst KEINE vlan-id — die kommt pro VAP vom Manager. +# +# LEHRE: `remove [find]` ohne Ruecksicht auf Referenzen aus /interface wifi cap. +# Vor dem Abraeumen pruefen: :put [/interface wifi cap get slaves-datapath] +# ---------------------------------------------------------------------------