# 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]]])