From b1ddd3574d01d97a863b50c5f7fbd1fc42eda560 Mon Sep 17 00:00:00 2001 From: Christoph Emsenhuber Date: Mon, 17 Aug 2026 15:48:23 +0200 Subject: [PATCH] =?UTF-8?q?TP26:=20defconf-Firewall=20auf=20beiden=20APs?= =?UTF-8?q?=20abgeraeumt=20=E2=80=94=20--assert=20hat=20zwei=20Fehlschlaeg?= =?UTF-8?q?e=20gefangen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- routeros/tp26-ap-firewall-cleanup.rsc | 48 +++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 routeros/tp26-ap-firewall-cleanup.rsc diff --git a/routeros/tp26-ap-firewall-cleanup.rsc b/routeros/tp26-ap-firewall-cleanup.rsc new file mode 100644 index 0000000..74d1fb5 --- /dev/null +++ b/routeros/tp26-ap-firewall-cleanup.rsc @@ -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]]])