TP26: defconf-Firewall auf beiden APs abgeraeumt — --assert hat zwei Fehlschlaege gefangen

11 statische Werksregeln je AP entfernt (input-seal, fasttrack, ipsec, sogar
"accept to local loopback (for CAPsMAN)"). Ein reiner AP routet nicht; die
Regeln waren inert. Mgmt haengt an /ip service (TP16.1), nicht an der
input-Kette — kein Lockout-Risiko. ap2 danach: 2 Radios running, 7 Clients.

Der eigentliche Wert dieser Session steckt in den zwei Fehlschlaegen davor,
die --assert bei seinem ERSTEN echten Einsatz gefangen hat. Beide meldeten
"Plan-Status: Completed":

1. `remove [find]` erfasst die DYNAMISCHE Fasttrack-Dummy-Regel mit. RouterOS
   verweigert deren Entfernung, das ganze Kommando wirft, es wird NICHTS
   entfernt. Log: "tp26: remove warf".

2. Der naheliegende Fix `[find !dynamic]` ist ein SYNTAXFEHLER — korrekt ist
   `[find where !dynamic]`. Und Syntaxfehler schlagen beim Parsen zu:
   `:do {} on-error={}` faengt sie NICHT, der Handler laeuft nie. Symptom
   deshalb besonders tueckisch — kein Fehler im Log, keine Wirkung,
   Plan "Completed". Merkregel: on-error schuetzt vor Laufzeitfehlern,
   nicht vor Tippfehlern.

Ohne --assert waeren beide unbemerkt geblieben. Genau der Fehlermodus, den
Christoph mit "einstellungen werden nicht uebernommen, dir faellt das nicht
mal auf" benannt hat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-17 15:48:23 +02:00
parent 2f102b48de
commit b1ddd3574d

View File

@@ -0,0 +1,48 @@
# TP26 — defconf-Firewallregeln auf den APs abraeumen (User-Entscheid 2026-08-17).
#
# WARUM: ap1 und ap2 tragen je 12 Werksregeln (input-seal, fasttrack, zwei
# ipsec-Zeilen, und sogar "accept to local loopback (for CAPsMAN)"). Ein reiner
# AP routet nicht — er hat keine forward-Kette zu schuetzen und keinen Verkehr,
# der seine input-Kette passiert ausser Mgmt. Die Regeln sind inert.
#
# WARUM NICHT "als Sollzustand ins Template schreiben": das hiesse Werksmuell als
# Absicht in die SoT zu schreiben. Dasselbe Argument wie bei telnet/ftp in
# TP16.1 — nichts hier nutzt sie, also gehoeren sie weg und nicht dokumentiert.
#
# ⚠️ Der Mgmt-Zugang haengt NICHT an diesen Regeln: er wird von /ip service
# (address=10.40.0.0/16,100.96.0.0/12, TP16.1) geschuetzt, nicht von der
# input-Kette. Die Werksregel "drop all not coming from LAN" faellt weg,
# aber /ip service bleibt die wirksame ACL. Kein Lockout-Risiko.
#
# Idempotent: laeuft die Datei zweimal, passiert beim zweiten Mal nichts.
#
# 🔴 GOTCHA, im ersten Anlauf am 2026-08-17 getroffen: `remove [find]` erfasst
# auch die DYNAMISCHE Regel "special dummy rule to show fasttrack counters".
# RouterOS verweigert deren Entfernung, das GESAMTE Kommando wirft, und damit
# wird *nichts* entfernt — der Plan meldet trotzdem "Completed".
# Ist-Stand war: 12 gesamt = 11 statisch + 1 dynamisch.
# => dynamische Regeln muessen ausgefiltert werden. Gleiche Klasse wie der
# dokumentierte `bridge/vlan/set nur auf [find ... and !dynamic]` in CLAUDE.md.
#
# 🔴 ZWEITER GOTCHA, direkt danach: `[find !dynamic]` ist hier ein SYNTAXFEHLER.
# Korrekt ist `[find where !dynamic]`. Und Syntaxfehler schlagen beim PARSEN
# zu — `:do {} on-error={}` faengt sie NICHT, der Handler laeuft nie. Symptom
# ist deshalb besonders tueckisch: kein Fehler im Log, keine Wirkung, Plan
# "Completed". Merkregel: on-error schuetzt vor Laufzeitfehlern, nicht vor
# Tippfehlern.
#
# Beide Fehlschlaege hat --assert gefangen. Ohne die Pruefung waeren sie
# unbemerkt geblieben — der Plan-Status meldete jedes Mal "Completed".
#
# Push (BEIDE APs), mit maschineller Abnahme. Die Assertion filtert bewusst auf
# dynamic=false — die Dummy-Regel ist kein Rueckstand, sondern nicht entfernbar:
# python3 nautobot/gc-manual-plan.py --device ap1 \
# --commands-file routeros/tp26-ap-firewall-cleanup.rsc \
# --change-id TP26-fw-cleanup-ap1 --deploy \
# --assert '/ip/firewall/filter?dynamic=false|count=0'
#
# Backups davor: ap{1,2}-pre-tp26-20260817.backup
:do { /ip firewall filter remove [find where !dynamic] } on-error={ :log info "tp26: remove warf" }
:log info ("tp26: statisch-verbleibend=" . [:tostr [:len [/ip firewall filter find where !dynamic]]] . " dynamisch=" . [:tostr [:len [/ip firewall filter find where dynamic]]])