Files
bf-infra/routeros/tp28-ap3-phase2-cap.rsc
Christoph Emsenhuber 1006f91e6a TP28: ap3 (cAP ax) live als CAP, ap1 funkstill, Compliance 130/130 ueber 5 Geraete
Der dritte Access-Point laeuft: 10.40.99.13 auf vlan99, Uplink ether1 -> core ether21,
reiner CAP unter crs326-core, Kanaele 5180/ax/Ce/I und 2437/ax (ch6) -- am Geraet
nachgemessen, nicht aus dem Plan abgeschrieben. Der Kanalplan stammt aus TP25 vom
2026-08-24; mein erster Entwurf hatte ihn neu erfunden und waere bei ch1 statt ch6
gelandet. Lehre: den TP-Body lesen, nicht nur den Quick-Index.

ap1 hat bewusst KEINE Provisioning-Regel mehr: es steht bis zu seinem Umzug ans
Sideboard direkt neben ap3 und wuerde auf 5180 kollidieren. Geraet bleibt erreichbar,
die Objekte ch-*-ap1 / cfg-main-*-ap1 bleiben fuer den Umzug stehen.

Bring-up in zwei Phasen ueber ein Patchkabel ap3 ether2 -> core ether22, weil ueber
ether1 nichts ging (s.u.). Loop-Schutz: ether21 war waehrend Phase 1 abgeschaltet und
wurde im selben Befehl gegen ether22 getauscht. RouterOS 7.20.8 -> 7.24.1 plus
RouterBOOT (zwei Reboots, TP27-Kriterium erfuellt). Die anderen vier stehen auf 7.24 --
die Angleichung ist ein eigener Durchgang, der Core-Reboot ist ein Standort-Ausfall.

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 physisch aber in Technik UG (User-Bestaetigung).

Sechs Funde, alle als Gotcha in CLAUDE.md und im Handoff:
- ether1 ist am Werksgeraet WAN: Discovery aus, Input-TCP verworfen, ICMP aber erlaubt.
  Es pingt, und das liest sich wie "erreichbar". MikroMCP hilft nicht -- Port 80 ist zu.
- pvid ist Ingress, tagged/untagged ist Egress. Ein Lease hing ewig auf "offered", weil
  der ACK getaggt rausging und ein Werksgeraet das nicht versteht.
- `cap enabled=yes` reicht nicht: jedes Master-Radio braucht configuration.manager=capsman,
  sonst bietet der CAP seine Radios gar nicht an -- state=Ok, radio-Tabelle leer.
- Ein Geraet ohne secrets_group erzeugt eine LUECKE, keine Fehlermeldung: Backup scheitert
  still, keine Compliance-Eintraege, Zahl bleibt unauffaellig bei 104/104. Eine
  gleichbleibende Compliance-Zahl nach dem Hinzufuegen eines Geraets ist ein BEFUND.
- CAPsMAN verteilt keine Login-Passwoerter, nur WLAN-PSKs. Der Geraete-Login ist eine
  lokale DB pro Geraet; das einheitliche Admin-PW ist eine Konvention von Hand.
- Firewall-Regelnummern aus `print where` sind Handles, keine Positionen. Beweis ist der
  Zaehler, nicht die Zahl.

Abnahme: 3 CAPs state=Ok, VAP-Satz vollstaendig und running, 20 IOT-Clients auf ap3 mit
0 % Ping-Verlust ueber VLAN30 (bewusst nicht ueber die Registration-Table abgenommen),
Compliance 130/130 / 0 Drifts, Core-Temp-Pfad restlos abgeraeumt.

Offen: TP25-Messrunde (braucht Rundgang), PW-Rotation TP30, MikroMCP-Neustart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 17:54:07 +02:00

81 lines
5.2 KiB
Plaintext

# =====================================================================================
# ap3 (cAP ax) — PHASE 2: aus dem Standalone-Werksgeraet einen reinen CAP machen.
# TP28-Nachtrag, 2026-08-30.
#
# LAEUFT UEBER vlan99 (10.40.99.13), NICHT ueber das Werks-WLAN -- denn hier stirbt das
# Werks-WLAN. Erst ausfuehren, wenn `ping 10.40.99.13` vom Core sauber durchgeht.
# =====================================================================================
# --- (1) Werks-WLAN und Standalone-Reste abraeumen.
# 🔴 REIHENFOLGE IST PFLICHT: `configuration` referenziert security/datapath/channel.
# Wer die Referenzierten zuerst loescht, bekommt einen Fehler und laesst einen
# Teil-Zustand zurueck.
# 🔴 `[find !dynamic]` waere hier ein SYNTAXFEHLER -- diese Objekte haben gar keine
# `dynamic`-Eigenschaft, die gibt es nur auf /interface wifi selbst. Ein frueherer
# Versuch lief deshalb komplett in die on-error-Zweige, aenderte NICHTS und meldete
# trotzdem Erfolg (Lehre aus tp28-ap-wifi-reste-abraeumen.rsc, 2026-08-18).
/interface wifi capsman set enabled=no
/interface wifi remove [find where !(name=wifi1 || name=wifi2)]
/interface wifi configuration remove [find]
/interface wifi steering remove [find]
/interface wifi security remove [find]
/interface wifi datapath remove [find]
/interface wifi channel remove [find]
# Werks-Inline-Overrides auf den Master-Radios loeschen, sonst gewinnen sie gegen den Manager.
/interface wifi set [find name=wifi1] !configuration.ssid !security.authentication-types !security.passphrase !security.ft-over-ds
/interface wifi set [find name=wifi2] !configuration.ssid !security.authentication-types !security.passphrase !security.ft-over-ds
# --- (2) L3-Reste des Werks-Routers weg (jetzt gefahrlos: die WLAN-Sitzung ist ohnehin tot) ---
/ip dhcp-server remove [find]
/ip dhcp-server network remove [find]
/ip pool remove [find]
/ip firewall nat remove [find]
/ipv6 dhcp-client remove [find]
/ip address remove [find where interface=bridge]
# --- (3) Bridge-Ports. cAP ax hat nur ZWEI Ethernet-Ports; ether2 traegt PoE-out und
# haengt nichts -> aus, wie ap1/ap2 es mit ihrem PoE-Port halten. ether2 wird
# KEIN Bridge-Port (Zielzustand identisch zu ap2) -> ap.extra_ports = [].
/interface ethernet set [find name=ether2] poe-out=off
/interface bridge port remove [find where interface=ether2]
:if ([:len [/interface bridge port find where interface=wifi1]]=0) do={ /interface bridge port add bridge=bridge comment=defconf interface=wifi1 }
:if ([:len [/interface bridge port find where interface=wifi2]]=0) do={ /interface bridge port add bridge=bridge comment=defconf interface=wifi2 }
# --- (4) Bridge-VLAN-Tabelle, Muster = ap2 live (2026-08-30 gelesen).
# IOT (30) nur auf wifi2: die Zone hat bands=["2g"] (ConfigContext ap-common).
# MGMT (99) liegt auf der Bridge, NICHT auf den Radios -- sonst waere Management
# over-the-air.
/interface bridge vlan remove [find where !dynamic]
/interface bridge vlan add bridge=bridge untagged=bridge,ether1 vlan-ids=1
/interface bridge vlan add bridge=bridge tagged=ether1,wifi1,wifi2 vlan-ids=10
/interface bridge vlan add bridge=bridge tagged=ether1,wifi1,wifi2 vlan-ids=20
/interface bridge vlan add bridge=bridge tagged=ether1,wifi2 vlan-ids=30
/interface bridge vlan add bridge=bridge tagged=ether1,wifi1,wifi2 vlan-ids=40
/interface bridge vlan add bridge=bridge tagged=ether1,wifi1,wifi2 vlan-ids=50
/interface bridge vlan add bridge=bridge tagged=ether1,wifi1,wifi2 vlan-ids=90
/interface bridge vlan add bridge=bridge tagged=ether1,bridge vlan-ids=99
# --- (5) CAP-Modus.
# 🔴🔴 `slaves-datapath` IST NICHT OPTIONAL. Der Manager schickt `datapath.bridge=bridge`
# zwar mit, der CAP uebernimmt davon aber NUR die vlan-id -- die Bridge-Mitgliedschaft
# bleibt lokal. Fehlt das Objekt, assoziieren Clients auf iot/media/untrusted/guest
# sauber und bekommen NIE DHCP, waehrend dirtyvader-main (Master-Radios = statische
# Bridge-Ports) weiterlaeuft. Genau so lagen IOT+MEDIA am 2026-08-18 rund 14 Stunden.
# Das Objekt traegt bewusst KEINE vlan-id: die liefert der Manager pro VAP.
/interface wifi datapath add name=dp-caps-slaves bridge=bridge comment="TP28-fix: bridge fuer CAPsMAN-Slave-VAPs"
/interface wifi cap set enabled=yes discovery-interfaces=vlan99 slaves-datapath=dp-caps-slaves
# 🔴 `cap enabled=yes` REICHT NICHT. Jedes Master-Radio muss zusaetzlich selbst auf
# `configuration.manager=capsman` stehen, sonst BIETET der CAP seine Radios dem
# Manager gar nicht an. Symptom (2026-08-30 live aufgeschlagen): `remote-cap print`
# zeigt `state=Ok`, aber `/interface wifi radio print` am Manager listet fuer dieses
# Geraet NICHTS -- und weil die Provisioning-Regel dann nicht matcht, sucht man den
# Fehler in der radio-mac statt an dieser Stelle. ap1/ap2 tragen es seit dem
# TP28-Cutover, im Werkszustand ist es leer (= local).
/interface wifi set [find name=wifi1] configuration.manager=capsman
/interface wifi set [find name=wifi2] configuration.manager=capsman
# --- (6) ZULETZT scharf schalten. Vorher waere der Rest der Datei nicht angekommen. ---
/interface bridge set [find name=bridge] vlan-filtering=yes
:log info "tp28-ap3 phase2: CAP aktiv, Manager-Suche auf vlan99, vlan-filtering=yes"