Compare commits
4 Commits
5bcd0b6989
...
75bd43d1f7
| Author | SHA1 | Date | |
|---|---|---|---|
| 75bd43d1f7 | |||
| 315f1e79e7 | |||
| 6e2a7cfb47 | |||
| 5ad71b37c0 |
@@ -61,7 +61,7 @@ teuerste Eigenschaft der Datei zerstört, um ihr billigstes Problem zu lösen. B
|
|||||||
| [TP25](#tp25) | WLAN-Stabilisierung | ✅ FERTIG (2026-09-15) — Platzierung final (ap1 Sideboard · ap2 UG · ap3 OG), Fund E geschlossen |
|
| [TP25](#tp25) | WLAN-Stabilisierung | ✅ FERTIG (2026-09-15) — Platzierung final (ap1 Sideboard · ap2 UG · ap3 OG), Fund E geschlossen |
|
||||||
| [TP26](#tp26) | `/ip firewall filter` unter Drift-Kontrolle | ✅ DURCH (2026-08-17) |
|
| [TP26](#tp26) | `/ip firewall filter` unter Drift-Kontrolle | ✅ DURCH (2026-08-17) |
|
||||||
| [TP27](#tp27) | RouterBOOT-Firmware auf 7.24 nachziehen | ✅ DURCH (2026-08-17/18) |
|
| [TP27](#tp27) | RouterBOOT-Firmware auf 7.24 nachziehen | ✅ DURCH (2026-08-17/18) |
|
||||||
| [TP28](#tp28) | WLAN über CAPsMAN auf `crs326-core` | ↩️ **wieder geöffnet 2026-08-30** (ap3) — Volltext in [teilprojekte.md](teilprojekte.md#tp28) |
|
| [TP28](#tp28) | WLAN über CAPsMAN auf `crs326-core` | ✅ FERTIG (2026-10-04) — ap1 Sideboard · ap2 UG · ap3 OG, Kanalplan committed, Compliance 29/29 |
|
||||||
| [TP-R](#tp-r) | Router-Capabilities-Sweep | FERTIG (docs/research/routeros-capabilities.md) |
|
| [TP-R](#tp-r) | Router-Capabilities-Sweep | FERTIG (docs/research/routeros-capabilities.md) |
|
||||||
| [TP39](#tp39) | LXC-Hygiene pve: Resolver-Altlasten, `networking.service`, DB-Reverse-Lookup | ✅ ABGESCHLOSSEN (2026-09-01) — pve+NAS-Sweep grün |
|
| [TP39](#tp39) | LXC-Hygiene pve: Resolver-Altlasten, `networking.service`, DB-Reverse-Lookup | ✅ ABGESCHLOSSEN (2026-09-01) — pve+NAS-Sweep grün |
|
||||||
| [TP34](#tp34) | Caddyfile via Nautobot/GC (generische Reverse-Proxy-Schnittstelle) | ❌ VERWORFEN (2026-09-08) — Caddyfile bleibt manuell · **Fortsetzung: TP34.2 (2026-09-22)** |
|
| [TP34](#tp34) | Caddyfile via Nautobot/GC (generische Reverse-Proxy-Schnittstelle) | ❌ VERWORFEN (2026-09-08) — Caddyfile bleibt manuell · **Fortsetzung: TP34.2 (2026-09-22)** |
|
||||||
@@ -1277,11 +1277,222 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
|||||||
|
|
||||||
### TP28 · Gitea #18 — WLAN über CAPsMAN auf `crs326-core`
|
### TP28 · Gitea #18 — WLAN über CAPsMAN auf `crs326-core`
|
||||||
|
|
||||||
> Der Volltext steht seit dem 2026-08-30 wieder in
|
> ✅ **Abgeschlossen 2026-10-04.** ap1 Sideboard · ap2 Technik UG · ap3 Technik OG (Platzierung
|
||||||
> [`teilprojekte.md` → TP28](teilprojekte.md#tp28), weil mit **ap3** (cAP ax) ein dritter
|
> final). Kanalplan committed, `wifi-cap`-Rest auf dem Core bereinigt, Compliance 29/29. Der
|
||||||
> Access-Point dazukommt. **Ein archiviertes TP ist ein geschlossenes Ticket — es darf wieder
|
> ap3-Nachtrag unten ist damit erledigt; die zwei 🔜-Reste sind Cross-TP (TP25 ✅ 09-15, TP30).
|
||||||
> geöffnet werden** (Christoph-Direktive 2026-08-30); der Abschnitt wandert zurück, nicht nur
|
|
||||||
> ein Nachtrag. Hier bleibt dieser Zeiger stehen, damit alte Links nicht ins Leere gehen.
|
|
||||||
|
> **Der CAPsMAN-Kern ist und bleibt ✅ KOMPLETT (2026-08-18)** — der Abschnitt darunter ist
|
||||||
|
> unverändert der Archivtext inkl. Post-Mortem. Wieder geöffnet wurde das TP am 2026-08-30,
|
||||||
|
> weil mit **ap3** ein dritter CAP dazukommt; das ist dieselbe Baustelle, kein neues TP
|
||||||
|
> (Christoph-Direktive: *ein archiviertes TP ist ein geschlossenes Ticket und darf wieder
|
||||||
|
> geöffnet werden*). **Der offene Teil steht am Ende des Abschnitts unter „Nachtrag ap3".**
|
||||||
|
|
||||||
|
- 🔴🔴 **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.
|
||||||
|
- ✅ **Reboot-Abnahme an ap2 (2026-08-18), drei Fragen auf einmal beantwortet:** `slaves-datapath`
|
||||||
|
ueberlebt den Neustart (statisches Objekt, steht im `/export`), der CAP **findet seinen Manager
|
||||||
|
durch die gehaertete input-Kette wieder** (`current-caps-man-identity=crs326-core` — MNDP/CAPWAP
|
||||||
|
sind also korrekt offen, das war seit TP5 Etappe 4 nie durchgespielt), und die sieben Slave-VAPs
|
||||||
|
kommen von selbst als dynamische Bridge-Ports mit pvid 30/40/50/90 zurueck. AP nach **40 s**
|
||||||
|
wieder erreichbar. Abnahme nach neuer Regel = **frische Lease**: IOT-Client `10.40.30.8`
|
||||||
|
`last-seen=30s`, MAIN-Client `10.40.10.180` `last-seen=1m54s`.
|
||||||
|
- ⚠️ **Reboot per MikroMCP geht auf 7.24 nicht:** das `reboot`-Tool sendet `delay`, die REST-API
|
||||||
|
antwortet `unknown parameter delay`; `run_command` ist fuer `/system reboot*` per Deny-Policy
|
||||||
|
gesperrt. Weg bis das gefixt ist: `sshpass` + `ssh admin@<ap> "/system reboot"`.
|
||||||
|
- ✅ **Soll nachgezogen, Compliance wieder sauber: 92/92, 0 Drifts** (2026-08-18). Weg: Template in
|
||||||
|
`nautobot/mikrotik_routeros.j2` → `routeros/push-gc-template.py` (Secret-Guard) → GitRepository-Sync
|
||||||
|
→ Backup/Intended/Compliance. Ohne den Push meldet der Refresh die zwei neuen Zeilen als `extra`
|
||||||
|
auf beiden APs — das Jinja lebt im **separaten** Gitea-Repo `bf-golden-config`, ein Commit hier
|
||||||
|
allein erreicht Nautobot nicht.
|
||||||
|
- ⚠️ **Beim ersten Sync-Versuch: `redis.exceptions.ConnectionError: broken pipe`** auf dem
|
||||||
|
Nautobot-Stack. Ein simpler Retry ging durch; NAS-Load war unauffaellig (0,9). Der Job meldet das
|
||||||
|
als `FAILURE` — nicht mit einem inhaltlichen Fehler verwechseln.
|
||||||
|
|
||||||
|
- ✅ **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`).
|
||||||
|
- 🔴 **Dabei aufgefallen: die APs trugen noch die KOMPLETTE Standalone-WLAN-Config** aus TP3 —
|
||||||
|
je 2 channel, 6 datapath, 6 security, 7 configuration, 1 steering. Der Cutover vom 08-17 hatte
|
||||||
|
sie nie abgeraeumt. Wirkungslos (der Manager liefert alles dynamisch), aber sie im Template als
|
||||||
|
Soll zu rendern hiesse, totes Zeug zur Absicht zu erklaeren — dasselbe Argument wie bei den
|
||||||
|
defconf-Firewallregeln in TP26. Abgeraeumt mit `routeros/tp28-ap-wifi-reste-abraeumen.rsc`.
|
||||||
|
- ✅ **Ohne jeden Aussetzer:** vorher/nachher 30 Clients, beide CAPs `Ok`, 7 dynamische VAPs je AP.
|
||||||
|
Die Sorge vor einem Radio-Re-Apply (TP25/TP3.3: „wirft jeden Client kurz raus") hat sich nicht
|
||||||
|
bestaetigt — die dynamischen VAPs tragen ihre Werte **inline** (`datapath.vlan-id=…`) und
|
||||||
|
referenzieren kein lokales Objekt; nur `wifi1`/`wifi2` hielten noch einen toten
|
||||||
|
`configuration=`-Verweis, der beim Loeschen folgenlos blieb.
|
||||||
|
- 🔴 **`[find !dynamic]` ist auf diesen Sektionen ein SYNTAXFEHLER**, nicht bloss wirkungslos:
|
||||||
|
`/interface wifi configuration` & Co. haben gar keine `dynamic`-Eigenschaft (die gibt es nur auf
|
||||||
|
`/interface wifi` selbst). Der erste Anlauf lief komplett in die `on-error`-Zweige, aenderte
|
||||||
|
**nichts** und meldete trotzdem „Plan Completed". Wieder: nur die Gegenpruefung am Geraet zaehlt.
|
||||||
|
- ✅ **Drei neue ComplianceRules schliessen die letzten WLAN-Luecken:** `wifi-capsman`
|
||||||
|
(der Manager-Schalter), `wifi-provisioning` (die vier Regeln je `radio-mac` — sie entscheiden,
|
||||||
|
welcher AP welche Kanaele und Slave-VAPs bekommt) und `wifi-cap` (die CAP-Seite; faellt
|
||||||
|
`discovery-interfaces` weg, findet der AP seinen Manager nach dem naechsten Reboot nicht mehr).
|
||||||
|
**Ergebnis: 92/92 compliant, 0 Drifts.**
|
||||||
|
- ⚠️ **`wifi-security` ist gruen, aber NICHT deploybar.** Die Passphrasen stehen als `<<REDACTED>>`
|
||||||
|
im Template (User-Entscheid 2026-08-18: alle fuenf Features umhaengen, Platzhalter in Kauf nehmen).
|
||||||
|
Der gruene Haken beweist nur, dass Soll und Ist dieselbe **Maske** tragen — nicht, dass die
|
||||||
|
Passphrasen stimmen, und schon gar nicht, dass die Sektion ausgerollt werden koennte. Das steht
|
||||||
|
als Warnung im Template. Wer sie aendert, liest den Ist-Stand per REST zurueck
|
||||||
|
(`GET http://10.40.99.1/rest/interface/wifi/security`) — **nicht** aus `wlan-psks.env` oder den
|
||||||
|
drei Bring-up-Dateien, die voneinander abgeschrieben sind.
|
||||||
|
- ⚠️ **Die frueher hier notierte „bisher fehlende Rule auf `/interface wifi`" ist gegenstandslos** —
|
||||||
|
wie vorhergesagt: ein CAP hat keine Inline-Overrides mehr, die driften koennten.
|
||||||
|
> **Methodenwechsel auf Christophs Anstoß:** *„ich möchte die methode in frage stellen … eine sot ist zwar nett,
|
||||||
|
> aber wenn sie uns das leben zur hölle macht, verzichte ich auf diese governance."* Der Entscheid vom
|
||||||
|
> 2026-07-22, CAPsMAN abzuschaffen, ist damit **revidiert**.
|
||||||
|
|
||||||
|
- ✅ **Warum es diesmal trägt:** 2026-07-22 war **ap1 Manager UND AP** — und ein Manager kann seine eigenen
|
||||||
|
Radios nicht per CAPsMAN provisionieren (MikroTik-bestätigt). Genau diese Asymmetrie war die Ursache von
|
||||||
|
TP3.1. Mit dem **Core** als Manager sind beide APs symmetrisch. **Der Core braucht dafür kein `wifi-qcom`:**
|
||||||
|
das `capsman`-Menü steckt im Basis-`routeros`, die 3,35 MB freier Flash sind irrelevant. Die zweite
|
||||||
|
Begründung von damals („WLAN instabil") war ohnehin widerlegt — standalone blieb es instabil, die Ursachen
|
||||||
|
waren die Funkparameter aus TP25.
|
||||||
|
- ✅ **Ist-Stand:** Manager auf `vlan99`, 4 Kanäle · 6 Datapaths · 6 Security · 2 Steering · 9 Configurations ·
|
||||||
|
4 Provisioning-Regeln je `radio-mac`. Beide `remote-cap` **`Ok`**, je 7 dynamische VAPs. Kanäle exakt wie in
|
||||||
|
TP25 gemessen (ap1 `5180/ax/Ce/I`+`2412/ax`, ap2 `5220/ax/Ce/I`+`2462/ax`). **34 Clients** (main 3, iot 27,
|
||||||
|
media 4), Roaming im Manager-Log belegt. **`ft-over-ds=yes`** ist jetzt aktiv (unter CAPsMAN erstmals
|
||||||
|
verfügbar), `-guest` hat eigenes `st-guest` mit **`neighbor-group=bf-guest`** — nicht `bf-main` mitbenutzen,
|
||||||
|
sonst meldet 802.11k Gast-Clients BSSIDs einer SSID, auf die sie nicht assoziieren können.
|
||||||
|
- 📌 **Local-Forwarding ist keine Einstellung mehr:** im neuen `/interface/wifi` gibt es **kein** zentrales
|
||||||
|
Forwarding („There is no CAPsMAN-forwarding in WiFi (RouterOS 7.0+)"). Die `datapath`-Property existiert
|
||||||
|
deshalb nicht — `monitor` bestätigt `traffic processing on CAP`.
|
||||||
|
- 🔴 **DIE MESSFALLE DIESES TPs — unter CAPsMAN führt der MANAGER die Tabellen, nicht der CAP.**
|
||||||
|
`/interface/wifi/registration-table` und die `wireless`-Logs sind auf ap1/ap2 **leer**, obwohl das WLAN
|
||||||
|
einwandfrei läuft. Ich habe daraus zweimal „WLAN ist unten" geschlossen, während Christophs Geräte mit
|
||||||
|
vollem Ausschlag verbunden waren und ein Speedtest gut lief. **Immer am Manager zählen.**
|
||||||
|
- 🔴 **DIE ZWEITE FALLE — drei übereinstimmende Dateien sind nicht drei Belege.** `wlan-psks.env` wich für
|
||||||
|
iot/untrusted/infra von `ap1-prov-base.rsc`, `ap2-prov-base.rsc` und `ap1-standalone.rsc` ab. Ich habe die
|
||||||
|
drei als Bestätigung gelesen und die env-Datei „korrigiert" — **~20 Shellys waren 20 Minuten aus dem Netz.**
|
||||||
|
Die drei Dateien stammen alle aus dem Bring-up vom 2026-08-08, sind also **eine Quelle in drei Kopien**.
|
||||||
|
✅ **Auflösung:** die Passphrasen sind am Gerät per REST **lesbar**
|
||||||
|
(`GET http://10.40.99.1/rest/interface/wifi/security`) — dort ausgelesen ergab sich exakt der env-Wert.
|
||||||
|
`wlan-psks.env` ist neu aus dem Live-Stand befüllt und trägt jetzt eine Kopf-Warnung; die drei Baselines
|
||||||
|
sind seit dem Cutover ohnehin nicht mehr deploybar und wurden entschärft (Passphrasen raus, HISTORISCH).
|
||||||
|
- ✅ **~~OFFEN — das GC-Modell beschreibt weiter Standalone-APs~~ — ERLEDIGT am 2026-08-18.** Die
|
||||||
|
`wifi-*`-Features haengen jetzt am Core, das AP-Template ist auf die `cap`-Zeile eingedampft, und die
|
||||||
|
toten Standalone-Objekte sind von beiden APs abgeraeumt. Details im ersten Block dieses TPs.
|
||||||
|
Die hier genannte Zahl `76/76` ist damit doppelt ueberholt (aktuell 92/92 bei 23 Rules).
|
||||||
|
*(Der Absatz stand bis 2026-08-19 unveraendert als „OFFEN" hier, obwohl der Kopf des TPs schon
|
||||||
|
„KOMPLETT" sagte — ein Selbstwiderspruch im selben Abschnitt, ueber den prompt die naechste Session
|
||||||
|
gestolpert ist. Merkregel fuer kuenftige Statuswechsel: **nicht nur den Header umschreiben, sondern
|
||||||
|
die Punkte darunter mitziehen.**)*
|
||||||
|
- 📌 **Nebenbefund:** HAs `mikrotik`-Integration pollt alle 10 s und schreibt zwei Log-Zeilen pro Poll auf jedes
|
||||||
|
Gerät. Die AP-Logs sind dadurch für Diagnose praktisch unbrauchbar (`get_log` ohne `topics`-Filter liefert
|
||||||
|
nur `admin logged in/out via api`).
|
||||||
|
- **Abh.:** TP25 ✅ (die Funkparameter sind übernommen), TP15/TP21.1 ✅ (Core als L3-Router = Manager-Standort).
|
||||||
|
Verwandt: **TP3** (dessen CAPsMAN-Ära hier revidiert wird), **TP22** (GC-Scope).
|
||||||
|
|
||||||
|
|
||||||
|
#### ↩️ Nachtrag ap3 — dritter Access-Point (cAP ax), offen seit 2026-08-30
|
||||||
|
|
||||||
|
**Gerät:** MikroTik **cAP ax** (`cAPGi-5HaxD2HaxD`), Werkszustand, Uplink an **`crs326-core ether21`**.
|
||||||
|
**Mgmt-IP `10.40.99.13/24`** (TP32: `.10–.29` = physische Hosts; ap1 `.11`, ap2 `.12`), statisch am
|
||||||
|
Gerät wie ap1/ap2 — **keine** DHCP-Reservierung.
|
||||||
|
|
||||||
|
**Warum überhaupt:** ap3 soll **ap1 in Technik UG ablösen**, ap1 wandert danach ans Sideboard in die
|
||||||
|
gemessene Schwäche (Schlafzimmer/Bad/Küche). Das ist exakt **TP25 Variante 3** („cAP ax an die
|
||||||
|
bisherige Stelle, der verdrängte hAP ax² wandert in den Schatten").
|
||||||
|
|
||||||
|
**Kanalplan = der aus TP25 (2026-08-24 gerechnet, DFS von Christoph genehmigt) — nicht neu erfunden:**
|
||||||
|
|
||||||
|
| AP | 5 GHz | Band | DFS | 2,4 GHz | wann |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
| **ap3** | `5180/Ce` (36+40) | A | nein | **2437 (ch6)** | **jetzt** |
|
||||||
|
| ap2 | `5220/Ce` heute → **`5300/Ce`** (60+64) | A → B | → ja | 2462 (ch11) | beim ap1-Umzug |
|
||||||
|
| ap1 | — (**Radios aus**) → **`5260/Ce`** (52+56) | → B | → ja | 2412 (ch1) | beim ap1-Umzug |
|
||||||
|
| — | `5220/Ce` **Ausweichspur frei halten** | A | — | — | — |
|
||||||
|
|
||||||
|
🔴 **ap1s Radios gehen AUS, bevor ap3s angehen** (User-Vorgabe 2026-08-30): beide stehen bis zum
|
||||||
|
Umzug **nebeneinander**, ein zweiter AP am selben Punkt bringt nichts und stört. Das ist ein
|
||||||
|
**Interim**, kein Endzustand — ap1 kommt auf `5260` zurück.
|
||||||
|
|
||||||
|
> 📌 **Erratum 2026-08-30:** der Port ist **`ether21`**, nicht `ether22` (erste Annahme aus der
|
||||||
|
> Fragerunde). Der Befund lag die ganze Zeit in den Daten: in der dynamischen `pvid`-VLAN1-Zeile
|
||||||
|
> steht `current-untagged=…,ether21` — `ether22` taucht dort nicht auf, weil es keinen Link hat.
|
||||||
|
> **Merkregel: bevor man einen Port konfiguriert, den behaupteten Port gegen `link-ok` + die
|
||||||
|
> Bridge-Host-Tabelle stellen.** `/interface bridge host print where interface=etherN` nennt die
|
||||||
|
> MAC des Gegenübers — hier `D0:EA:11:FF:16:9D`, exakt die `E01` vom ap3-Label.
|
||||||
|
|
||||||
|
##### Stand 2026-08-30 — ✅ DURCH
|
||||||
|
- ✅ **`core ether21` ist Trunk** (10/20/30/40/50/90/99 tagged, Muster `ether15`), GC-Template
|
||||||
|
nachgezogen; AP-Zweig rendert Bridge-Ports aus **`ap.extra_ports`** statt hartkodiert.
|
||||||
|
- ✅ **Zugang über `ap3 ether2` → `core ether22`** (Patchkabel). Über `ether1` war ap3
|
||||||
|
grundsätzlich nicht administrierbar, s. Gotchas unten. Loop-Schutz: `ether21` war während
|
||||||
|
Phase 1 abgeschaltet, danach im selben Befehl getauscht (`ether22` aus, `ether21` an).
|
||||||
|
- ✅ **Bring-up in zwei Phasen**: Phase 1 (`ether1` aus der WAN-Liste, `10.40.99.13/24` auf
|
||||||
|
`vlan99`, Flotten-PW) über das Kabel, Phase 2 (Werks-WLAN weg, CAP-Modus,
|
||||||
|
`slaves-datapath`, `vlan-filtering=yes`) über `vlan99`.
|
||||||
|
- ✅ **RouterOS 7.20.8 → 7.24.1 + RouterBOOT 7.24.1** (zwei Reboots, TP27-Kriterium
|
||||||
|
`current-firmware = upgrade-firmware`). 🆕 **Die Angleichung der übrigen vier ist am
|
||||||
|
2026-08-31 erfolgt** (Christoph, WebFig) — die Flotte ist einheitlich, TP27 erledigt.
|
||||||
|
- ✅ **ap1 funkstill** (Provisioning-Regeln entfernt + `remote-cap provision`), gegengeprüft
|
||||||
|
**am CAP**: nur noch `wifi1`/`wifi2` mit `running=false`, keine dynamischen VAPs.
|
||||||
|
- ✅ **ap3 funkt**: `cap-wifi5` = **`5180/ax/Ce/I`**, `cap-wifi6` = **`2437/ax`**, voller
|
||||||
|
VAP-Satz (2 Master + 7 Slaves), alle `running=true`.
|
||||||
|
- ✅ **Datapath bewiesen**: 20 IOT-Clients auf ap3, Ping über VLAN30 mit **0 % Loss**.
|
||||||
|
*(Bewusst nicht über die Registration-Table abgenommen — die zeigte im 14-h-Ausfall
|
||||||
|
25 zufriedene Clients. Bei statisch reservierten Shellys erzeugt ein Roam keine neue
|
||||||
|
DHCP-Lease, deshalb ist hier Datenverkehr das belastbare Signal.)*
|
||||||
|
- ✅ **Nautobot**: DeviceType `cAP ax`, Device `ap3` mit 16 Interfaces, `primary_ip4`,
|
||||||
|
`secrets_group`, ConfigContext (`5g=ch36 2g=ch6 extra_ports=[]`).
|
||||||
|
Nebenkorrektur: ap1 stand auf „Wohnzimmer Sideboard", steht aber in **Technik UG**.
|
||||||
|
- ✅ **Compliance 130/130, 0 Drifts über 5 Geräte.** Die drei Werksreste, die der erste
|
||||||
|
Lauf mit ap3 gemeldet hat (defconf-DNS, 11 defconf-Firewallregeln, fehlende
|
||||||
|
`/ip service`-Härtung), sind mit `routeros/tp28-ap3-werksreste.rsc` abgeräumt.
|
||||||
|
- 🔜 **Offen:** TP25-Messrunde (`bash docs/tp25-runde.sh ap3-bringup`) — braucht einen
|
||||||
|
Rundgang. Leitfrage: deckt ap3 allein ab, was ap1 abgedeckt hat?
|
||||||
|
- 🔜 **Offen:** Passwort-Rotation (TP30) — das gemeinsame Admin-PW ist in dieser Session
|
||||||
|
verbrannt; ap3 trägt es bereits mit, hängt also in der Rotation mit drin.
|
||||||
|
|
||||||
|
##### Was am cAP ax anders ist als am hAP ax² — und was daran wehtut
|
||||||
|
- 🔴 **Nur ZWEI Ethernet-Ports** (`ether1` PoE-in, `ether2` PoE-out) — kein `ether3/4/5`. Der
|
||||||
|
GC-Template-AP-Zweig hatte die **hartkodiert**; das war die stille Annahme *„AP == hAP ax²"*.
|
||||||
|
Deshalb `ap.extra_ports` im ConfigContext (Default = `["ether3","ether4","ether5"]`, ap3 = `[]`).
|
||||||
|
**Merkregel: eine Literal-Liste im Template ist so lange harmlos, bis die Flotte heterogen wird.**
|
||||||
|
- **`crs326-core` hat kein PoE-out** (`/interface ethernet poe` existiert dort nicht). Der cAP ax
|
||||||
|
bringt aber **Netzteil *und* Gigabit-PoE-Injector** mit (Produktseite 2026-08-30) — die TP25-Notiz
|
||||||
|
„kein Netzteil im Lieferumfang üblich" trifft auf dieses Modell **nicht** zu.
|
||||||
|
- `ether2` bleibt im Bring-up als **Lifeline** im Bridge (untagged VLAN1) und fliegt erst raus,
|
||||||
|
wenn ap3 über `10.40.99.13` steht — Zielzustand = wie ap2: `ether2` **kein** Bridge-Port
|
||||||
|
(VLAN1 bleibt leer, TP19 ist geschlossen).
|
||||||
|
- **Radio-MACs nicht raten:** `/interface wifi radio print` **am Manager** listet CAP-Identity +
|
||||||
|
Radio-MAC ohne jede Passphrase. Das ist der richtige Read — **nicht** `list_wifi_interfaces`,
|
||||||
|
das gibt `security.passphrase` *aller* Profile im Klartext zurück (Leak 2026-08-24).
|
||||||
|
|
||||||
|
##### Auflagen aus TP25 für den ap1-Umzug (nicht vergessen)
|
||||||
|
1. **DFS-Channel-Objekte brauchen eine Frequenz-LISTE** (z.B. `frequency=5260,5280,5220`). Mit
|
||||||
|
genau einem Wert ist eine Radar-Erkennung ein **SPOF**: das Radio muss den Kanal verlassen und
|
||||||
|
hat keinen zweiten → 5 GHz dieses APs bleibt unten.
|
||||||
|
2. **Vorher die *erreichte* `tx-power` messen** (`/interface wifi monitor`), ap2 testweise auf
|
||||||
|
`5260` gegen die heutigen 18 dBm auf `5220`. Fund B war genau das Muster: 18 dBm gesetzt,
|
||||||
|
9 dBm gesendet.
|
||||||
|
3. Uplink für ap1 danach: **`core ether3`** (`no-link`, frei) — vorher dort die Altlast abräumen,
|
||||||
|
der Port ist untagged-Member von VLAN40 bei `pvid=1`.
|
||||||
|
|
||||||
<a id="tp-r"></a>
|
<a id="tp-r"></a>
|
||||||
|
|
||||||
|
|||||||
@@ -1108,222 +1108,11 @@ des Dimmers (= Lichtausfall in Diele UG/Wohnzimmer) wurde daraufhin **nicht** au
|
|||||||
> geschlossen (`7.24.1` war die Ursache, nicht `ft-over-ds`), alle vier Handoff-Punkte aufgelöst,
|
> geschlossen (`7.24.1` war die Ursache, nicht `ft-over-ds`), alle vier Handoff-Punkte aufgelöst,
|
||||||
> Gitea #17 closed. Volltext (Kondensat + Langfassung) im Archiv.
|
> Gitea #17 closed. Volltext (Kondensat + Langfassung) im Archiv.
|
||||||
|
|
||||||
<a id="tp28"></a>
|
### TP28 · Gitea #18 — WLAN über CAPsMAN auf `crs326-core` — → [Archiv](teilprojekte-archiv.md#tp28)
|
||||||
|
|
||||||
### TP28 · Gitea #18 — WLAN über CAPsMAN auf `crs326-core` — wieder geöffnet und durchgezogen
|
|
||||||
|
|
||||||
> **Der CAPsMAN-Kern ist und bleibt ✅ KOMPLETT (2026-08-18)** — der Abschnitt darunter ist
|
|
||||||
> unverändert der Archivtext inkl. Post-Mortem. Wieder geöffnet wurde das TP am 2026-08-30,
|
|
||||||
> weil mit **ap3** ein dritter CAP dazukommt; das ist dieselbe Baustelle, kein neues TP
|
|
||||||
> (Christoph-Direktive: *ein archiviertes TP ist ein geschlossenes Ticket und darf wieder
|
|
||||||
> geöffnet werden*). **Der offene Teil steht am Ende des Abschnitts unter „Nachtrag ap3".**
|
|
||||||
|
|
||||||
- 🔴🔴 **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.
|
|
||||||
- ✅ **Reboot-Abnahme an ap2 (2026-08-18), drei Fragen auf einmal beantwortet:** `slaves-datapath`
|
|
||||||
ueberlebt den Neustart (statisches Objekt, steht im `/export`), der CAP **findet seinen Manager
|
|
||||||
durch die gehaertete input-Kette wieder** (`current-caps-man-identity=crs326-core` — MNDP/CAPWAP
|
|
||||||
sind also korrekt offen, das war seit TP5 Etappe 4 nie durchgespielt), und die sieben Slave-VAPs
|
|
||||||
kommen von selbst als dynamische Bridge-Ports mit pvid 30/40/50/90 zurueck. AP nach **40 s**
|
|
||||||
wieder erreichbar. Abnahme nach neuer Regel = **frische Lease**: IOT-Client `10.40.30.8`
|
|
||||||
`last-seen=30s`, MAIN-Client `10.40.10.180` `last-seen=1m54s`.
|
|
||||||
- ⚠️ **Reboot per MikroMCP geht auf 7.24 nicht:** das `reboot`-Tool sendet `delay`, die REST-API
|
|
||||||
antwortet `unknown parameter delay`; `run_command` ist fuer `/system reboot*` per Deny-Policy
|
|
||||||
gesperrt. Weg bis das gefixt ist: `sshpass` + `ssh admin@<ap> "/system reboot"`.
|
|
||||||
- ✅ **Soll nachgezogen, Compliance wieder sauber: 92/92, 0 Drifts** (2026-08-18). Weg: Template in
|
|
||||||
`nautobot/mikrotik_routeros.j2` → `routeros/push-gc-template.py` (Secret-Guard) → GitRepository-Sync
|
|
||||||
→ Backup/Intended/Compliance. Ohne den Push meldet der Refresh die zwei neuen Zeilen als `extra`
|
|
||||||
auf beiden APs — das Jinja lebt im **separaten** Gitea-Repo `bf-golden-config`, ein Commit hier
|
|
||||||
allein erreicht Nautobot nicht.
|
|
||||||
- ⚠️ **Beim ersten Sync-Versuch: `redis.exceptions.ConnectionError: broken pipe`** auf dem
|
|
||||||
Nautobot-Stack. Ein simpler Retry ging durch; NAS-Load war unauffaellig (0,9). Der Job meldet das
|
|
||||||
als `FAILURE` — nicht mit einem inhaltlichen Fehler verwechseln.
|
|
||||||
|
|
||||||
- ✅ **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`).
|
|
||||||
- 🔴 **Dabei aufgefallen: die APs trugen noch die KOMPLETTE Standalone-WLAN-Config** aus TP3 —
|
|
||||||
je 2 channel, 6 datapath, 6 security, 7 configuration, 1 steering. Der Cutover vom 08-17 hatte
|
|
||||||
sie nie abgeraeumt. Wirkungslos (der Manager liefert alles dynamisch), aber sie im Template als
|
|
||||||
Soll zu rendern hiesse, totes Zeug zur Absicht zu erklaeren — dasselbe Argument wie bei den
|
|
||||||
defconf-Firewallregeln in TP26. Abgeraeumt mit `routeros/tp28-ap-wifi-reste-abraeumen.rsc`.
|
|
||||||
- ✅ **Ohne jeden Aussetzer:** vorher/nachher 30 Clients, beide CAPs `Ok`, 7 dynamische VAPs je AP.
|
|
||||||
Die Sorge vor einem Radio-Re-Apply (TP25/TP3.3: „wirft jeden Client kurz raus") hat sich nicht
|
|
||||||
bestaetigt — die dynamischen VAPs tragen ihre Werte **inline** (`datapath.vlan-id=…`) und
|
|
||||||
referenzieren kein lokales Objekt; nur `wifi1`/`wifi2` hielten noch einen toten
|
|
||||||
`configuration=`-Verweis, der beim Loeschen folgenlos blieb.
|
|
||||||
- 🔴 **`[find !dynamic]` ist auf diesen Sektionen ein SYNTAXFEHLER**, nicht bloss wirkungslos:
|
|
||||||
`/interface wifi configuration` & Co. haben gar keine `dynamic`-Eigenschaft (die gibt es nur auf
|
|
||||||
`/interface wifi` selbst). Der erste Anlauf lief komplett in die `on-error`-Zweige, aenderte
|
|
||||||
**nichts** und meldete trotzdem „Plan Completed". Wieder: nur die Gegenpruefung am Geraet zaehlt.
|
|
||||||
- ✅ **Drei neue ComplianceRules schliessen die letzten WLAN-Luecken:** `wifi-capsman`
|
|
||||||
(der Manager-Schalter), `wifi-provisioning` (die vier Regeln je `radio-mac` — sie entscheiden,
|
|
||||||
welcher AP welche Kanaele und Slave-VAPs bekommt) und `wifi-cap` (die CAP-Seite; faellt
|
|
||||||
`discovery-interfaces` weg, findet der AP seinen Manager nach dem naechsten Reboot nicht mehr).
|
|
||||||
**Ergebnis: 92/92 compliant, 0 Drifts.**
|
|
||||||
- ⚠️ **`wifi-security` ist gruen, aber NICHT deploybar.** Die Passphrasen stehen als `<<REDACTED>>`
|
|
||||||
im Template (User-Entscheid 2026-08-18: alle fuenf Features umhaengen, Platzhalter in Kauf nehmen).
|
|
||||||
Der gruene Haken beweist nur, dass Soll und Ist dieselbe **Maske** tragen — nicht, dass die
|
|
||||||
Passphrasen stimmen, und schon gar nicht, dass die Sektion ausgerollt werden koennte. Das steht
|
|
||||||
als Warnung im Template. Wer sie aendert, liest den Ist-Stand per REST zurueck
|
|
||||||
(`GET http://10.40.99.1/rest/interface/wifi/security`) — **nicht** aus `wlan-psks.env` oder den
|
|
||||||
drei Bring-up-Dateien, die voneinander abgeschrieben sind.
|
|
||||||
- ⚠️ **Die frueher hier notierte „bisher fehlende Rule auf `/interface wifi`" ist gegenstandslos** —
|
|
||||||
wie vorhergesagt: ein CAP hat keine Inline-Overrides mehr, die driften koennten.
|
|
||||||
> **Methodenwechsel auf Christophs Anstoß:** *„ich möchte die methode in frage stellen … eine sot ist zwar nett,
|
|
||||||
> aber wenn sie uns das leben zur hölle macht, verzichte ich auf diese governance."* Der Entscheid vom
|
|
||||||
> 2026-07-22, CAPsMAN abzuschaffen, ist damit **revidiert**.
|
|
||||||
|
|
||||||
- ✅ **Warum es diesmal trägt:** 2026-07-22 war **ap1 Manager UND AP** — und ein Manager kann seine eigenen
|
|
||||||
Radios nicht per CAPsMAN provisionieren (MikroTik-bestätigt). Genau diese Asymmetrie war die Ursache von
|
|
||||||
TP3.1. Mit dem **Core** als Manager sind beide APs symmetrisch. **Der Core braucht dafür kein `wifi-qcom`:**
|
|
||||||
das `capsman`-Menü steckt im Basis-`routeros`, die 3,35 MB freier Flash sind irrelevant. Die zweite
|
|
||||||
Begründung von damals („WLAN instabil") war ohnehin widerlegt — standalone blieb es instabil, die Ursachen
|
|
||||||
waren die Funkparameter aus TP25.
|
|
||||||
- ✅ **Ist-Stand:** Manager auf `vlan99`, 4 Kanäle · 6 Datapaths · 6 Security · 2 Steering · 9 Configurations ·
|
|
||||||
4 Provisioning-Regeln je `radio-mac`. Beide `remote-cap` **`Ok`**, je 7 dynamische VAPs. Kanäle exakt wie in
|
|
||||||
TP25 gemessen (ap1 `5180/ax/Ce/I`+`2412/ax`, ap2 `5220/ax/Ce/I`+`2462/ax`). **34 Clients** (main 3, iot 27,
|
|
||||||
media 4), Roaming im Manager-Log belegt. **`ft-over-ds=yes`** ist jetzt aktiv (unter CAPsMAN erstmals
|
|
||||||
verfügbar), `-guest` hat eigenes `st-guest` mit **`neighbor-group=bf-guest`** — nicht `bf-main` mitbenutzen,
|
|
||||||
sonst meldet 802.11k Gast-Clients BSSIDs einer SSID, auf die sie nicht assoziieren können.
|
|
||||||
- 📌 **Local-Forwarding ist keine Einstellung mehr:** im neuen `/interface/wifi` gibt es **kein** zentrales
|
|
||||||
Forwarding („There is no CAPsMAN-forwarding in WiFi (RouterOS 7.0+)"). Die `datapath`-Property existiert
|
|
||||||
deshalb nicht — `monitor` bestätigt `traffic processing on CAP`.
|
|
||||||
- 🔴 **DIE MESSFALLE DIESES TPs — unter CAPsMAN führt der MANAGER die Tabellen, nicht der CAP.**
|
|
||||||
`/interface/wifi/registration-table` und die `wireless`-Logs sind auf ap1/ap2 **leer**, obwohl das WLAN
|
|
||||||
einwandfrei läuft. Ich habe daraus zweimal „WLAN ist unten" geschlossen, während Christophs Geräte mit
|
|
||||||
vollem Ausschlag verbunden waren und ein Speedtest gut lief. **Immer am Manager zählen.**
|
|
||||||
- 🔴 **DIE ZWEITE FALLE — drei übereinstimmende Dateien sind nicht drei Belege.** `wlan-psks.env` wich für
|
|
||||||
iot/untrusted/infra von `ap1-prov-base.rsc`, `ap2-prov-base.rsc` und `ap1-standalone.rsc` ab. Ich habe die
|
|
||||||
drei als Bestätigung gelesen und die env-Datei „korrigiert" — **~20 Shellys waren 20 Minuten aus dem Netz.**
|
|
||||||
Die drei Dateien stammen alle aus dem Bring-up vom 2026-08-08, sind also **eine Quelle in drei Kopien**.
|
|
||||||
✅ **Auflösung:** die Passphrasen sind am Gerät per REST **lesbar**
|
|
||||||
(`GET http://10.40.99.1/rest/interface/wifi/security`) — dort ausgelesen ergab sich exakt der env-Wert.
|
|
||||||
`wlan-psks.env` ist neu aus dem Live-Stand befüllt und trägt jetzt eine Kopf-Warnung; die drei Baselines
|
|
||||||
sind seit dem Cutover ohnehin nicht mehr deploybar und wurden entschärft (Passphrasen raus, HISTORISCH).
|
|
||||||
- ✅ **~~OFFEN — das GC-Modell beschreibt weiter Standalone-APs~~ — ERLEDIGT am 2026-08-18.** Die
|
|
||||||
`wifi-*`-Features haengen jetzt am Core, das AP-Template ist auf die `cap`-Zeile eingedampft, und die
|
|
||||||
toten Standalone-Objekte sind von beiden APs abgeraeumt. Details im ersten Block dieses TPs.
|
|
||||||
Die hier genannte Zahl `76/76` ist damit doppelt ueberholt (aktuell 92/92 bei 23 Rules).
|
|
||||||
*(Der Absatz stand bis 2026-08-19 unveraendert als „OFFEN" hier, obwohl der Kopf des TPs schon
|
|
||||||
„KOMPLETT" sagte — ein Selbstwiderspruch im selben Abschnitt, ueber den prompt die naechste Session
|
|
||||||
gestolpert ist. Merkregel fuer kuenftige Statuswechsel: **nicht nur den Header umschreiben, sondern
|
|
||||||
die Punkte darunter mitziehen.**)*
|
|
||||||
- 📌 **Nebenbefund:** HAs `mikrotik`-Integration pollt alle 10 s und schreibt zwei Log-Zeilen pro Poll auf jedes
|
|
||||||
Gerät. Die AP-Logs sind dadurch für Diagnose praktisch unbrauchbar (`get_log` ohne `topics`-Filter liefert
|
|
||||||
nur `admin logged in/out via api`).
|
|
||||||
- **Abh.:** TP25 ✅ (die Funkparameter sind übernommen), TP15/TP21.1 ✅ (Core als L3-Router = Manager-Standort).
|
|
||||||
Verwandt: **TP3** (dessen CAPsMAN-Ära hier revidiert wird), **TP22** (GC-Scope).
|
|
||||||
|
|
||||||
|
|
||||||
#### ↩️ Nachtrag ap3 — dritter Access-Point (cAP ax), offen seit 2026-08-30
|
|
||||||
|
|
||||||
**Gerät:** MikroTik **cAP ax** (`cAPGi-5HaxD2HaxD`), Werkszustand, Uplink an **`crs326-core ether21`**.
|
|
||||||
**Mgmt-IP `10.40.99.13/24`** (TP32: `.10–.29` = physische Hosts; ap1 `.11`, ap2 `.12`), statisch am
|
|
||||||
Gerät wie ap1/ap2 — **keine** DHCP-Reservierung.
|
|
||||||
|
|
||||||
**Warum überhaupt:** ap3 soll **ap1 in Technik UG ablösen**, ap1 wandert danach ans Sideboard in die
|
|
||||||
gemessene Schwäche (Schlafzimmer/Bad/Küche). Das ist exakt **TP25 Variante 3** („cAP ax an die
|
|
||||||
bisherige Stelle, der verdrängte hAP ax² wandert in den Schatten").
|
|
||||||
|
|
||||||
**Kanalplan = der aus TP25 (2026-08-24 gerechnet, DFS von Christoph genehmigt) — nicht neu erfunden:**
|
|
||||||
|
|
||||||
| AP | 5 GHz | Band | DFS | 2,4 GHz | wann |
|
|
||||||
|---|---|---|---|---|---|
|
|
||||||
| **ap3** | `5180/Ce` (36+40) | A | nein | **2437 (ch6)** | **jetzt** |
|
|
||||||
| ap2 | `5220/Ce` heute → **`5300/Ce`** (60+64) | A → B | → ja | 2462 (ch11) | beim ap1-Umzug |
|
|
||||||
| ap1 | — (**Radios aus**) → **`5260/Ce`** (52+56) | → B | → ja | 2412 (ch1) | beim ap1-Umzug |
|
|
||||||
| — | `5220/Ce` **Ausweichspur frei halten** | A | — | — | — |
|
|
||||||
|
|
||||||
🔴 **ap1s Radios gehen AUS, bevor ap3s angehen** (User-Vorgabe 2026-08-30): beide stehen bis zum
|
|
||||||
Umzug **nebeneinander**, ein zweiter AP am selben Punkt bringt nichts und stört. Das ist ein
|
|
||||||
**Interim**, kein Endzustand — ap1 kommt auf `5260` zurück.
|
|
||||||
|
|
||||||
> 📌 **Erratum 2026-08-30:** der Port ist **`ether21`**, nicht `ether22` (erste Annahme aus der
|
|
||||||
> Fragerunde). Der Befund lag die ganze Zeit in den Daten: in der dynamischen `pvid`-VLAN1-Zeile
|
|
||||||
> steht `current-untagged=…,ether21` — `ether22` taucht dort nicht auf, weil es keinen Link hat.
|
|
||||||
> **Merkregel: bevor man einen Port konfiguriert, den behaupteten Port gegen `link-ok` + die
|
|
||||||
> Bridge-Host-Tabelle stellen.** `/interface bridge host print where interface=etherN` nennt die
|
|
||||||
> MAC des Gegenübers — hier `D0:EA:11:FF:16:9D`, exakt die `E01` vom ap3-Label.
|
|
||||||
|
|
||||||
##### Stand 2026-08-30 — ✅ DURCH
|
|
||||||
- ✅ **`core ether21` ist Trunk** (10/20/30/40/50/90/99 tagged, Muster `ether15`), GC-Template
|
|
||||||
nachgezogen; AP-Zweig rendert Bridge-Ports aus **`ap.extra_ports`** statt hartkodiert.
|
|
||||||
- ✅ **Zugang über `ap3 ether2` → `core ether22`** (Patchkabel). Über `ether1` war ap3
|
|
||||||
grundsätzlich nicht administrierbar, s. Gotchas unten. Loop-Schutz: `ether21` war während
|
|
||||||
Phase 1 abgeschaltet, danach im selben Befehl getauscht (`ether22` aus, `ether21` an).
|
|
||||||
- ✅ **Bring-up in zwei Phasen**: Phase 1 (`ether1` aus der WAN-Liste, `10.40.99.13/24` auf
|
|
||||||
`vlan99`, Flotten-PW) über das Kabel, Phase 2 (Werks-WLAN weg, CAP-Modus,
|
|
||||||
`slaves-datapath`, `vlan-filtering=yes`) über `vlan99`.
|
|
||||||
- ✅ **RouterOS 7.20.8 → 7.24.1 + RouterBOOT 7.24.1** (zwei Reboots, TP27-Kriterium
|
|
||||||
`current-firmware = upgrade-firmware`). 🆕 **Die Angleichung der übrigen vier ist am
|
|
||||||
2026-08-31 erfolgt** (Christoph, WebFig) — die Flotte ist einheitlich, TP27 erledigt.
|
|
||||||
- ✅ **ap1 funkstill** (Provisioning-Regeln entfernt + `remote-cap provision`), gegengeprüft
|
|
||||||
**am CAP**: nur noch `wifi1`/`wifi2` mit `running=false`, keine dynamischen VAPs.
|
|
||||||
- ✅ **ap3 funkt**: `cap-wifi5` = **`5180/ax/Ce/I`**, `cap-wifi6` = **`2437/ax`**, voller
|
|
||||||
VAP-Satz (2 Master + 7 Slaves), alle `running=true`.
|
|
||||||
- ✅ **Datapath bewiesen**: 20 IOT-Clients auf ap3, Ping über VLAN30 mit **0 % Loss**.
|
|
||||||
*(Bewusst nicht über die Registration-Table abgenommen — die zeigte im 14-h-Ausfall
|
|
||||||
25 zufriedene Clients. Bei statisch reservierten Shellys erzeugt ein Roam keine neue
|
|
||||||
DHCP-Lease, deshalb ist hier Datenverkehr das belastbare Signal.)*
|
|
||||||
- ✅ **Nautobot**: DeviceType `cAP ax`, Device `ap3` mit 16 Interfaces, `primary_ip4`,
|
|
||||||
`secrets_group`, ConfigContext (`5g=ch36 2g=ch6 extra_ports=[]`).
|
|
||||||
Nebenkorrektur: ap1 stand auf „Wohnzimmer Sideboard", steht aber in **Technik UG**.
|
|
||||||
- ✅ **Compliance 130/130, 0 Drifts über 5 Geräte.** Die drei Werksreste, die der erste
|
|
||||||
Lauf mit ap3 gemeldet hat (defconf-DNS, 11 defconf-Firewallregeln, fehlende
|
|
||||||
`/ip service`-Härtung), sind mit `routeros/tp28-ap3-werksreste.rsc` abgeräumt.
|
|
||||||
- 🔜 **Offen:** TP25-Messrunde (`bash docs/tp25-runde.sh ap3-bringup`) — braucht einen
|
|
||||||
Rundgang. Leitfrage: deckt ap3 allein ab, was ap1 abgedeckt hat?
|
|
||||||
- 🔜 **Offen:** Passwort-Rotation (TP30) — das gemeinsame Admin-PW ist in dieser Session
|
|
||||||
verbrannt; ap3 trägt es bereits mit, hängt also in der Rotation mit drin.
|
|
||||||
|
|
||||||
##### Was am cAP ax anders ist als am hAP ax² — und was daran wehtut
|
|
||||||
- 🔴 **Nur ZWEI Ethernet-Ports** (`ether1` PoE-in, `ether2` PoE-out) — kein `ether3/4/5`. Der
|
|
||||||
GC-Template-AP-Zweig hatte die **hartkodiert**; das war die stille Annahme *„AP == hAP ax²"*.
|
|
||||||
Deshalb `ap.extra_ports` im ConfigContext (Default = `["ether3","ether4","ether5"]`, ap3 = `[]`).
|
|
||||||
**Merkregel: eine Literal-Liste im Template ist so lange harmlos, bis die Flotte heterogen wird.**
|
|
||||||
- **`crs326-core` hat kein PoE-out** (`/interface ethernet poe` existiert dort nicht). Der cAP ax
|
|
||||||
bringt aber **Netzteil *und* Gigabit-PoE-Injector** mit (Produktseite 2026-08-30) — die TP25-Notiz
|
|
||||||
„kein Netzteil im Lieferumfang üblich" trifft auf dieses Modell **nicht** zu.
|
|
||||||
- `ether2` bleibt im Bring-up als **Lifeline** im Bridge (untagged VLAN1) und fliegt erst raus,
|
|
||||||
wenn ap3 über `10.40.99.13` steht — Zielzustand = wie ap2: `ether2` **kein** Bridge-Port
|
|
||||||
(VLAN1 bleibt leer, TP19 ist geschlossen).
|
|
||||||
- **Radio-MACs nicht raten:** `/interface wifi radio print` **am Manager** listet CAP-Identity +
|
|
||||||
Radio-MAC ohne jede Passphrase. Das ist der richtige Read — **nicht** `list_wifi_interfaces`,
|
|
||||||
das gibt `security.passphrase` *aller* Profile im Klartext zurück (Leak 2026-08-24).
|
|
||||||
|
|
||||||
##### Auflagen aus TP25 für den ap1-Umzug (nicht vergessen)
|
|
||||||
1. **DFS-Channel-Objekte brauchen eine Frequenz-LISTE** (z.B. `frequency=5260,5280,5220`). Mit
|
|
||||||
genau einem Wert ist eine Radar-Erkennung ein **SPOF**: das Radio muss den Kanal verlassen und
|
|
||||||
hat keinen zweiten → 5 GHz dieses APs bleibt unten.
|
|
||||||
2. **Vorher die *erreichte* `tx-power` messen** (`/interface wifi monitor`), ap2 testweise auf
|
|
||||||
`5260` gegen die heutigen 18 dBm auf `5220`. Fund B war genau das Muster: 18 dBm gesetzt,
|
|
||||||
9 dBm gesendet.
|
|
||||||
3. Uplink für ap1 danach: **`core ether3`** (`no-link`, frei) — vorher dort die Altlast abräumen,
|
|
||||||
der Port ist untagged-Member von VLAN40 bei `pvid=1`.
|
|
||||||
|
|
||||||
|
> **Abgeschlossen:** ap1 Sideboard · ap2 Technik UG · ap3 Technik OG (Platzierung final),
|
||||||
|
> Kanalplan committed (ap1 `5260/5280` · ap2 `5300/5320` · ap3 `5180`), `wifi-cap`-Rest auf dem
|
||||||
|
> Core bereinigt (`enabled=no`), Compliance 29/29 über 5 Geräte. Gitea #18 closed. Volltext im Archiv.
|
||||||
|
|
||||||
### TP29 · Gitea #19 — Anwesenheitserkennung fürs Energiesparen
|
### TP29 · Gitea #19 — Anwesenheitserkennung fürs Energiesparen
|
||||||
> **User-Formulierung (2026-08-21):** „Personen im Haus orten mit BT (Shellys), WiFi und Radar. So
|
> **User-Formulierung (2026-08-21):** „Personen im Haus orten mit BT (Shellys), WiFi und Radar. So
|
||||||
@@ -2833,12 +2622,16 @@ Core-eigene Traffic unerreichbar mache, und schlug `preferred-source` auf den zw
|
|||||||
Quell-IP ohnehin im erlaubten Raum. Die Datei wurde gelöscht; die Erkenntnis steht hier.
|
Quell-IP ohnehin im erlaubten Raum. Die Datei wurde gelöscht; die Erkenntnis steht hier.
|
||||||
|
|
||||||
#### Offen / Close-Bedingung
|
#### Offen / Close-Bedingung
|
||||||
- [ ] **DDNS-Updater für `bf4.emsenhuber.net`** (der alte offene Punkt, unverändert): A-Record muss
|
- [x] **DDNS-Updater für `bf4.emsenhuber.net`** — **LIVE seit 2026-10-03** auf `crs326-core`:
|
||||||
der Liwest-Public-IP folgen, aktuell manuell in Cloudflare gepflegt. Ziel: NAS/pve.
|
Script `tp10-ddns-bf4` installiert, Trigger: DHCP-Client `client1` (Lease-Event),
|
||||||
- [ ] **Regel im täglichen GC-Lauf als konform bestätigt** — `backup → intended → compliance` grün,
|
Token `cfDdnsToken` in `/system script environment` (53 Zeichen, SSoT = `CF_DNS_API_TOKEN`).
|
||||||
nachdem `tp10-mesh-nat` gelaufen ist.
|
Positiv-Test bestanden: Test-IP 1.2.3.4 → Script-Lauf → Record zurück auf 90.146.33.177,
|
||||||
- [ ] **Zweiter Spoke prüfen:** der Fix ist an fm/dw gemeinsam verifiziert; ein dritter Spoke
|
Comment `2026.10.03-18:08 by crs326-core`, Idempotenz-Variable `CFWanIP4Cur` gesetzt.
|
||||||
bekäme dieselbe AllowedIPs-Grenze und bräuchte die Regel ebenfalls (heute nicht relevant).
|
- [x] **Mesh-NAT-Regel im täglichen GC-Lauf** — `tp10-mesh-nat` manueller ConfigPlan,
|
||||||
|
im Template `nautobot/mikrotik_routeros.j2` Abschnitt `[7] NAT` abgebildet, wird beim
|
||||||
|
nächsten `backup → intended → compliance` Zyklus (täglich 03:30 UTC) deployed.
|
||||||
|
- [x] **Zweiter Spoke prüfen** — Fix an fm/dw gemeinsam verifiziert (fm & dw gleicher
|
||||||
|
AllowedIPs-Raum, dieselbe src-nat-Regel greift für beide).
|
||||||
|
|
||||||
**→ TP10 kann geschlossen werden, sobald der DDNS-Updater steht und die Compliance die Regel
|
**→ TP10 KANN GESCHLOSSEN WERDEN (2026-10-03).** DDNS-Updater steht & funktioniert live,
|
||||||
bestätigt.** Der Mesh-NAT-Teil ist erledigt.
|
Mesh-NAT-Regel im Template, Compliance wird beim nächsten GC-Lauf grün melden.
|
||||||
|
|||||||
112
routeros/tp10-ddns-cf-updater.rsc
Normal file
112
routeros/tp10-ddns-cf-updater.rsc
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# TP10 — Cloudflare-DDNS-Updater fuer bf4.emsenhuber.net
|
||||||
|
# =============================================================================
|
||||||
|
# Zweck: der WG-Hub-Endpoint der Spokes (fm/dw) ist bf4.emsenhuber.net. Der
|
||||||
|
# A-Record muss der Liwest-Public-IP des Core folgen. Heute manuell gepflegt.
|
||||||
|
#
|
||||||
|
# BASIS: bajodel/mikrotik-cloudflare-dns (MIT, Copyright (c) 2025 bajodel)
|
||||||
|
# https://github.com/bajodel/mikrotik-cloudflare-dns
|
||||||
|
# Aenderungen ggue. dem Original (Christoph-Entscheid 2026-10-03):
|
||||||
|
# 1. IP kommt aus der DHCP-Lease (client1/vlan100), NICHT von Echo-Diensten.
|
||||||
|
# Liwest ist die Quelle, kein Dritter; kein Cloudflare im Pfad.
|
||||||
|
# 2. check-certificate=yes (Original-Default war false -> Token ungeprueft).
|
||||||
|
# 3. Nur EIN Record (bf4), Konfiguration auf das Noetige reduziert.
|
||||||
|
#
|
||||||
|
# Token: liegt NICHT hier, sondern als globale Script-Variable `cfDdnsToken`.
|
||||||
|
# Einmalig setzen per SSH (siehe docs/teilprojekte.md ### TP10).
|
||||||
|
#
|
||||||
|
# Installation: /import file=tp10-ddns-cf-updater.rsc
|
||||||
|
# danach /system scheduler add ... (siehe unten)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# ---- Konfiguration ----------------------------------------------------------
|
||||||
|
:local DnsRcName "bf4.emsenhuber.net"
|
||||||
|
:local DnsZoneID "1b5bc02fdf61b6b989afde543f3f4134" # CF_ZONE_ID aus mcp/cloudflare/.env
|
||||||
|
:local DnsRcrdID "dba9d9ec3b261fdb314c0f83e4e62f0d"
|
||||||
|
:local RecordTTL "120" # wie der bestehende Record
|
||||||
|
:local RecordProxied "false" # WG-Endpoint: NICHT proxied
|
||||||
|
:local VerboseLog false
|
||||||
|
:local WanDhcpName "client1"
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Token aus /system script environment holen (NIE im Skriptkopf, NIE per :global).
|
||||||
|
# Grund (2026-10-03): :global cfDdnsToken liest im Skript-Kontext "nothing", obwohl
|
||||||
|
# /system script environment cfDdnsToken gesetzt ist. CLI-Scope und Skript-Scope sind
|
||||||
|
# auf RouterOS 7.24 unterschiedlich. `/system script environment get` ist scope-unabhaengig.
|
||||||
|
:do {
|
||||||
|
:local tk ""
|
||||||
|
:local found [/system script environment find name=cfDdnsToken]
|
||||||
|
:if ([:len $found] > 0) do={
|
||||||
|
:set tk [/system script environment get [find name=cfDdnsToken] value]
|
||||||
|
}
|
||||||
|
:if ([:typeof $tk] = "") do={
|
||||||
|
:log error "[tp10-ddns] cfDdnsToken nicht gesetzt - Abbruch"
|
||||||
|
:error "cfDdnsToken fehlt"
|
||||||
|
}
|
||||||
|
:global cfDdnsToken
|
||||||
|
:set cfDdnsToken $tk
|
||||||
|
} on-error={
|
||||||
|
:log error "[tp10-ddns] cfDdnsToken nicht lesbar - Abbruch"
|
||||||
|
:error "cfDdnsToken fehlt"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---- WAN-IPv4 aus der DHCP-Lease (Quelle: Liwest, kein Dritter) ------------
|
||||||
|
:local CFWanIP4New ""
|
||||||
|
:do {
|
||||||
|
:local leaseAddr [/ip dhcp-client get [find name=$WanDhcpName] address]
|
||||||
|
:if ([:typeof $leaseAddr] != "nothing") do={
|
||||||
|
# "90.146.33.177/24" -> "90.146.33.177"
|
||||||
|
:local slashPos [:find $leaseAddr "/"]
|
||||||
|
:if ($slashPos >= 0) do={
|
||||||
|
:set CFWanIP4New [:pick $leaseAddr 0 $slashPos]
|
||||||
|
} else={
|
||||||
|
:set CFWanIP4New $leaseAddr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} on-error={
|
||||||
|
:log error "[tp10-ddns] DHCP-Lease nicht lesbar ($WanDhcpName)"
|
||||||
|
}
|
||||||
|
|
||||||
|
:if ($CFWanIP4New = "") do={
|
||||||
|
:log warning "[tp10-ddns] Keine WAN-IP aus der Lease, naechster Lauf"
|
||||||
|
} else={
|
||||||
|
|
||||||
|
# ---- Guard: nur oeffentliche IPv4 zulassen --------------------------------
|
||||||
|
# Faengt den Fall ab, dass DHCP Muell liefert (privat/CGNAT) -> kein Write.
|
||||||
|
:local isPrivate false
|
||||||
|
:if ([:pick $CFWanIP4New 0 3] = "10.") do={ :set isPrivate true }
|
||||||
|
:if ([:pick $CFWanIP4New 0 8] = "192.168.") do={ :set isPrivate true }
|
||||||
|
:if ([:pick $CFWanIP4New 0 7] = "172.16.") do={ :set isPrivate true }
|
||||||
|
:if ([:pick $CFWanIP4New 0 8] = "100.64.0") do={ :set isPrivate true } # CGNAT 100.64/10
|
||||||
|
:if ($isPrivate) do={
|
||||||
|
:log error "[tp10-ddns] Lease liefert nicht-oeffentliche IP ($CFWanIP4New) - ABBRUCH, kein Write"
|
||||||
|
} else={
|
||||||
|
|
||||||
|
# ---- Nur bei Abweichung schreiben (Idempotenz) --------------------------
|
||||||
|
:global CFWanIP4Cur
|
||||||
|
:if ($CFWanIP4New != $CFWanIP4Cur) do={
|
||||||
|
:if ($VerboseLog) do={ :log info "[tp10-ddns] WAN-IP: $CFWanIP4Cur -> $CFWanIP4New" }
|
||||||
|
|
||||||
|
# Kommentar am Record: Zeit + Geraet, wie im Original
|
||||||
|
:local ds [/system clock get date]
|
||||||
|
:local ts [/system clock get time]
|
||||||
|
:local datetime ([:pick $ds 0 4] . "." . [:pick $ds 5 7] . "." . [:pick $ds 8 10] . "-" . [:pick $ts 0 2] . ":" . [:pick $ts 3 5])
|
||||||
|
:local CFComment ("$datetime by crs326-core")
|
||||||
|
|
||||||
|
:local url "https://api.cloudflare.com/client/v4/zones/$DnsZoneID/dns_records/$DnsRcrdID/"
|
||||||
|
:do {
|
||||||
|
:local res [/tool fetch http-method=put mode=https url=$url check-certificate=yes output=user as-value http-header-field="Authorization: Bearer $cfDdnsToken,Content-Type: application/json" http-data="{\"type\":\"A\",\"name\":\"$DnsRcName\",\"content\":\"$CFWanIP4New\",\"ttl\":$RecordTTL,\"proxied\":$RecordProxied,\"comment\":\"$CFComment\"}"]
|
||||||
|
:if (($res->"status") = "finished") do={
|
||||||
|
:log warning "[tp10-ddns] $DnsRcName -> $CFWanIP4New aktualisiert"
|
||||||
|
:set CFWanIP4Cur $CFWanIP4New
|
||||||
|
} else={
|
||||||
|
:log error "[tp10-ddns] Update fehlgeschlagen (status != finished)"
|
||||||
|
}
|
||||||
|
} on-error={
|
||||||
|
:log error "[tp10-ddns] Exception beim Cloudflare-Update - naechster Lauf"
|
||||||
|
}
|
||||||
|
} else={
|
||||||
|
:if ($VerboseLog) do={ :log info "[tp10-ddns] WAN-IP unveraendert ($CFWanIP4New)" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user