Initial import from bf-network-r6.opencode — opencode migration
This commit is contained in:
63
routeros/HANDOVER-wifi.md
Normal file
63
routeros/HANDOVER-wifi.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Übergabe-Prompt: hAP ax² WLAN/CAPsMAN-Setup (BF)
|
||||
|
||||
```
|
||||
Du übernimmst die WLAN-Einrichtung von zwei MikroTik hAP ax². ARBEITE DOKU-GEGRÜNDET
|
||||
(MikroTik RouterOS 7 "wifi"/CAPsMAN, help.mikrotik.com) — KEINE Trial-and-Error-Schleifen.
|
||||
Lies ZUERST die Doku zu: /interface/wifi, CAPsMAN, configuration, datapath, security,
|
||||
channel, provisioning. Verstehe das "bound"-Konzept, BEVOR du etwas änderst.
|
||||
|
||||
ZIEL
|
||||
- ap1 = CAPsMAN-Manager + AP, ap2 = CAP (zieht Config von ap1).
|
||||
- Erst ein TEST-WLAN auf dem aktuellen FLAT-Netz (Bridge, KEIN VLAN), SSID "BF-Main"
|
||||
(Name egal). Verifiziere: Client verbindet, Roaming ap1<->ap2.
|
||||
- Bänder: wifi1 = 5 GHz (5ghz-ax), wifi2 = 2,4 GHz (2ghz-ax) — verifiziert.
|
||||
- WPA3-only für BF-Main ist gewünscht/ok. Country = Austria. Temp-Passphrase (User
|
||||
setzt echte später), z.B. "BFtest-2026-tmp".
|
||||
|
||||
ZUGANG
|
||||
- ap1 = 10.40.41.1, ap2 = 10.40.41.2. user=admin pw=46484b9952#P
|
||||
- REST über HTTP funktioniert: curl -s -u 'admin:46484b9952#P' http://10.40.41.1/rest/interface/wifi
|
||||
ACHTUNG: nested-set via REST ({"channel":{"band":..}} bzw. "channel.band") hat beim
|
||||
Vorgänger NICHT zuverlässig gegriffen (kam als None zurück). Lieber SSH/CLI ODER
|
||||
korrekten REST-Pfad aus der Doku verifizieren.
|
||||
- SSH geht (1. Login fragt "software license? [Y/n]" -> n). Tools: telnet/expect (macOS).
|
||||
Python 3.14 hat KEIN telnetlib.
|
||||
|
||||
STAND
|
||||
- Beide auf RouterOS 7.23.1 + RouterBOOT 7.23.1, Identity ap1/ap2, Mgmt-IP .1/.2 auf der
|
||||
Bridge (untagged vlan1). Default-Bridge (ether2-5 + wifi). ether1=WAN ungenutzt. Uplink=ether2.
|
||||
|
||||
DAS PROBLEM (Kern!)
|
||||
- Vorgänger hat CAPsMAN halb aufgesetzt (auf ap1: security/datapath/configuration/
|
||||
provisioning; auf ap2: cap). Kopplung lief (ap2 bei ap1 registriert, state=Ok).
|
||||
- ABER die wifi-Interfaces sind "bound=true" (CAPsMAN-gebunden) -> lokale
|
||||
`set channel.band/configuration.*` werden IGNORIERT -> channel=None, running=false,
|
||||
es funkt NICHTS. Auch nach `capsman/cap disable` + `provisioning remove` blieb bound=true.
|
||||
- VERMUTUNG (DOKU PRÜFEN!): Im CAPsMAN-Modell gehört Band/Kanal in die configuration bzw.
|
||||
in ein /interface/wifi/channel-Profil + provisioning mit supported-bands (je Radio das
|
||||
passende Config). cfg-test hatte KEINEN Kanal -> gebundene Interfaces ohne Kanal -> aus.
|
||||
Klär aus der Doku: wie löst man "bound" sauber (ggf. komplettes Reset der wifi-Config,
|
||||
ggf. Reboot/Power-Cycle), und wie setzt man Band/Kanal im CAPsMAN-Modell korrekt.
|
||||
|
||||
ZU TUN
|
||||
1. wifi-Config sauber entwirren (bound lösen). Sauberer Reset ODER korrekt über CAPsMAN.
|
||||
2. Test-WLAN BF-Main hochbringen (beide Bänder, beide APs, gleiche SSID), Client testen,
|
||||
Roaming testen. (Standalone-inline ist erlaubt, falls CAPsMAN für den Schnelltest zickt
|
||||
— User will aber eigentlich CAPsMAN: ap2 zieht von ap1.)
|
||||
3. ERST danach SSID->VLAN (datapath vlan-id) — nutzbar aber erst NACH Router-Cutover.
|
||||
|
||||
CONSTRAINTS / SAFETY
|
||||
- HEUTE/aktuell NICHTS Riskantes, KEIN Router-Cutover. Nur WLAN-Test.
|
||||
- APs tragen noch keinen Haushalts-Traffic; das Hauptnetz läuft über die FritzBox (unberührt).
|
||||
- User ist ein paar Tage außer Haus, arbeitet remote mit. Beide APs an SCHALTBAREN
|
||||
Steckdosen (Remote-Not-Aus) -> bei riskanten Änderungen IMMER Auto-Rückfall-Timer setzen
|
||||
(/system scheduler, der nach X Min zurückstellt, außer du bestätigst).
|
||||
- Mgmt der APs (.1/.2 auf Bridge/vlan1) NICHT aussperren.
|
||||
|
||||
KONTEXT/REPO
|
||||
- ~/dev/bf-network-r6/ : Gesamt-Übergabe HANDOVER.md, VLAN-Plan docs/vlan-plan.md,
|
||||
geplante (noch NICHT verifiziert korrekte) Configs routeros/ap1-manager.rsc / ap2-cap.rsc,
|
||||
IP-Plan: .1-10 Router/APs, .11-20 Switches; VLANs 10/20/30/40/90/99/100.
|
||||
|
||||
ERWARTUNG: präzise nach Doku, keine Rate-Schleifen. Bei Unklarheit: Doku-Stelle nennen, dann handeln.
|
||||
```
|
||||
54
routeros/README.md
Normal file
54
routeros/README.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# hAP ax² Setup — CAPsMAN + VLAN (Design & Plan, REVIEW vor Apply)
|
||||
|
||||
Stand: beide auf RouterOS **7.23.1** + RouterBOOT 7.23.1. Namen/IPs gesetzt:
|
||||
**ap1 = 10.40.41.1** (künftiges Gateway/Router) · **ap2 = 10.40.41.2** (CAP). Default-Bridge (ether2–5+wifi, vlan-filtering aus).
|
||||
|
||||
> ⚠️ **Status: NUR PLAN.** An den Geräten bisher nur: Firmware 7.23.1, Identity ap1/ap2, Stray-IP weg, **Mgmt-IP→.1/.2**.
|
||||
> Exakte 7.23-Syntax (wifi/capsman/provisioning/scheduler) wird **vor Apply gegen das Gerät validiert**.
|
||||
|
||||
## Hardware-Realität
|
||||
- **WiFi 6 (ax)**, dual-band 2,4+5 GHz. **MLO ist NICHT verfügbar** (MLO = WiFi 7/802.11be → bräuchte hAP be³). „MLO wenn möglich" entfällt.
|
||||
|
||||
## Rollen
|
||||
- **ap1 = CAPsMAN-Manager + AP** (später zusätzlich **Router** — L3/DHCP/DNS/NAT/CAKE = **separater Cutover**, NICHT hier).
|
||||
- **ap2 = CAP** (zieht Wireless-Config von ap1 @ 10.40.41.1).
|
||||
|
||||
## ⚠️ Topologie / Verkabelung (Klärungsbedarf)
|
||||
- **ap1** → **Core-Switch Port 2** (direkt). ✓ Guter Trunk-Kandidat.
|
||||
- **ap2** → hinter **TP-Link TL-SG108E** → Core-Switch **Port 8**. Damit ap2 die VLANs **getaggt** bekommt, müsste **auch der TP-Link trunken** (kann 802.1Q, aber fummelige UI). **Empfehlung:** ap2 im Wartungsfenster **direkt an einen freien Core-Port** (z.B. Port 3) → sauberer Trunk, keine TP-Link-VLAN-Config.
|
||||
- **ether1 = WAN — Achtung:** Für **ap1 (Router)** ist ether1 = **WAN zur FB** (Internet); der **LAN-Trunk** zum Core bleibt **ether2** → ap1 braucht **2 Kabel**. Für **ap2 (reiner AP)** gibt es kein WAN; **ein** Uplink (Trunk) genügt. → Den LAN-Trunk auf ether1 zu legen wäre für den Router falsch. **Finale Verkabelung bitte bestätigen.**
|
||||
|
||||
## Bridge-VLAN-Layout (beide APs)
|
||||
- **Uplink ether2 = Trunk:** tagged `10,20,30,40,90,99,100` **+ native/untagged vlan1** (= aktuelles Mgmt-Netz, .1/.2).
|
||||
- **Mgmt bleibt erreichbar** (untagged vlan1), solange der Switch-Port native vlan1 untagged bleibt.
|
||||
- `vlan-filtering=yes` zuletzt — mit **Auto-Rollback** (5 min) gegen Lockout.
|
||||
|
||||
## WLAN (SSID → VLAN via CAPsMAN-Datapath)
|
||||
| SSID | VLAN | Security |
|
||||
|---|---|---|
|
||||
| `BF-Main` | 10 (MAIN) | **WPA3-only** |
|
||||
| `BF-IoT` | 30 (IOT) | WPA2/WPA3-PSK |
|
||||
| `BF-Guest` | 90 (GUEST) | WPA2/WPA3-PSK |
|
||||
Beide Bänder (2,4+5 GHz ax). **Temp-Passphrase** (Platzhalter `BFtest-2026-tmp`) — User setzt echte in Ruhe.
|
||||
|
||||
> VLAN-SSIDs bekommen erst **nach dem Router-Cutover** DHCP/Gateway. Sofort-Test optional via Temp-SSID auf **native vlan1** (FB-DHCP).
|
||||
|
||||
## Apply-Reihenfolge (wenn freigegeben)
|
||||
1. **Switch:** AP-Uplink-Port(s) → Trunk (tagged 10,20,30,40,90,99,100 + native vlan1). [ap2 erst sinnvoll, wenn direkt am Core ODER TP-Link trunkt]
|
||||
2. **ap1:** Bridge-VLAN → CAPsMAN-Manager → (Auto-Rollback) vlan-filtering=yes.
|
||||
3. **ap2:** Bridge-VLAN → CAP enable (manager=10.40.41.1).
|
||||
4. Verifizieren: ap2 im Manager; SSIDs auf beiden Radios; Mgmt erreichbar. Rollback canceln.
|
||||
|
||||
## Safety — Auto-Rollback
|
||||
```
|
||||
/system scheduler add name=vlan-rollback interval=5m \
|
||||
on-event="/interface bridge set [find name=bridge] vlan-filtering=no; /system scheduler remove vlan-rollback"
|
||||
```
|
||||
|
||||
## Offene Punkte (User)
|
||||
- Finale Verkabelung bestätigen (ap1: ether1→FB-WAN, ether2→Core-Trunk; ap2: direkt an Core vs. TP-Link trunken).
|
||||
- Switch-Mgmt-IP: `.3` oder `.239` (da `.2` jetzt = ap2).
|
||||
- Echte WLAN-Passphrasen (später).
|
||||
|
||||
## Dateien
|
||||
- `routeros/ap1-manager.rsc` · `routeros/ap2-cap.rsc`
|
||||
10
routeros/ap1-cutover-summary.txt
Normal file
10
routeros/ap1-cutover-summary.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
ap1 Cutover-Export vom 2026-08-05T22:44:30+02:00
|
||||
DHCP-Leases gesamt: 59
|
||||
statisch (dynamic=no): 54
|
||||
dynamisch: 5
|
||||
WG-Hub private-key erfasst: ja
|
||||
|
||||
Nächste Schritte im Cutover-Fenster:
|
||||
1. ap1-leases-export.json filtern: nur dynamic=no, server-Namen auf core dhcp-v10..v99 mappen.
|
||||
2. ap1-wg-hub.privkey in core-Config einsetzen (ersetzt <<< AP1_WG_HUB_PRIVKEY >>>).
|
||||
3. Generate Intended Config für crs326-core erneut laufen lassen -> Nautobot-Deployment.
|
||||
1266
routeros/ap1-leases-export.json
Normal file
1266
routeros/ap1-leases-export.json
Normal file
File diff suppressed because it is too large
Load Diff
59
routeros/ap1-leases-to-core.rsc
Normal file
59
routeros/ap1-leases-to-core.rsc
Normal file
@@ -0,0 +1,59 @@
|
||||
# ap1 static leases -> crs326-core (STAGED, disabled=yes)
|
||||
# Quelle: ap1-leases-export.json | 54 statische Leases
|
||||
|
||||
/ip/dhcp-server/lease add server=dhcp-v10 mac-address="F2:62:4C:E1:AF:09" address="10.40.10.196" client-id="1:f2:62:4c:e1:af:9" comment="iPhone" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v10 mac-address="56:71:6C:22:E6:A9" address="10.40.10.82" client-id="1:56:71:6c:22:e6:a9" dhcp-option='dns 1.1.1.1' comment="Mac" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v20 mac-address="90:09:D0:58:20:F9" address="10.40.20.10" comment="nas-bf" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="FC:EE:11:03:32:26" address="10.40.30.150" client-id="1:fc:ee:11:3:32:26" comment="ingenic-3226 / Ender3V3KE-3226" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="E4:BC:96:1F:B2:81" address="10.40.30.180" client-id="1:e4:bc:96:1f:b2:81" dhcp-option='dns 1.1.1.1' comment="espressif / Airfryer" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="A0:85:E3:C8:65:34" address="10.40.30.202" comment="shelly-s22_kueche_steckdose3-2" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="AC:15:18:7B:62:20" address="10.40.30.203" comment="shelly-s23_dieleug-wohnzimmer_licht" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="14:33:5C:D8:2D:7C" address="10.40.30.204" comment="shelly-s24_bad_spiegelschrank" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="98:A3:16:79:38:50" address="10.40.30.205" comment="shelly-s25_bad_lichtschalter" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="98:A3:16:7C:5F:EC" address="10.40.30.206" comment="shelly-s20_kueche_steckdosen2" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="20:6E:F1:01:F9:F8" address="10.40.30.207" comment="shelly-s21_kueche_steckdosen4" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="E4:B0:63:D7:C7:A4" address="10.40.30.208" comment="shelly-s1_weihnachten_kueche" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="28:37:2F:36:F4:7C" address="10.40.30.209" comment="shelly-s2_weihnachten_terrasse" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="E4:B0:63:E4:EF:7C" address="10.40.30.210" comment="shelly-s3_weihnachten_kinderzimmer" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="E4:B0:63:E4:0F:30" address="10.40.30.211" comment="shelly-s4_kueche_mikrowelle" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="D8:85:AC:0C:5C:C8" address="10.40.30.212" comment="shelly-s5_kueche_backofen" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="D0:CF:13:D8:18:FC" address="10.40.30.213" comment="shelly-s6_kueche_kuehlschrank" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="D0:CF:13:D9:94:E8" address="10.40.30.214" comment="shelly-s7_kueche_tiefkuehlschrank" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="E4:B0:63:FA:FD:E0" address="10.40.30.215" comment="shelly-s8_kueche_geschirrspueler" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="E8:F6:0A:61:88:08" address="10.40.30.216" comment="shelly-s9_wohnzimmer_sideboard" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="E4:B0:63:FC:57:E4" address="10.40.30.217" comment="shelly-s10_bad_sonos" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="E4:B0:63:FA:6C:00" address="10.40.30.218" comment="shelly-s11_kinderzimmer_sonos" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="48:F6:EE:C8:E6:AC" address="10.40.30.219" comment="shelly-s12_dieleug_steckdosen" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="48:F6:EE:DD:6A:F4" address="10.40.30.220" comment="shelly-s13_arbeitszimmer_technik" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="E4:B0:63:FC:59:48" address="10.40.30.221" comment="shelly-s14_schlafzimmer_bett" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="E4:B0:63:FA:D5:34" address="10.40.30.222" comment="shelly-s15_technik_pve" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="10:20:BA:FA:F5:40" address="10.40.30.223" comment="shelly-s16_wohnzimmer_steckdosen" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="10:20:BA:FB:6D:64" address="10.40.30.224" comment="shelly-s17_bad_steckdosen" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="48:F6:EE:CC:16:E4" address="10.40.30.225" comment="shelly-s18_kueche_steckdosen1" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="10:20:BA:FB:70:FC" address="10.40.30.226" comment="shelly-s19_kueche_steckdosen3" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="B8:F8:62:09:F2:04" address="10.40.30.227" comment="SwitchBot-floor-lamp / switchbot-floorlamp" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="98:F4:AB:2C:A7:88" address="10.40.30.228" comment="Twinkly-2CA789 / Twinkly_Weihnachtsgirlande" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="00:24:E4:40:2A:72" address="10.40.30.230" comment="Withings_waage" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="A4:7E:FA:18:2C:64" address="10.40.30.231" comment="Withings_blutdruck" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="BC:24:11:8E:0A:57" address="10.40.30.232" comment="pve-homematic-raspi-ccu" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="98:A3:16:7A:A3:54" address="10.40.30.233" comment="shelly-s26_bad_luefter" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="A4:F0:0F:5F:D0:EC" address="10.40.30.236" comment="lichterkette" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="24:DC:C3:9B:89:64" address="10.40.30.237" comment="lichterkette-mini" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="28:DB:A7:09:7B:54" address="10.40.30.241" comment="NukiSmartlock" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="24:62:AB:B1:63:F4" address="10.40.30.244" comment="NukiBridge" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="4C:EB:BD:E3:25:F2" address="10.40.30.5" comment="P750W / P750W" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v30 mac-address="54:F2:9F:12:51:F0" address="10.40.30.8" comment="DTUBI-414392337823 / DTUBI-414392337823" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v40 mac-address="70:AF:24:B8:C9:86" address="10.40.40.11" comment="tv" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v40 mac-address="34:7E:5C:32:37:96" address="10.40.40.191" client-id="1:34:7e:5c:32:37:96" comment="SonosZP" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v40 mac-address="34:7E:5C:32:33:B8" address="10.40.40.192" client-id="1:34:7e:5c:32:33:b8" comment="SonosZP" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v40 mac-address="78:28:CA:80:2A:F6" address="10.40.40.193" client-id="1:78:28:ca:80:2a:f6" comment="SonosZP" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v40 mac-address="48:A6:B8:14:FE:D0" address="10.40.40.194" client-id="1:48:a6:b8:14:fe:d0" comment="SonosZP" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v40 mac-address="78:28:CA:82:16:C2" address="10.40.40.195" client-id="1:78:28:ca:82:16:c2" comment="SonosZP" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v40 mac-address="48:A6:B8:16:38:AE" address="10.40.40.196" client-id="1:48:a6:b8:16:38:ae" comment="SonosZP" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v40 mac-address="48:A6:B8:14:FE:F2" address="10.40.40.197" client-id="1:48:a6:b8:14:fe:f2" comment="SonosZP" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v40 mac-address="78:28:CA:D2:0D:AC" address="10.40.40.198" comment="SonosZP / SonosTerrasse" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v40 mac-address="48:A6:B8:0B:63:10" address="10.40.40.199" client-id="1:48:a6:b8:b:63:10" comment="SonosZP" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v40 mac-address="48:A6:B8:69:69:7B" address="10.40.40.200" client-id="1:48:a6:b8:69:69:7b" comment="SonosZP" disabled=yes
|
||||
/ip/dhcp-server/lease add server=dhcp-v40 mac-address="94:9F:3E:49:59:EE" address="10.40.40.201" client-id="1:94:9f:3e:49:59:ee" comment="SonosZP" disabled=yes
|
||||
|
||||
# Cutover: /ip/dhcp-server/lease/enable [find comment~"ap1 lease"]
|
||||
BIN
routeros/ap1-pre-core-cutover-20260806-041627.backup
Normal file
BIN
routeros/ap1-pre-core-cutover-20260806-041627.backup
Normal file
Binary file not shown.
558
routeros/ap1-pre-core-cutover-20260806-041627.rsc
Normal file
558
routeros/ap1-pre-core-cutover-20260806-041627.rsc
Normal file
@@ -0,0 +1,558 @@
|
||||
# 2026-08-06 06:16:12 by RouterOS 7.23.2
|
||||
# software id = 2ATI-ZRRH
|
||||
#
|
||||
# model = C52iG-5HaxD2HaxD
|
||||
# serial number = HM70BFZBYVQ
|
||||
/interface bridge
|
||||
add admin-mac=D0:EA:11:4D:40:E1 auto-mac=no comment=defconf name=bridge \
|
||||
vlan-filtering=yes
|
||||
/interface wireguard
|
||||
add comment="TP10 Multi-Site VPN Hub (FM/DW spokes). Kein IP aufs IF (Routing \
|
||||
via AllowedIPs/Routes)." listen-port=51821 mtu=1412 name=wg-hub
|
||||
/interface vlan
|
||||
add comment="MAIN 10.40.10.0/24" interface=bridge name=vlan10 vlan-id=10
|
||||
add comment="INFRA 10.40.20.0/24" interface=bridge name=vlan20 vlan-id=20
|
||||
add comment="IOT 10.40.30.0/24" interface=bridge name=vlan30 vlan-id=30
|
||||
add comment="MEDIA 10.40.40.0/24" interface=bridge name=vlan40 vlan-id=40
|
||||
add comment="UNTRUSTED 10.40.50.0/24" interface=bridge name=vlan50 vlan-id=50
|
||||
add comment="GUEST 10.40.90.0/24" interface=bridge name=vlan90 vlan-id=90
|
||||
add comment="MGMT 10.40.99.0/24" interface=bridge name=vlan99 vlan-id=99
|
||||
add comment="WAN Arris (Liwest)" interface=bridge name=vlan100 vlan-id=100
|
||||
/interface list
|
||||
add comment=defconf name=WAN
|
||||
add comment=defconf name=LAN
|
||||
/interface wifi channel
|
||||
add band=2ghz-ax disabled=no frequency=2462 name=ch-2g width=20mhz
|
||||
add band=5ghz-ax disabled=no frequency=5745 name=ch-5g skip-dfs-channels=\
|
||||
10min-cac width=20/40/80mhz
|
||||
/interface wifi datapath
|
||||
add bridge=bridge name=dp-main vlan-id=10
|
||||
add bridge=bridge name=dp-iot vlan-id=30
|
||||
add bridge=bridge name=dp-media vlan-id=40
|
||||
add bridge=bridge name=dp-untrusted vlan-id=50
|
||||
add bridge=bridge name=dp-guest vlan-id=90
|
||||
add bridge=bridge name=dp-infra vlan-id=20
|
||||
/interface wifi security
|
||||
add authentication-types=wpa3-psk disabled=no ft=yes ft-over-ds=yes name=\
|
||||
sec-main
|
||||
add authentication-types=wpa2-psk,wpa3-psk disabled=no ft=no name=sec-iot
|
||||
add authentication-types=wpa2-psk,wpa3-psk disabled=no ft=no ft-over-ds=no \
|
||||
name=sec-media
|
||||
add authentication-types=wpa2-psk,wpa3-psk disabled=no ft=no name=\
|
||||
sec-untrusted
|
||||
add authentication-types=wpa2-psk,wpa3-psk ft=yes ft-over-ds=yes name=\
|
||||
sec-guest
|
||||
add authentication-types=wpa2-psk,wpa3-psk ft=no name=sec-infra
|
||||
/interface wifi configuration
|
||||
add country=Austria disabled=no mode=ap name=cfg-main-2g security=sec-main \
|
||||
ssid=dirtyvader-main tx-power=20
|
||||
add country=Austria datapath=dp-iot mode=ap multicast-enhance=enabled name=\
|
||||
cfg-iot security=sec-iot ssid=dirtyvader-iot
|
||||
add country=Austria datapath=dp-media mode=ap multicast-enhance=enabled name=\
|
||||
cfg-media security=sec-media ssid=dirtyvader-media
|
||||
add country=Austria datapath=dp-untrusted mode=ap name=cfg-untrusted \
|
||||
security=sec-untrusted ssid=dirtyvader-untrusted
|
||||
add country=Austria datapath=dp-guest mode=ap name=cfg-guest security=\
|
||||
sec-guest ssid=dirtyvader-guest
|
||||
add country=Austria datapath=dp-infra mode=ap name=cfg-infra security=\
|
||||
sec-infra ssid=dirtyvader-infra
|
||||
/interface wifi
|
||||
set [ find default-name=wifi2 ] channel.frequency=2412 configuration=\
|
||||
cfg-main-2g configuration.manager=local disabled=no
|
||||
add configuration=cfg-guest disabled=no mac-address=D2:EA:11:4D:40:EB \
|
||||
master-interface=wifi2 name=w2-guest
|
||||
add configuration=cfg-iot disabled=no mac-address=D2:EA:11:4D:40:E8 \
|
||||
master-interface=wifi2 name=w2-iot
|
||||
add configuration=cfg-media disabled=no mac-address=D2:EA:11:4D:40:E9 \
|
||||
master-interface=wifi2 name=w2-media
|
||||
add configuration=cfg-untrusted disabled=no mac-address=D2:EA:11:4D:40:EA \
|
||||
master-interface=wifi2 name=w2-untrusted
|
||||
/interface wifi steering
|
||||
add name=st-main neighbor-group=bf-main rrm=yes wnm=yes
|
||||
/interface wifi configuration
|
||||
add channel=ch-5g country=Austria datapath=dp-main mode=ap name=cfg-main-5g \
|
||||
security=sec-main ssid=dirtyvader-main steering=st-main
|
||||
/interface wifi
|
||||
set [ find default-name=wifi1 ] channel.frequency=5180 configuration=\
|
||||
cfg-main-5g configuration.manager=local disabled=no
|
||||
add configuration=cfg-guest disabled=no mac-address=D2:EA:11:4D:40:E7 \
|
||||
master-interface=wifi1 name=w5-guest
|
||||
add configuration=cfg-media disabled=no mac-address=D2:EA:11:4D:40:E5 \
|
||||
master-interface=wifi1 name=w5-media
|
||||
add configuration=cfg-untrusted disabled=no mac-address=D2:EA:11:4D:40:E6 \
|
||||
master-interface=wifi1 name=w5-untrusted
|
||||
/ip dhcp-server option
|
||||
add code=6 name="dns 1.1.1.1" value=0x01010101
|
||||
add code=138 name=omada-inform value=0x0A2814AF
|
||||
/ip pool
|
||||
add name=default-dhcp ranges=192.168.88.10-192.168.88.254
|
||||
add name=pool-v10 ranges=10.40.10.100-10.40.10.200
|
||||
add name=pool-v20 ranges=10.40.20.100-10.40.20.200
|
||||
add name=pool-v30 ranges=10.40.30.100-10.40.30.250
|
||||
add name=pool-v40 ranges=10.40.40.100-10.40.40.200
|
||||
add name=pool-v50 ranges=10.40.50.100-10.40.50.200
|
||||
add name=pool-v90 ranges=10.40.90.100-10.40.90.200
|
||||
add name=pool-v99 ranges=10.40.99.100-10.40.99.200
|
||||
add comment="BF flat .41 (legacy, retiring)" name=pool-v1 ranges=\
|
||||
10.40.41.180-10.40.41.199
|
||||
/ip dhcp-server
|
||||
add address-pool=pool-v1 disabled=yes interface=bridge lease-time=2h name=\
|
||||
defconf
|
||||
add address-pool=pool-v10 comment=MAIN interface=vlan10 lease-time=1d name=\
|
||||
dhcp-v10
|
||||
add address-pool=pool-v20 comment=INFRA interface=vlan20 lease-time=1d name=\
|
||||
dhcp-v20
|
||||
add address-pool=pool-v30 comment=IOT interface=vlan30 lease-time=1d name=\
|
||||
dhcp-v30
|
||||
add address-pool=pool-v40 comment=MEDIA interface=vlan40 lease-time=1d name=\
|
||||
dhcp-v40
|
||||
add address-pool=pool-v50 comment=UNTRUSTED interface=vlan50 lease-time=1d \
|
||||
name=dhcp-v50
|
||||
add address-pool=pool-v90 comment=GUEST interface=vlan90 lease-time=12h name=\
|
||||
dhcp-v90
|
||||
add address-pool=pool-v99 comment=MGMT interface=vlan99 lease-time=1d name=\
|
||||
dhcp-v99
|
||||
/system logging action
|
||||
add disk-file-name=wan-test disk-lines-per-file=2000 name=wantest target=disk
|
||||
/system script
|
||||
add dont-require-permissions=no name=wantest-probe owner=admin policy=\
|
||||
read,write,policy,test source=" :local ts ([/system clock get date] . \" \
|
||||
\" . [/system clock get time])\
|
||||
\n :local e1stat \"\?\"\
|
||||
\n :do { :set e1stat [/ip dhcp-client get [find interface=ether1] status]\
|
||||
\_} on-error={}\
|
||||
\n :local e1addr \"-\"\
|
||||
\n :do { :set e1addr [/ip dhcp-client get [find interface=ether1] address\
|
||||
] } on-error={}\
|
||||
\n :local e1mac [/interface ethernet get [find name=ether1] mac-address]\
|
||||
\n :log info (\"WANTEST [\" . \$ts . \"] ether1 status=\" . \$e1stat . \"\
|
||||
\_addr=\" . \$e1addr . \" mac=\" . \$e1mac)\
|
||||
\n :local gw \"-\"\
|
||||
\n :do { :set gw [/ip route get [find dst-address=\"0.0.0.0/0\" active=ye\
|
||||
s] gateway] } on-error={}\
|
||||
\n :log info (\"WANTEST route default-gw=\" . \$gw)\
|
||||
\n # WAN-Routing+NAT: Router -> public 1.1.1.1 (UDP/53). UNABH\C3\84NGIG \
|
||||
von ap1-DNS-Config.\
|
||||
\n # (ICMP/HTTPS sind hier geblockt -> :resolve gegen feste IP ist das ro\
|
||||
buste Signal.)\
|
||||
\n :do { :local w [:resolve \"google.com\" server=1.1.1.1] ; :log info (\
|
||||
\"WANTEST wan-reach via-1.1.1.1 ok google.com=\" . \$w) } on-error={ :log \
|
||||
info \"WANTEST wan-reach via-1.1.1.1 FAIL (Routing/NAT\?)\" }\
|
||||
\n # DoH end-to-end: ap1-Resolver = was die Clients als DNS bekommen\
|
||||
\n :do { :local d [:resolve \"google.com\"] ; :log info (\"WANTEST dns-do\
|
||||
h ok google.com=\" . \$d) } on-error={ :log info \"WANTEST dns-doh FAIL (D\
|
||||
oH/Bootstrap\?)\" }"
|
||||
add dont-require-permissions=no name=wantest-run owner=admin policy=\
|
||||
read,write,policy,test source=" :global WTN\
|
||||
\n :if (([:typeof \$WTN] = \"nothing\") or (\$WTN = \"\")) do={ :set WTN \
|
||||
24 }\
|
||||
\n :log info (\"WANTEST run start (\" . \$WTN . \"x @15s, ~\" . (\$WTN * \
|
||||
15 / 60) . \" min)\")\
|
||||
\n :for i from=1 to=\$WTN do={\
|
||||
\n /system script run wantest-probe\
|
||||
\n :delay 15s\
|
||||
\n }\
|
||||
\n :log info \"WANTEST run done\""
|
||||
add dont-require-permissions=no name=wanmac-clone owner=admin policy=\
|
||||
read,write,policy,test source=" :global FBMAC\
|
||||
\n :if (([:typeof \$FBMAC] = \"nothing\") or (\$FBMAC = \"\")) do={ :set \
|
||||
FBMAC \"0C:72:74:36:90:99\" }\
|
||||
\n :global E1ORIG\
|
||||
\n :set E1ORIG [/interface ethernet get [find name=ether1] mac-address]\
|
||||
\n :log info (\"WANTEST macclone: orig=\" . \$E1ORIG . \" -> fb=\" . \$FB\
|
||||
MAC . \" (Auto-Revert in ~90s)\")\
|
||||
\n /interface ethernet set [find name=ether1] mac-address=\$FBMAC\
|
||||
\n :do { /ip dhcp-client release [find interface=ether1] } on-error={}\
|
||||
\n :delay 2s\
|
||||
\n :do { /ip dhcp-client renew [find interface=ether1] } on-error={}\
|
||||
\n :delay 25s\
|
||||
\n :for i from=1 to=4 do={ /system script run wantest-probe ; :delay 15s \
|
||||
}\
|
||||
\n # --- garantierter Auto-Revert im selben Lauf (kein Scheduler n\C3\B6t\
|
||||
ig) ---\
|
||||
\n /interface ethernet reset-mac-address [find name=ether1]\
|
||||
\n :do { /ip dhcp-client release [find interface=ether1] } on-error={}\
|
||||
\n :delay 2s\
|
||||
\n :do { /ip dhcp-client renew [find interface=ether1] } on-error={}\
|
||||
\n :delay 15s\
|
||||
\n /system script run wantest-probe\
|
||||
\n :log info (\"WANTEST macclone done -> revert auf factory-MAC (orig war\
|
||||
\_\" . \$E1ORIG . \")\")"
|
||||
add dont-require-permissions=no name=wanmac-revert owner=admin policy=\
|
||||
read,write,policy,test source=" /interface ethernet reset-mac-address [fi\
|
||||
nd name=ether1]\
|
||||
\n :do { /ip dhcp-client release [find interface=ether1] } on-error={}\
|
||||
\n :delay 2s\
|
||||
\n :do { /ip dhcp-client renew [find interface=ether1] } on-error={}\
|
||||
\n :delay 10s\
|
||||
\n /system script run wantest-probe\
|
||||
\n :log info \"WANTEST macclone manual-revert -> factory-MAC\""
|
||||
/disk settings
|
||||
set auto-media-interface=bridge auto-media-sharing=yes auto-smb-sharing=yes
|
||||
/interface bridge port
|
||||
add bridge=bridge comment=defconf interface=ether2
|
||||
add bridge=bridge comment=defconf interface=ether3
|
||||
add bridge=bridge comment=defconf interface=ether4
|
||||
add bridge=bridge comment=defconf interface=ether5
|
||||
add bridge=bridge comment=defconf interface=wifi2
|
||||
add bridge=bridge interface=ether1
|
||||
/interface bridge vlan
|
||||
add bridge=bridge untagged=bridge,ether2 vlan-ids=1
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=10
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=20
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=30
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=40
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=50
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=90
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=99
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=100
|
||||
/interface list member
|
||||
add comment=defconf interface=bridge list=LAN
|
||||
add comment=defconf interface=ether1 list=WAN
|
||||
add comment="WAN Arris via vlan100" interface=vlan100 list=WAN
|
||||
/interface wifi access-list
|
||||
add action=accept comment="pin P750W to ap1 (1/2): accept on ap1 iot" \
|
||||
disabled=yes interface=w2-iot mac-address=4C:EB:BD:E3:25:F2
|
||||
add action=reject comment=\
|
||||
"pin P750W to ap1 (2/2): reject on any other AP incl dynamic ap2 VAPs" \
|
||||
disabled=yes mac-address=4C:EB:BD:E3:25:F2
|
||||
/interface wifi cap
|
||||
set caps-man-addresses=10.40.41.1 discovery-interfaces=bridge
|
||||
/interface wifi capsman
|
||||
set enabled=yes interfaces=bridge
|
||||
/interface wifi provisioning
|
||||
add action=create-dynamic-enabled master-configuration=cfg-main-2g \
|
||||
slave-configurations=cfg-iot,cfg-media,cfg-untrusted,cfg-guest,cfg-infra \
|
||||
supported-bands=2ghz-ax
|
||||
add action=create-dynamic-enabled master-configuration=cfg-main-5g \
|
||||
slave-configurations=cfg-media,cfg-untrusted,cfg-guest,cfg-infra \
|
||||
supported-bands=5ghz-ax
|
||||
/interface wireguard peers
|
||||
add allowed-address=10.101.0.0/24 comment=fm endpoint-address=\
|
||||
abxhutfgsid9snmy.myfritz.net endpoint-port=52476 interface=wg-hub name=fm \
|
||||
public-key="dzRY0lnnUygijChWe5wXZmXPeNcbdALpqBptA3fyiVE="
|
||||
add allowed-address=10.95.10.0/24 comment=dw interface=wg-hub name=dw \
|
||||
public-key="FqYZLztQ/qME5VDie5QLGH++5299WJiE1dPpQnPbzUw="
|
||||
/ip address
|
||||
add address=10.40.41.1/24 comment=defconf interface=bridge network=10.40.41.0
|
||||
add address=10.40.10.1/24 comment="MAIN GW" interface=vlan10 network=\
|
||||
10.40.10.0
|
||||
add address=10.40.20.1/24 comment="INFRA GW" interface=vlan20 network=\
|
||||
10.40.20.0
|
||||
add address=10.40.30.1/24 comment="IOT GW" interface=vlan30 network=\
|
||||
10.40.30.0
|
||||
add address=10.40.40.1/24 comment="MEDIA GW" interface=vlan40 network=\
|
||||
10.40.40.0
|
||||
add address=10.40.50.1/24 comment="UNTRUSTED GW" interface=vlan50 network=\
|
||||
10.40.50.0
|
||||
add address=10.40.90.1/24 comment="GUEST GW" interface=vlan90 network=\
|
||||
10.40.90.0
|
||||
add address=10.40.99.1/24 comment="MGMT GW" interface=vlan99 network=\
|
||||
10.40.99.0
|
||||
add address=10.40.41.254/24 comment="Secondary = alte FB-GW-IP; haelt statisch\
|
||||
e .41-Hosts online nach Arris-Swap (ap1 NATs + WG-Hub)" interface=bridge \
|
||||
network=10.40.41.0
|
||||
/ip dhcp-client
|
||||
add comment=defconf disabled=yes interface=ether1 name=client1 use-peer-dns=\
|
||||
no
|
||||
add comment="WAN Arris DHCP (Liwest) via vlan100" interface=vlan100 name=\
|
||||
client2 use-peer-dns=no use-peer-ntp=no
|
||||
/ip dhcp-server lease
|
||||
add address=10.40.10.82 client-id=1:56:71:6c:22:e6:a9 dhcp-option=\
|
||||
"dns 1.1.1.1" mac-address=56:71:6C:22:E6:A9 server=dhcp-v10
|
||||
add address=10.40.10.196 client-id=1:f2:62:4c:e1:af:9 mac-address=\
|
||||
F2:62:4C:E1:AF:09 server=dhcp-v10
|
||||
add address=10.40.40.199 client-id=1:48:a6:b8:b:63:10 mac-address=\
|
||||
48:A6:B8:0B:63:10 server=dhcp-v40
|
||||
add address=10.40.40.191 client-id=1:34:7e:5c:32:37:96 mac-address=\
|
||||
34:7E:5C:32:37:96 server=dhcp-v40
|
||||
add address=10.40.40.192 client-id=1:34:7e:5c:32:33:b8 mac-address=\
|
||||
34:7E:5C:32:33:B8 server=dhcp-v40
|
||||
add address=10.40.40.193 client-id=1:78:28:ca:80:2a:f6 mac-address=\
|
||||
78:28:CA:80:2A:F6 server=dhcp-v40
|
||||
add address=10.40.40.195 client-id=1:78:28:ca:82:16:c2 mac-address=\
|
||||
78:28:CA:82:16:C2 server=dhcp-v40
|
||||
add address=10.40.40.201 client-id=1:94:9f:3e:49:59:ee mac-address=\
|
||||
94:9F:3E:49:59:EE server=dhcp-v40
|
||||
add address=10.40.40.196 client-id=1:48:a6:b8:16:38:ae mac-address=\
|
||||
48:A6:B8:16:38:AE server=dhcp-v40
|
||||
add address=10.40.40.197 client-id=1:48:a6:b8:14:fe:f2 mac-address=\
|
||||
48:A6:B8:14:FE:F2 server=dhcp-v40
|
||||
add address=10.40.40.200 client-id=1:48:a6:b8:69:69:7b mac-address=\
|
||||
48:A6:B8:69:69:7B server=dhcp-v40
|
||||
add address=10.40.40.194 client-id=1:48:a6:b8:14:fe:d0 mac-address=\
|
||||
48:A6:B8:14:FE:D0 server=dhcp-v40
|
||||
add address=10.40.40.198 comment=SonosTerrasse mac-address=78:28:CA:D2:0D:AC \
|
||||
server=dhcp-v40
|
||||
add address=10.40.30.202 comment=shelly-s22_kueche_steckdose3-2 mac-address=\
|
||||
A0:85:E3:C8:65:34 server=dhcp-v30
|
||||
add address=10.40.30.203 comment=shelly-s23_dieleug-wohnzimmer_licht \
|
||||
mac-address=AC:15:18:7B:62:20 server=dhcp-v30
|
||||
add address=10.40.30.205 comment=shelly-s25_bad_lichtschalter mac-address=\
|
||||
98:A3:16:79:38:50 server=dhcp-v30
|
||||
add address=10.40.30.206 comment=shelly-s20_kueche_steckdosen2 mac-address=\
|
||||
98:A3:16:7C:5F:EC server=dhcp-v30
|
||||
add address=10.40.30.207 comment=shelly-s21_kueche_steckdosen4 mac-address=\
|
||||
20:6E:F1:01:F9:F8 server=dhcp-v30
|
||||
add address=10.40.30.208 comment=shelly-s1_weihnachten_kueche mac-address=\
|
||||
E4:B0:63:D7:C7:A4 server=dhcp-v30
|
||||
add address=10.40.30.209 comment=shelly-s2_weihnachten_terrasse mac-address=\
|
||||
28:37:2F:36:F4:7C server=dhcp-v30
|
||||
add address=10.40.30.210 comment=shelly-s3_weihnachten_kinderzimmer \
|
||||
mac-address=E4:B0:63:E4:EF:7C server=dhcp-v30
|
||||
add address=10.40.30.211 comment=shelly-s4_kueche_mikrowelle mac-address=\
|
||||
E4:B0:63:E4:0F:30 server=dhcp-v30
|
||||
add address=10.40.30.212 comment=shelly-s5_kueche_backofen mac-address=\
|
||||
D8:85:AC:0C:5C:C8 server=dhcp-v30
|
||||
add address=10.40.30.213 comment=shelly-s6_kueche_kuehlschrank mac-address=\
|
||||
D0:CF:13:D8:18:FC server=dhcp-v30
|
||||
add address=10.40.30.214 comment=shelly-s7_kueche_tiefkuehlschrank \
|
||||
mac-address=D0:CF:13:D9:94:E8 server=dhcp-v30
|
||||
add address=10.40.30.215 comment=shelly-s8_kueche_geschirrspueler \
|
||||
mac-address=E4:B0:63:FA:FD:E0 server=dhcp-v30
|
||||
add address=10.40.30.216 comment=shelly-s9_wohnzimmer_sideboard mac-address=\
|
||||
E8:F6:0A:61:88:08 server=dhcp-v30
|
||||
add address=10.40.30.217 comment=shelly-s10_bad_sonos mac-address=\
|
||||
E4:B0:63:FC:57:E4 server=dhcp-v30
|
||||
add address=10.40.30.218 comment=shelly-s11_kinderzimmer_sonos mac-address=\
|
||||
E4:B0:63:FA:6C:00 server=dhcp-v30
|
||||
add address=10.40.30.219 comment=shelly-s12_dieleug_steckdosen mac-address=\
|
||||
48:F6:EE:C8:E6:AC server=dhcp-v30
|
||||
add address=10.40.30.220 comment=shelly-s13_arbeitszimmer_technik \
|
||||
mac-address=48:F6:EE:DD:6A:F4 server=dhcp-v30
|
||||
add address=10.40.30.221 comment=shelly-s14_schlafzimmer_bett mac-address=\
|
||||
E4:B0:63:FC:59:48 server=dhcp-v30
|
||||
add address=10.40.30.222 comment=shelly-s15_technik_pve mac-address=\
|
||||
E4:B0:63:FA:D5:34 server=dhcp-v30
|
||||
add address=10.40.30.223 comment=shelly-s16_wohnzimmer_steckdosen \
|
||||
mac-address=10:20:BA:FA:F5:40 server=dhcp-v30
|
||||
add address=10.40.30.224 comment=shelly-s17_bad_steckdosen mac-address=\
|
||||
10:20:BA:FB:6D:64 server=dhcp-v30
|
||||
add address=10.40.30.225 comment=shelly-s18_kueche_steckdosen1 mac-address=\
|
||||
48:F6:EE:CC:16:E4 server=dhcp-v30
|
||||
add address=10.40.30.226 comment=shelly-s19_kueche_steckdosen3 mac-address=\
|
||||
10:20:BA:FB:70:FC server=dhcp-v30
|
||||
add address=10.40.30.227 comment=switchbot-floorlamp mac-address=\
|
||||
B8:F8:62:09:F2:04 server=dhcp-v30
|
||||
add address=10.40.30.228 comment=Twinkly_Weihnachtsgirlande mac-address=\
|
||||
98:F4:AB:2C:A7:88 server=dhcp-v30
|
||||
add address=10.40.30.230 comment=Withings_waage mac-address=00:24:E4:40:2A:72 \
|
||||
server=dhcp-v30
|
||||
add address=10.40.30.231 comment=Withings_blutdruck mac-address=\
|
||||
A4:7E:FA:18:2C:64 server=dhcp-v30
|
||||
add address=10.40.30.232 comment=pve-homematic-raspi-ccu mac-address=\
|
||||
BC:24:11:8E:0A:57 server=dhcp-v30
|
||||
add address=10.40.30.233 comment=shelly-s26_bad_luefter mac-address=\
|
||||
98:A3:16:7A:A3:54 server=dhcp-v30
|
||||
add address=10.40.30.236 comment=lichterkette mac-address=A4:F0:0F:5F:D0:EC \
|
||||
server=dhcp-v30
|
||||
add address=10.40.30.237 comment=lichterkette-mini mac-address=\
|
||||
24:DC:C3:9B:89:64 server=dhcp-v30
|
||||
add address=10.40.30.241 comment=NukiSmartlock mac-address=28:DB:A7:09:7B:54 \
|
||||
server=dhcp-v30
|
||||
add address=10.40.30.244 comment=NukiBridge mac-address=24:62:AB:B1:63:F4 \
|
||||
server=dhcp-v30
|
||||
add address=10.40.30.8 comment=DTUBI-414392337823 mac-address=\
|
||||
54:F2:9F:12:51:F0 server=dhcp-v30
|
||||
add address=10.40.20.10 comment=nas-bf mac-address=90:09:D0:58:20:F9 server=\
|
||||
dhcp-v20
|
||||
add address=10.40.40.11 comment=tv mac-address=70:AF:24:B8:C9:86 server=\
|
||||
dhcp-v40
|
||||
add address=10.40.30.5 comment=P750W mac-address=4C:EB:BD:E3:25:F2 server=\
|
||||
dhcp-v30
|
||||
add address=10.40.30.180 client-id=1:e4:bc:96:1f:b2:81 comment=Airfryer \
|
||||
dhcp-option="dns 1.1.1.1" mac-address=E4:BC:96:1F:B2:81 server=dhcp-v30
|
||||
add address=10.40.30.204 comment=shelly-s24_bad_spiegelschrank mac-address=\
|
||||
14:33:5C:D8:2D:7C server=dhcp-v30
|
||||
add address=10.40.30.150 client-id=1:fc:ee:11:3:32:26 comment=Ender3V3KE-3226 \
|
||||
mac-address=FC:EE:11:03:32:26 server=dhcp-v30
|
||||
/ip dhcp-server network
|
||||
add address=10.40.10.0/24 comment=MAIN dns-server=10.40.10.1 gateway=\
|
||||
10.40.10.1
|
||||
add address=10.40.20.0/24 comment=INFRA dns-server=10.40.20.1 gateway=\
|
||||
10.40.20.1
|
||||
add address=10.40.30.0/24 comment=IOT dns-server=10.40.30.1 gateway=\
|
||||
10.40.30.1
|
||||
add address=10.40.40.0/24 comment=MEDIA dns-server=10.40.40.1 gateway=\
|
||||
10.40.40.1
|
||||
add address=10.40.41.0/24 comment=defconf dns-server=10.40.41.1 gateway=\
|
||||
10.40.41.1 netmask=24
|
||||
add address=10.40.50.0/24 comment=UNTRUSTED dns-server=10.40.50.1 gateway=\
|
||||
10.40.50.1
|
||||
add address=10.40.90.0/24 comment=GUEST dns-server=10.40.90.1 gateway=\
|
||||
10.40.90.1
|
||||
add address=10.40.99.0/24 comment=MGMT dhcp-option=omada-inform dns-server=\
|
||||
10.40.99.1 gateway=10.40.99.1
|
||||
/ip dns
|
||||
set allow-remote-requests=yes mdns-repeat-ifaces=\
|
||||
vlan10,vlan20,vlan40,vlan30,vlan90,bridge servers=1.1.1.1 use-doh-server=\
|
||||
https://px35ynlol3.cloudflare-gateway.com/dns-query verify-doh-cert=yes
|
||||
/ip dns static
|
||||
add address=10.40.41.1 comment=defconf name=router.lan type=A
|
||||
add address=10.40.41.2 comment=\
|
||||
"TP4-transition; update to 10.40.99.2 after MGMT migration" name=\
|
||||
ap2.bf.lan type=A
|
||||
add address=10.40.41.11 comment="ALLNET core switch" name=sw1.bf.lan type=A
|
||||
add address=10.40.41.12 comment="Omada access switch" name=sw2.bf.lan type=A
|
||||
add address=10.40.20.167 comment=\
|
||||
"Mac mini (INFRA VLAN20, migriert 2026-06-16)" name=macmini.bf.lan type=A
|
||||
add address=10.40.20.100 comment="Proxmox hypervisor" name=pve.bf.lan type=A
|
||||
add address=10.40.20.173 comment="pve-mcp SSE server" name=pve-mcp.bf.lan \
|
||||
type=A
|
||||
add address=10.40.20.10 comment=\
|
||||
"DS923+ NAS (VLAN20, TP14.1, DNS-Sweep TP14.3 2026-07-16)" name=\
|
||||
nas.bf.lan type=A
|
||||
add address=10.40.20.126 comment=\
|
||||
"Docker-LXC / Portainer (VLAN20, TP14.2, DNS-Sweep TP14.3 2026-07-16)" \
|
||||
name=docker.bf.lan type=A
|
||||
add address=10.40.99.1 comment=\
|
||||
"TP19.1: ap1 MGMT = vlan99 GW (live since TP4), no separate move needed" \
|
||||
name=ap1.bf.lan type=A
|
||||
add address=10.40.20.20 comment=\
|
||||
"TP20: Platform-Postgres LXC 105 on pve, PG16, nautobot DB" name=\
|
||||
platform-pg.bf.lan type=A
|
||||
/ip firewall filter
|
||||
add action=accept chain=forward comment="defconf: accept in ipsec policy" \
|
||||
ipsec-policy=in,ipsec
|
||||
add action=accept chain=forward comment="defconf: accept out ipsec policy" \
|
||||
ipsec-policy=out,ipsec
|
||||
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \
|
||||
connection-state=established,related
|
||||
add action=accept chain=forward comment=\
|
||||
"defconf: accept established,related, untracked" connection-state=\
|
||||
established,related,untracked
|
||||
add action=drop chain=forward comment="defconf: drop invalid" \
|
||||
connection-state=invalid
|
||||
add action=drop chain=forward comment=\
|
||||
"defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \
|
||||
in-interface-list=WAN
|
||||
add action=accept chain=input comment=TP10-seal-est connection-state=\
|
||||
established,related,untracked
|
||||
add action=drop chain=input comment=TP10-seal-inv connection-state=invalid
|
||||
add action=accept chain=input comment="TP10: WG hub listen (51821)" dst-port=\
|
||||
51821 protocol=udp
|
||||
add action=accept chain=forward comment="TP10: allow from WG spokes (FM/DW)" \
|
||||
in-interface=wg-hub
|
||||
add action=accept chain=forward comment="TP10: allow to WG spokes (FM/DW)" \
|
||||
out-interface=wg-hub
|
||||
add action=accept chain=input comment=TP10-seal-dhcp dst-port=68 \
|
||||
in-interface-list=WAN protocol=udp
|
||||
add action=accept chain=input comment=TP10-seal-icmp protocol=icmp
|
||||
add action=accept chain=input comment=TP10-seal-lan in-interface-list=LAN
|
||||
add action=drop chain=input comment=TP10-seal-wandrop in-interface-list=WAN
|
||||
add action=accept chain=forward comment=\
|
||||
"TP5: MAIN->MEDIA forward (AirPlay/Sonos)" in-interface=vlan10 \
|
||||
out-interface=vlan40
|
||||
add action=accept chain=forward comment=\
|
||||
"TP5: MEDIA->MAIN forward (AirPlay/Sonos)" in-interface=vlan40 \
|
||||
out-interface=vlan10
|
||||
add action=accept chain=input comment=\
|
||||
"TP5: mDNS 5353 input vlan10 (repeater)" dst-port=5353 in-interface=\
|
||||
vlan10 protocol=udp
|
||||
add action=accept chain=input comment=\
|
||||
"TP5: mDNS 5353 input vlan40 (repeater)" dst-port=5353 in-interface=\
|
||||
vlan40 protocol=udp
|
||||
add action=accept chain=forward comment=\
|
||||
"TP5: INFRA->MEDIA forward (HA<->Sonos)" in-interface=vlan20 \
|
||||
out-interface=vlan40
|
||||
add action=accept chain=forward comment=\
|
||||
"TP5: MEDIA->INFRA forward (HA<->Sonos)" in-interface=vlan40 \
|
||||
out-interface=vlan20
|
||||
add action=accept chain=input comment=\
|
||||
"TP5: mDNS 5353 input vlan20 (repeater/HA)" dst-port=5353 in-interface=\
|
||||
vlan20 protocol=udp
|
||||
add action=accept chain=input comment=\
|
||||
"TP5: mDNS 5353 input vlan30 (repeater)" dst-port=5353 in-interface=\
|
||||
vlan30 protocol=udp
|
||||
add action=accept chain=input comment=\
|
||||
"TP5: mDNS 5353 input vlan90 (repeater)" dst-port=5353 in-interface=\
|
||||
vlan90 protocol=udp
|
||||
add action=accept chain=forward comment=\
|
||||
"TP5: GUEST->MEDIA forward (Sonos/Cast)" in-interface=vlan90 \
|
||||
out-interface=vlan40
|
||||
add action=accept chain=forward comment=\
|
||||
"TP5: MEDIA->GUEST forward (Sonos/Cast)" in-interface=vlan40 \
|
||||
out-interface=vlan90
|
||||
/ip firewall nat
|
||||
add action=masquerade chain=srcnat comment="defconf: masquerade" \
|
||||
ipsec-policy=out,none out-interface-list=WAN
|
||||
add action=accept chain=srcnat comment=\
|
||||
"TP4: no-NAT inter-VLAN (LAN-internal, before masquerade)" dst-address=\
|
||||
10.40.0.0/16
|
||||
add action=masquerade chain=srcnat comment="TP4: masquerade VLANs toward FB" \
|
||||
disabled=yes out-interface=bridge
|
||||
add action=masquerade chain=srcnat comment=\
|
||||
"TP4: masquerade VLANs via ether1 (Liwest WAN)" disabled=yes \
|
||||
out-interface=ether1
|
||||
/ip route
|
||||
add comment="TP10: FM spoke -> wg-hub" dst-address=10.101.0.0/24 gateway=\
|
||||
wg-hub
|
||||
add comment="TP10: DW spoke (kuenftig) -> wg-hub" dst-address=10.95.10.0/24 \
|
||||
gateway=wg-hub
|
||||
/ipv6 firewall address-list
|
||||
add address=::/128 comment="defconf: unspecified address" list=bad_ipv6
|
||||
add address=::1/128 comment="defconf: lo" list=bad_ipv6
|
||||
add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6
|
||||
add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6
|
||||
add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6
|
||||
add address=100::/64 comment="defconf: discard only " list=bad_ipv6
|
||||
add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6
|
||||
add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6
|
||||
add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6
|
||||
/ipv6 firewall filter
|
||||
add action=accept chain=input comment=\
|
||||
"defconf: accept established,related,untracked" connection-state=\
|
||||
established,related,untracked
|
||||
add action=drop chain=input comment="defconf: drop invalid" connection-state=\
|
||||
invalid
|
||||
add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\
|
||||
icmpv6
|
||||
add action=accept chain=input comment="defconf: accept UDP traceroute" \
|
||||
dst-port=33434-33534 protocol=udp
|
||||
add action=accept chain=input comment=\
|
||||
"defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\
|
||||
udp src-address=fe80::/10
|
||||
add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \
|
||||
protocol=udp
|
||||
add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\
|
||||
ipsec-ah
|
||||
add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\
|
||||
ipsec-esp
|
||||
add action=accept chain=input comment=\
|
||||
"defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
|
||||
add action=drop chain=input comment=\
|
||||
"defconf: drop everything else not coming from LAN" in-interface-list=\
|
||||
!LAN
|
||||
add action=fasttrack-connection chain=forward comment="defconf: fasttrack6" \
|
||||
connection-state=established,related
|
||||
add action=accept chain=forward comment=\
|
||||
"defconf: accept established,related,untracked" connection-state=\
|
||||
established,related,untracked
|
||||
add action=drop chain=forward comment="defconf: drop invalid" \
|
||||
connection-state=invalid
|
||||
add action=drop chain=forward comment=\
|
||||
"defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6
|
||||
add action=drop chain=forward comment=\
|
||||
"defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6
|
||||
add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \
|
||||
hop-limit=equal:1 protocol=icmpv6
|
||||
add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\
|
||||
icmpv6
|
||||
add action=accept chain=forward comment="defconf: accept HIP" protocol=139
|
||||
add action=accept chain=forward comment="defconf: accept IKE" dst-port=\
|
||||
500,4500 protocol=udp
|
||||
add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\
|
||||
ipsec-ah
|
||||
add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\
|
||||
ipsec-esp
|
||||
add action=accept chain=forward comment=\
|
||||
"defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
|
||||
add action=drop chain=forward comment=\
|
||||
"defconf: drop everything else not coming from LAN" in-interface-list=\
|
||||
!LAN
|
||||
/system clock
|
||||
set time-zone-name=Europe/Vienna
|
||||
/system identity
|
||||
set name=ap1
|
||||
/system logging
|
||||
add action=wantest topics=script
|
||||
BIN
routeros/ap1-pre-core-cutover-20260806-073616.backup
Normal file
BIN
routeros/ap1-pre-core-cutover-20260806-073616.backup
Normal file
Binary file not shown.
558
routeros/ap1-pre-core-cutover-20260806-073616.rsc
Normal file
558
routeros/ap1-pre-core-cutover-20260806-073616.rsc
Normal file
@@ -0,0 +1,558 @@
|
||||
# 2026-08-06 09:36:00 by RouterOS 7.23.2
|
||||
# software id = 2ATI-ZRRH
|
||||
#
|
||||
# model = C52iG-5HaxD2HaxD
|
||||
# serial number = HM70BFZBYVQ
|
||||
/interface bridge
|
||||
add admin-mac=D0:EA:11:4D:40:E1 auto-mac=no comment=defconf name=bridge \
|
||||
vlan-filtering=yes
|
||||
/interface wireguard
|
||||
add comment="TP10 Multi-Site VPN Hub (FM/DW spokes). Kein IP aufs IF (Routing \
|
||||
via AllowedIPs/Routes)." listen-port=51821 mtu=1412 name=wg-hub
|
||||
/interface vlan
|
||||
add comment="MAIN 10.40.10.0/24" interface=bridge name=vlan10 vlan-id=10
|
||||
add comment="INFRA 10.40.20.0/24" interface=bridge name=vlan20 vlan-id=20
|
||||
add comment="IOT 10.40.30.0/24" interface=bridge name=vlan30 vlan-id=30
|
||||
add comment="MEDIA 10.40.40.0/24" interface=bridge name=vlan40 vlan-id=40
|
||||
add comment="UNTRUSTED 10.40.50.0/24" interface=bridge name=vlan50 vlan-id=50
|
||||
add comment="GUEST 10.40.90.0/24" interface=bridge name=vlan90 vlan-id=90
|
||||
add comment="MGMT 10.40.99.0/24" interface=bridge name=vlan99 vlan-id=99
|
||||
add comment="WAN Arris (Liwest)" interface=bridge name=vlan100 vlan-id=100
|
||||
/interface list
|
||||
add comment=defconf name=WAN
|
||||
add comment=defconf name=LAN
|
||||
/interface wifi channel
|
||||
add band=2ghz-ax disabled=no frequency=2462 name=ch-2g width=20mhz
|
||||
add band=5ghz-ax disabled=no frequency=5745 name=ch-5g skip-dfs-channels=\
|
||||
10min-cac width=20/40/80mhz
|
||||
/interface wifi datapath
|
||||
add bridge=bridge name=dp-main vlan-id=10
|
||||
add bridge=bridge name=dp-iot vlan-id=30
|
||||
add bridge=bridge name=dp-media vlan-id=40
|
||||
add bridge=bridge name=dp-untrusted vlan-id=50
|
||||
add bridge=bridge name=dp-guest vlan-id=90
|
||||
add bridge=bridge name=dp-infra vlan-id=20
|
||||
/interface wifi security
|
||||
add authentication-types=wpa3-psk disabled=no ft=yes ft-over-ds=yes name=\
|
||||
sec-main
|
||||
add authentication-types=wpa2-psk,wpa3-psk disabled=no ft=no name=sec-iot
|
||||
add authentication-types=wpa2-psk,wpa3-psk disabled=no ft=no ft-over-ds=no \
|
||||
name=sec-media
|
||||
add authentication-types=wpa2-psk,wpa3-psk disabled=no ft=no name=\
|
||||
sec-untrusted
|
||||
add authentication-types=wpa2-psk,wpa3-psk ft=yes ft-over-ds=yes name=\
|
||||
sec-guest
|
||||
add authentication-types=wpa2-psk,wpa3-psk ft=no name=sec-infra
|
||||
/interface wifi configuration
|
||||
add country=Austria disabled=no mode=ap name=cfg-main-2g security=sec-main \
|
||||
ssid=dirtyvader-main tx-power=20
|
||||
add country=Austria datapath=dp-iot mode=ap multicast-enhance=enabled name=\
|
||||
cfg-iot security=sec-iot ssid=dirtyvader-iot
|
||||
add country=Austria datapath=dp-media mode=ap multicast-enhance=enabled name=\
|
||||
cfg-media security=sec-media ssid=dirtyvader-media
|
||||
add country=Austria datapath=dp-untrusted mode=ap name=cfg-untrusted \
|
||||
security=sec-untrusted ssid=dirtyvader-untrusted
|
||||
add country=Austria datapath=dp-guest mode=ap name=cfg-guest security=\
|
||||
sec-guest ssid=dirtyvader-guest
|
||||
add country=Austria datapath=dp-infra mode=ap name=cfg-infra security=\
|
||||
sec-infra ssid=dirtyvader-infra
|
||||
/interface wifi
|
||||
set [ find default-name=wifi2 ] channel.frequency=2412 configuration=\
|
||||
cfg-main-2g configuration.manager=local disabled=no
|
||||
add configuration=cfg-guest disabled=no mac-address=D2:EA:11:4D:40:EB \
|
||||
master-interface=wifi2 name=w2-guest
|
||||
add configuration=cfg-iot disabled=no mac-address=D2:EA:11:4D:40:E8 \
|
||||
master-interface=wifi2 name=w2-iot
|
||||
add configuration=cfg-media disabled=no mac-address=D2:EA:11:4D:40:E9 \
|
||||
master-interface=wifi2 name=w2-media
|
||||
add configuration=cfg-untrusted disabled=no mac-address=D2:EA:11:4D:40:EA \
|
||||
master-interface=wifi2 name=w2-untrusted
|
||||
/interface wifi steering
|
||||
add name=st-main neighbor-group=bf-main rrm=yes wnm=yes
|
||||
/interface wifi configuration
|
||||
add channel=ch-5g country=Austria datapath=dp-main mode=ap name=cfg-main-5g \
|
||||
security=sec-main ssid=dirtyvader-main steering=st-main
|
||||
/interface wifi
|
||||
set [ find default-name=wifi1 ] channel.frequency=5180 configuration=\
|
||||
cfg-main-5g configuration.manager=local disabled=no
|
||||
add configuration=cfg-guest disabled=no mac-address=D2:EA:11:4D:40:E7 \
|
||||
master-interface=wifi1 name=w5-guest
|
||||
add configuration=cfg-media disabled=no mac-address=D2:EA:11:4D:40:E5 \
|
||||
master-interface=wifi1 name=w5-media
|
||||
add configuration=cfg-untrusted disabled=no mac-address=D2:EA:11:4D:40:E6 \
|
||||
master-interface=wifi1 name=w5-untrusted
|
||||
/ip dhcp-server option
|
||||
add code=6 name="dns 1.1.1.1" value=0x01010101
|
||||
add code=138 name=omada-inform value=0x0A2814AF
|
||||
/ip pool
|
||||
add name=default-dhcp ranges=192.168.88.10-192.168.88.254
|
||||
add name=pool-v10 ranges=10.40.10.100-10.40.10.200
|
||||
add name=pool-v20 ranges=10.40.20.100-10.40.20.200
|
||||
add name=pool-v30 ranges=10.40.30.100-10.40.30.250
|
||||
add name=pool-v40 ranges=10.40.40.100-10.40.40.200
|
||||
add name=pool-v50 ranges=10.40.50.100-10.40.50.200
|
||||
add name=pool-v90 ranges=10.40.90.100-10.40.90.200
|
||||
add name=pool-v99 ranges=10.40.99.100-10.40.99.200
|
||||
add comment="BF flat .41 (legacy, retiring)" name=pool-v1 ranges=\
|
||||
10.40.41.180-10.40.41.199
|
||||
/ip dhcp-server
|
||||
add address-pool=pool-v1 disabled=yes interface=bridge lease-time=2h name=\
|
||||
defconf
|
||||
add address-pool=pool-v10 comment=MAIN interface=vlan10 lease-time=1d name=\
|
||||
dhcp-v10
|
||||
add address-pool=pool-v20 comment=INFRA interface=vlan20 lease-time=1d name=\
|
||||
dhcp-v20
|
||||
add address-pool=pool-v30 comment=IOT interface=vlan30 lease-time=1d name=\
|
||||
dhcp-v30
|
||||
add address-pool=pool-v40 comment=MEDIA interface=vlan40 lease-time=1d name=\
|
||||
dhcp-v40
|
||||
add address-pool=pool-v50 comment=UNTRUSTED interface=vlan50 lease-time=1d \
|
||||
name=dhcp-v50
|
||||
add address-pool=pool-v90 comment=GUEST interface=vlan90 lease-time=12h name=\
|
||||
dhcp-v90
|
||||
add address-pool=pool-v99 comment=MGMT interface=vlan99 lease-time=1d name=\
|
||||
dhcp-v99
|
||||
/system logging action
|
||||
add disk-file-name=wan-test disk-lines-per-file=2000 name=wantest target=disk
|
||||
/system script
|
||||
add dont-require-permissions=no name=wantest-probe owner=admin policy=\
|
||||
read,write,policy,test source=" :local ts ([/system clock get date] . \" \
|
||||
\" . [/system clock get time])\
|
||||
\n :local e1stat \"\?\"\
|
||||
\n :do { :set e1stat [/ip dhcp-client get [find interface=ether1] status]\
|
||||
\_} on-error={}\
|
||||
\n :local e1addr \"-\"\
|
||||
\n :do { :set e1addr [/ip dhcp-client get [find interface=ether1] address\
|
||||
] } on-error={}\
|
||||
\n :local e1mac [/interface ethernet get [find name=ether1] mac-address]\
|
||||
\n :log info (\"WANTEST [\" . \$ts . \"] ether1 status=\" . \$e1stat . \"\
|
||||
\_addr=\" . \$e1addr . \" mac=\" . \$e1mac)\
|
||||
\n :local gw \"-\"\
|
||||
\n :do { :set gw [/ip route get [find dst-address=\"0.0.0.0/0\" active=ye\
|
||||
s] gateway] } on-error={}\
|
||||
\n :log info (\"WANTEST route default-gw=\" . \$gw)\
|
||||
\n # WAN-Routing+NAT: Router -> public 1.1.1.1 (UDP/53). UNABH\C3\84NGIG \
|
||||
von ap1-DNS-Config.\
|
||||
\n # (ICMP/HTTPS sind hier geblockt -> :resolve gegen feste IP ist das ro\
|
||||
buste Signal.)\
|
||||
\n :do { :local w [:resolve \"google.com\" server=1.1.1.1] ; :log info (\
|
||||
\"WANTEST wan-reach via-1.1.1.1 ok google.com=\" . \$w) } on-error={ :log \
|
||||
info \"WANTEST wan-reach via-1.1.1.1 FAIL (Routing/NAT\?)\" }\
|
||||
\n # DoH end-to-end: ap1-Resolver = was die Clients als DNS bekommen\
|
||||
\n :do { :local d [:resolve \"google.com\"] ; :log info (\"WANTEST dns-do\
|
||||
h ok google.com=\" . \$d) } on-error={ :log info \"WANTEST dns-doh FAIL (D\
|
||||
oH/Bootstrap\?)\" }"
|
||||
add dont-require-permissions=no name=wantest-run owner=admin policy=\
|
||||
read,write,policy,test source=" :global WTN\
|
||||
\n :if (([:typeof \$WTN] = \"nothing\") or (\$WTN = \"\")) do={ :set WTN \
|
||||
24 }\
|
||||
\n :log info (\"WANTEST run start (\" . \$WTN . \"x @15s, ~\" . (\$WTN * \
|
||||
15 / 60) . \" min)\")\
|
||||
\n :for i from=1 to=\$WTN do={\
|
||||
\n /system script run wantest-probe\
|
||||
\n :delay 15s\
|
||||
\n }\
|
||||
\n :log info \"WANTEST run done\""
|
||||
add dont-require-permissions=no name=wanmac-clone owner=admin policy=\
|
||||
read,write,policy,test source=" :global FBMAC\
|
||||
\n :if (([:typeof \$FBMAC] = \"nothing\") or (\$FBMAC = \"\")) do={ :set \
|
||||
FBMAC \"0C:72:74:36:90:99\" }\
|
||||
\n :global E1ORIG\
|
||||
\n :set E1ORIG [/interface ethernet get [find name=ether1] mac-address]\
|
||||
\n :log info (\"WANTEST macclone: orig=\" . \$E1ORIG . \" -> fb=\" . \$FB\
|
||||
MAC . \" (Auto-Revert in ~90s)\")\
|
||||
\n /interface ethernet set [find name=ether1] mac-address=\$FBMAC\
|
||||
\n :do { /ip dhcp-client release [find interface=ether1] } on-error={}\
|
||||
\n :delay 2s\
|
||||
\n :do { /ip dhcp-client renew [find interface=ether1] } on-error={}\
|
||||
\n :delay 25s\
|
||||
\n :for i from=1 to=4 do={ /system script run wantest-probe ; :delay 15s \
|
||||
}\
|
||||
\n # --- garantierter Auto-Revert im selben Lauf (kein Scheduler n\C3\B6t\
|
||||
ig) ---\
|
||||
\n /interface ethernet reset-mac-address [find name=ether1]\
|
||||
\n :do { /ip dhcp-client release [find interface=ether1] } on-error={}\
|
||||
\n :delay 2s\
|
||||
\n :do { /ip dhcp-client renew [find interface=ether1] } on-error={}\
|
||||
\n :delay 15s\
|
||||
\n /system script run wantest-probe\
|
||||
\n :log info (\"WANTEST macclone done -> revert auf factory-MAC (orig war\
|
||||
\_\" . \$E1ORIG . \")\")"
|
||||
add dont-require-permissions=no name=wanmac-revert owner=admin policy=\
|
||||
read,write,policy,test source=" /interface ethernet reset-mac-address [fi\
|
||||
nd name=ether1]\
|
||||
\n :do { /ip dhcp-client release [find interface=ether1] } on-error={}\
|
||||
\n :delay 2s\
|
||||
\n :do { /ip dhcp-client renew [find interface=ether1] } on-error={}\
|
||||
\n :delay 10s\
|
||||
\n /system script run wantest-probe\
|
||||
\n :log info \"WANTEST macclone manual-revert -> factory-MAC\""
|
||||
/disk settings
|
||||
set auto-media-interface=bridge auto-media-sharing=yes auto-smb-sharing=yes
|
||||
/interface bridge port
|
||||
add bridge=bridge comment=defconf interface=ether2
|
||||
add bridge=bridge comment=defconf interface=ether3
|
||||
add bridge=bridge comment=defconf interface=ether4
|
||||
add bridge=bridge comment=defconf interface=ether5
|
||||
add bridge=bridge comment=defconf interface=wifi2
|
||||
add bridge=bridge interface=ether1
|
||||
/interface bridge vlan
|
||||
add bridge=bridge untagged=bridge,ether2 vlan-ids=1
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=10
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=20
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=30
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=40
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=50
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=90
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=99
|
||||
add bridge=bridge tagged=bridge,ether2,ether1 vlan-ids=100
|
||||
/interface list member
|
||||
add comment=defconf interface=bridge list=LAN
|
||||
add comment=defconf interface=ether1 list=WAN
|
||||
add comment="WAN Arris via vlan100" interface=vlan100 list=WAN
|
||||
/interface wifi access-list
|
||||
add action=accept comment="pin P750W to ap1 (1/2): accept on ap1 iot" \
|
||||
disabled=yes interface=w2-iot mac-address=4C:EB:BD:E3:25:F2
|
||||
add action=reject comment=\
|
||||
"pin P750W to ap1 (2/2): reject on any other AP incl dynamic ap2 VAPs" \
|
||||
disabled=yes mac-address=4C:EB:BD:E3:25:F2
|
||||
/interface wifi cap
|
||||
set caps-man-addresses=10.40.41.1 discovery-interfaces=bridge
|
||||
/interface wifi capsman
|
||||
set enabled=yes interfaces=bridge
|
||||
/interface wifi provisioning
|
||||
add action=create-dynamic-enabled master-configuration=cfg-main-2g \
|
||||
slave-configurations=cfg-iot,cfg-media,cfg-untrusted,cfg-guest,cfg-infra \
|
||||
supported-bands=2ghz-ax
|
||||
add action=create-dynamic-enabled master-configuration=cfg-main-5g \
|
||||
slave-configurations=cfg-media,cfg-untrusted,cfg-guest,cfg-infra \
|
||||
supported-bands=5ghz-ax
|
||||
/interface wireguard peers
|
||||
add allowed-address=10.101.0.0/24 comment=fm endpoint-address=\
|
||||
abxhutfgsid9snmy.myfritz.net endpoint-port=52476 interface=wg-hub name=fm \
|
||||
public-key="dzRY0lnnUygijChWe5wXZmXPeNcbdALpqBptA3fyiVE="
|
||||
add allowed-address=10.95.10.0/24 comment=dw interface=wg-hub name=dw \
|
||||
public-key="FqYZLztQ/qME5VDie5QLGH++5299WJiE1dPpQnPbzUw="
|
||||
/ip address
|
||||
add address=10.40.41.1/24 comment=defconf interface=bridge network=10.40.41.0
|
||||
add address=10.40.10.1/24 comment="MAIN GW" interface=vlan10 network=\
|
||||
10.40.10.0
|
||||
add address=10.40.20.1/24 comment="INFRA GW" interface=vlan20 network=\
|
||||
10.40.20.0
|
||||
add address=10.40.30.1/24 comment="IOT GW" interface=vlan30 network=\
|
||||
10.40.30.0
|
||||
add address=10.40.40.1/24 comment="MEDIA GW" interface=vlan40 network=\
|
||||
10.40.40.0
|
||||
add address=10.40.50.1/24 comment="UNTRUSTED GW" interface=vlan50 network=\
|
||||
10.40.50.0
|
||||
add address=10.40.90.1/24 comment="GUEST GW" interface=vlan90 network=\
|
||||
10.40.90.0
|
||||
add address=10.40.99.1/24 comment="MGMT GW" interface=vlan99 network=\
|
||||
10.40.99.0
|
||||
add address=10.40.41.254/24 comment="Secondary = alte FB-GW-IP; haelt statisch\
|
||||
e .41-Hosts online nach Arris-Swap (ap1 NATs + WG-Hub)" interface=bridge \
|
||||
network=10.40.41.0
|
||||
/ip dhcp-client
|
||||
add comment=defconf disabled=yes interface=ether1 name=client1 use-peer-dns=\
|
||||
no
|
||||
add comment="WAN Arris DHCP (Liwest) via vlan100" interface=vlan100 name=\
|
||||
client2 use-peer-dns=no use-peer-ntp=no
|
||||
/ip dhcp-server lease
|
||||
add address=10.40.10.82 client-id=1:56:71:6c:22:e6:a9 dhcp-option=\
|
||||
"dns 1.1.1.1" mac-address=56:71:6C:22:E6:A9 server=dhcp-v10
|
||||
add address=10.40.10.196 client-id=1:f2:62:4c:e1:af:9 mac-address=\
|
||||
F2:62:4C:E1:AF:09 server=dhcp-v10
|
||||
add address=10.40.40.199 client-id=1:48:a6:b8:b:63:10 mac-address=\
|
||||
48:A6:B8:0B:63:10 server=dhcp-v40
|
||||
add address=10.40.40.191 client-id=1:34:7e:5c:32:37:96 mac-address=\
|
||||
34:7E:5C:32:37:96 server=dhcp-v40
|
||||
add address=10.40.40.192 client-id=1:34:7e:5c:32:33:b8 mac-address=\
|
||||
34:7E:5C:32:33:B8 server=dhcp-v40
|
||||
add address=10.40.40.193 client-id=1:78:28:ca:80:2a:f6 mac-address=\
|
||||
78:28:CA:80:2A:F6 server=dhcp-v40
|
||||
add address=10.40.40.195 client-id=1:78:28:ca:82:16:c2 mac-address=\
|
||||
78:28:CA:82:16:C2 server=dhcp-v40
|
||||
add address=10.40.40.201 client-id=1:94:9f:3e:49:59:ee mac-address=\
|
||||
94:9F:3E:49:59:EE server=dhcp-v40
|
||||
add address=10.40.40.196 client-id=1:48:a6:b8:16:38:ae mac-address=\
|
||||
48:A6:B8:16:38:AE server=dhcp-v40
|
||||
add address=10.40.40.197 client-id=1:48:a6:b8:14:fe:f2 mac-address=\
|
||||
48:A6:B8:14:FE:F2 server=dhcp-v40
|
||||
add address=10.40.40.200 client-id=1:48:a6:b8:69:69:7b mac-address=\
|
||||
48:A6:B8:69:69:7B server=dhcp-v40
|
||||
add address=10.40.40.194 client-id=1:48:a6:b8:14:fe:d0 mac-address=\
|
||||
48:A6:B8:14:FE:D0 server=dhcp-v40
|
||||
add address=10.40.40.198 comment=SonosTerrasse mac-address=78:28:CA:D2:0D:AC \
|
||||
server=dhcp-v40
|
||||
add address=10.40.30.202 comment=shelly-s22_kueche_steckdose3-2 mac-address=\
|
||||
A0:85:E3:C8:65:34 server=dhcp-v30
|
||||
add address=10.40.30.203 comment=shelly-s23_dieleug-wohnzimmer_licht \
|
||||
mac-address=AC:15:18:7B:62:20 server=dhcp-v30
|
||||
add address=10.40.30.205 comment=shelly-s25_bad_lichtschalter mac-address=\
|
||||
98:A3:16:79:38:50 server=dhcp-v30
|
||||
add address=10.40.30.206 comment=shelly-s20_kueche_steckdosen2 mac-address=\
|
||||
98:A3:16:7C:5F:EC server=dhcp-v30
|
||||
add address=10.40.30.207 comment=shelly-s21_kueche_steckdosen4 mac-address=\
|
||||
20:6E:F1:01:F9:F8 server=dhcp-v30
|
||||
add address=10.40.30.208 comment=shelly-s1_weihnachten_kueche mac-address=\
|
||||
E4:B0:63:D7:C7:A4 server=dhcp-v30
|
||||
add address=10.40.30.209 comment=shelly-s2_weihnachten_terrasse mac-address=\
|
||||
28:37:2F:36:F4:7C server=dhcp-v30
|
||||
add address=10.40.30.210 comment=shelly-s3_weihnachten_kinderzimmer \
|
||||
mac-address=E4:B0:63:E4:EF:7C server=dhcp-v30
|
||||
add address=10.40.30.211 comment=shelly-s4_kueche_mikrowelle mac-address=\
|
||||
E4:B0:63:E4:0F:30 server=dhcp-v30
|
||||
add address=10.40.30.212 comment=shelly-s5_kueche_backofen mac-address=\
|
||||
D8:85:AC:0C:5C:C8 server=dhcp-v30
|
||||
add address=10.40.30.213 comment=shelly-s6_kueche_kuehlschrank mac-address=\
|
||||
D0:CF:13:D8:18:FC server=dhcp-v30
|
||||
add address=10.40.30.214 comment=shelly-s7_kueche_tiefkuehlschrank \
|
||||
mac-address=D0:CF:13:D9:94:E8 server=dhcp-v30
|
||||
add address=10.40.30.215 comment=shelly-s8_kueche_geschirrspueler \
|
||||
mac-address=E4:B0:63:FA:FD:E0 server=dhcp-v30
|
||||
add address=10.40.30.216 comment=shelly-s9_wohnzimmer_sideboard mac-address=\
|
||||
E8:F6:0A:61:88:08 server=dhcp-v30
|
||||
add address=10.40.30.217 comment=shelly-s10_bad_sonos mac-address=\
|
||||
E4:B0:63:FC:57:E4 server=dhcp-v30
|
||||
add address=10.40.30.218 comment=shelly-s11_kinderzimmer_sonos mac-address=\
|
||||
E4:B0:63:FA:6C:00 server=dhcp-v30
|
||||
add address=10.40.30.219 comment=shelly-s12_dieleug_steckdosen mac-address=\
|
||||
48:F6:EE:C8:E6:AC server=dhcp-v30
|
||||
add address=10.40.30.220 comment=shelly-s13_arbeitszimmer_technik \
|
||||
mac-address=48:F6:EE:DD:6A:F4 server=dhcp-v30
|
||||
add address=10.40.30.221 comment=shelly-s14_schlafzimmer_bett mac-address=\
|
||||
E4:B0:63:FC:59:48 server=dhcp-v30
|
||||
add address=10.40.30.222 comment=shelly-s15_technik_pve mac-address=\
|
||||
E4:B0:63:FA:D5:34 server=dhcp-v30
|
||||
add address=10.40.30.223 comment=shelly-s16_wohnzimmer_steckdosen \
|
||||
mac-address=10:20:BA:FA:F5:40 server=dhcp-v30
|
||||
add address=10.40.30.224 comment=shelly-s17_bad_steckdosen mac-address=\
|
||||
10:20:BA:FB:6D:64 server=dhcp-v30
|
||||
add address=10.40.30.225 comment=shelly-s18_kueche_steckdosen1 mac-address=\
|
||||
48:F6:EE:CC:16:E4 server=dhcp-v30
|
||||
add address=10.40.30.226 comment=shelly-s19_kueche_steckdosen3 mac-address=\
|
||||
10:20:BA:FB:70:FC server=dhcp-v30
|
||||
add address=10.40.30.227 comment=switchbot-floorlamp mac-address=\
|
||||
B8:F8:62:09:F2:04 server=dhcp-v30
|
||||
add address=10.40.30.228 comment=Twinkly_Weihnachtsgirlande mac-address=\
|
||||
98:F4:AB:2C:A7:88 server=dhcp-v30
|
||||
add address=10.40.30.230 comment=Withings_waage mac-address=00:24:E4:40:2A:72 \
|
||||
server=dhcp-v30
|
||||
add address=10.40.30.231 comment=Withings_blutdruck mac-address=\
|
||||
A4:7E:FA:18:2C:64 server=dhcp-v30
|
||||
add address=10.40.30.232 comment=pve-homematic-raspi-ccu mac-address=\
|
||||
BC:24:11:8E:0A:57 server=dhcp-v30
|
||||
add address=10.40.30.233 comment=shelly-s26_bad_luefter mac-address=\
|
||||
98:A3:16:7A:A3:54 server=dhcp-v30
|
||||
add address=10.40.30.236 comment=lichterkette mac-address=A4:F0:0F:5F:D0:EC \
|
||||
server=dhcp-v30
|
||||
add address=10.40.30.237 comment=lichterkette-mini mac-address=\
|
||||
24:DC:C3:9B:89:64 server=dhcp-v30
|
||||
add address=10.40.30.241 comment=NukiSmartlock mac-address=28:DB:A7:09:7B:54 \
|
||||
server=dhcp-v30
|
||||
add address=10.40.30.244 comment=NukiBridge mac-address=24:62:AB:B1:63:F4 \
|
||||
server=dhcp-v30
|
||||
add address=10.40.30.8 comment=DTUBI-414392337823 mac-address=\
|
||||
54:F2:9F:12:51:F0 server=dhcp-v30
|
||||
add address=10.40.20.10 comment=nas-bf mac-address=90:09:D0:58:20:F9 server=\
|
||||
dhcp-v20
|
||||
add address=10.40.40.11 comment=tv mac-address=70:AF:24:B8:C9:86 server=\
|
||||
dhcp-v40
|
||||
add address=10.40.30.5 comment=P750W mac-address=4C:EB:BD:E3:25:F2 server=\
|
||||
dhcp-v30
|
||||
add address=10.40.30.180 client-id=1:e4:bc:96:1f:b2:81 comment=Airfryer \
|
||||
dhcp-option="dns 1.1.1.1" mac-address=E4:BC:96:1F:B2:81 server=dhcp-v30
|
||||
add address=10.40.30.204 comment=shelly-s24_bad_spiegelschrank mac-address=\
|
||||
14:33:5C:D8:2D:7C server=dhcp-v30
|
||||
add address=10.40.30.150 client-id=1:fc:ee:11:3:32:26 comment=Ender3V3KE-3226 \
|
||||
mac-address=FC:EE:11:03:32:26 server=dhcp-v30
|
||||
/ip dhcp-server network
|
||||
add address=10.40.10.0/24 comment=MAIN dns-server=10.40.10.1 gateway=\
|
||||
10.40.10.1
|
||||
add address=10.40.20.0/24 comment=INFRA dns-server=10.40.20.1 gateway=\
|
||||
10.40.20.1
|
||||
add address=10.40.30.0/24 comment=IOT dns-server=10.40.30.1 gateway=\
|
||||
10.40.30.1
|
||||
add address=10.40.40.0/24 comment=MEDIA dns-server=10.40.40.1 gateway=\
|
||||
10.40.40.1
|
||||
add address=10.40.41.0/24 comment=defconf dns-server=10.40.41.1 gateway=\
|
||||
10.40.41.1 netmask=24
|
||||
add address=10.40.50.0/24 comment=UNTRUSTED dns-server=10.40.50.1 gateway=\
|
||||
10.40.50.1
|
||||
add address=10.40.90.0/24 comment=GUEST dns-server=10.40.90.1 gateway=\
|
||||
10.40.90.1
|
||||
add address=10.40.99.0/24 comment=MGMT dhcp-option=omada-inform dns-server=\
|
||||
10.40.99.1 gateway=10.40.99.1
|
||||
/ip dns
|
||||
set allow-remote-requests=yes mdns-repeat-ifaces=\
|
||||
vlan10,vlan20,vlan40,vlan30,vlan90,bridge servers=1.1.1.1 use-doh-server=\
|
||||
https://px35ynlol3.cloudflare-gateway.com/dns-query verify-doh-cert=yes
|
||||
/ip dns static
|
||||
add address=10.40.41.1 comment=defconf name=router.lan type=A
|
||||
add address=10.40.41.2 comment=\
|
||||
"TP4-transition; update to 10.40.99.2 after MGMT migration" name=\
|
||||
ap2.bf.lan type=A
|
||||
add address=10.40.41.11 comment="ALLNET core switch" name=sw1.bf.lan type=A
|
||||
add address=10.40.41.12 comment="Omada access switch" name=sw2.bf.lan type=A
|
||||
add address=10.40.20.167 comment=\
|
||||
"Mac mini (INFRA VLAN20, migriert 2026-06-16)" name=macmini.bf.lan type=A
|
||||
add address=10.40.20.100 comment="Proxmox hypervisor" name=pve.bf.lan type=A
|
||||
add address=10.40.20.173 comment="pve-mcp SSE server" name=pve-mcp.bf.lan \
|
||||
type=A
|
||||
add address=10.40.20.10 comment=\
|
||||
"DS923+ NAS (VLAN20, TP14.1, DNS-Sweep TP14.3 2026-07-16)" name=\
|
||||
nas.bf.lan type=A
|
||||
add address=10.40.20.126 comment=\
|
||||
"Docker-LXC / Portainer (VLAN20, TP14.2, DNS-Sweep TP14.3 2026-07-16)" \
|
||||
name=docker.bf.lan type=A
|
||||
add address=10.40.99.1 comment=\
|
||||
"TP19.1: ap1 MGMT = vlan99 GW (live since TP4), no separate move needed" \
|
||||
name=ap1.bf.lan type=A
|
||||
add address=10.40.20.20 comment=\
|
||||
"TP20: Platform-Postgres LXC 105 on pve, PG16, nautobot DB" name=\
|
||||
platform-pg.bf.lan type=A
|
||||
/ip firewall filter
|
||||
add action=accept chain=forward comment="defconf: accept in ipsec policy" \
|
||||
ipsec-policy=in,ipsec
|
||||
add action=accept chain=forward comment="defconf: accept out ipsec policy" \
|
||||
ipsec-policy=out,ipsec
|
||||
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \
|
||||
connection-state=established,related
|
||||
add action=accept chain=forward comment=\
|
||||
"defconf: accept established,related, untracked" connection-state=\
|
||||
established,related,untracked
|
||||
add action=drop chain=forward comment="defconf: drop invalid" \
|
||||
connection-state=invalid
|
||||
add action=drop chain=forward comment=\
|
||||
"defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \
|
||||
in-interface-list=WAN
|
||||
add action=accept chain=input comment=TP10-seal-est connection-state=\
|
||||
established,related,untracked
|
||||
add action=drop chain=input comment=TP10-seal-inv connection-state=invalid
|
||||
add action=accept chain=input comment="TP10: WG hub listen (51821)" dst-port=\
|
||||
51821 protocol=udp
|
||||
add action=accept chain=forward comment="TP10: allow from WG spokes (FM/DW)" \
|
||||
in-interface=wg-hub
|
||||
add action=accept chain=forward comment="TP10: allow to WG spokes (FM/DW)" \
|
||||
out-interface=wg-hub
|
||||
add action=accept chain=input comment=TP10-seal-dhcp dst-port=68 \
|
||||
in-interface-list=WAN protocol=udp
|
||||
add action=accept chain=input comment=TP10-seal-icmp protocol=icmp
|
||||
add action=accept chain=input comment=TP10-seal-lan in-interface-list=LAN
|
||||
add action=drop chain=input comment=TP10-seal-wandrop in-interface-list=WAN
|
||||
add action=accept chain=forward comment=\
|
||||
"TP5: MAIN->MEDIA forward (AirPlay/Sonos)" in-interface=vlan10 \
|
||||
out-interface=vlan40
|
||||
add action=accept chain=forward comment=\
|
||||
"TP5: MEDIA->MAIN forward (AirPlay/Sonos)" in-interface=vlan40 \
|
||||
out-interface=vlan10
|
||||
add action=accept chain=input comment=\
|
||||
"TP5: mDNS 5353 input vlan10 (repeater)" dst-port=5353 in-interface=\
|
||||
vlan10 protocol=udp
|
||||
add action=accept chain=input comment=\
|
||||
"TP5: mDNS 5353 input vlan40 (repeater)" dst-port=5353 in-interface=\
|
||||
vlan40 protocol=udp
|
||||
add action=accept chain=forward comment=\
|
||||
"TP5: INFRA->MEDIA forward (HA<->Sonos)" in-interface=vlan20 \
|
||||
out-interface=vlan40
|
||||
add action=accept chain=forward comment=\
|
||||
"TP5: MEDIA->INFRA forward (HA<->Sonos)" in-interface=vlan40 \
|
||||
out-interface=vlan20
|
||||
add action=accept chain=input comment=\
|
||||
"TP5: mDNS 5353 input vlan20 (repeater/HA)" dst-port=5353 in-interface=\
|
||||
vlan20 protocol=udp
|
||||
add action=accept chain=input comment=\
|
||||
"TP5: mDNS 5353 input vlan30 (repeater)" dst-port=5353 in-interface=\
|
||||
vlan30 protocol=udp
|
||||
add action=accept chain=input comment=\
|
||||
"TP5: mDNS 5353 input vlan90 (repeater)" dst-port=5353 in-interface=\
|
||||
vlan90 protocol=udp
|
||||
add action=accept chain=forward comment=\
|
||||
"TP5: GUEST->MEDIA forward (Sonos/Cast)" in-interface=vlan90 \
|
||||
out-interface=vlan40
|
||||
add action=accept chain=forward comment=\
|
||||
"TP5: MEDIA->GUEST forward (Sonos/Cast)" in-interface=vlan40 \
|
||||
out-interface=vlan90
|
||||
/ip firewall nat
|
||||
add action=masquerade chain=srcnat comment="defconf: masquerade" \
|
||||
ipsec-policy=out,none out-interface-list=WAN
|
||||
add action=accept chain=srcnat comment=\
|
||||
"TP4: no-NAT inter-VLAN (LAN-internal, before masquerade)" dst-address=\
|
||||
10.40.0.0/16
|
||||
add action=masquerade chain=srcnat comment="TP4: masquerade VLANs toward FB" \
|
||||
disabled=yes out-interface=bridge
|
||||
add action=masquerade chain=srcnat comment=\
|
||||
"TP4: masquerade VLANs via ether1 (Liwest WAN)" disabled=yes \
|
||||
out-interface=ether1
|
||||
/ip route
|
||||
add comment="TP10: FM spoke -> wg-hub" dst-address=10.101.0.0/24 gateway=\
|
||||
wg-hub
|
||||
add comment="TP10: DW spoke (kuenftig) -> wg-hub" dst-address=10.95.10.0/24 \
|
||||
gateway=wg-hub
|
||||
/ipv6 firewall address-list
|
||||
add address=::/128 comment="defconf: unspecified address" list=bad_ipv6
|
||||
add address=::1/128 comment="defconf: lo" list=bad_ipv6
|
||||
add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6
|
||||
add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6
|
||||
add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6
|
||||
add address=100::/64 comment="defconf: discard only " list=bad_ipv6
|
||||
add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6
|
||||
add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6
|
||||
add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6
|
||||
/ipv6 firewall filter
|
||||
add action=accept chain=input comment=\
|
||||
"defconf: accept established,related,untracked" connection-state=\
|
||||
established,related,untracked
|
||||
add action=drop chain=input comment="defconf: drop invalid" connection-state=\
|
||||
invalid
|
||||
add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\
|
||||
icmpv6
|
||||
add action=accept chain=input comment="defconf: accept UDP traceroute" \
|
||||
dst-port=33434-33534 protocol=udp
|
||||
add action=accept chain=input comment=\
|
||||
"defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\
|
||||
udp src-address=fe80::/10
|
||||
add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \
|
||||
protocol=udp
|
||||
add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\
|
||||
ipsec-ah
|
||||
add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\
|
||||
ipsec-esp
|
||||
add action=accept chain=input comment=\
|
||||
"defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
|
||||
add action=drop chain=input comment=\
|
||||
"defconf: drop everything else not coming from LAN" in-interface-list=\
|
||||
!LAN
|
||||
add action=fasttrack-connection chain=forward comment="defconf: fasttrack6" \
|
||||
connection-state=established,related
|
||||
add action=accept chain=forward comment=\
|
||||
"defconf: accept established,related,untracked" connection-state=\
|
||||
established,related,untracked
|
||||
add action=drop chain=forward comment="defconf: drop invalid" \
|
||||
connection-state=invalid
|
||||
add action=drop chain=forward comment=\
|
||||
"defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6
|
||||
add action=drop chain=forward comment=\
|
||||
"defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6
|
||||
add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \
|
||||
hop-limit=equal:1 protocol=icmpv6
|
||||
add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\
|
||||
icmpv6
|
||||
add action=accept chain=forward comment="defconf: accept HIP" protocol=139
|
||||
add action=accept chain=forward comment="defconf: accept IKE" dst-port=\
|
||||
500,4500 protocol=udp
|
||||
add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\
|
||||
ipsec-ah
|
||||
add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\
|
||||
ipsec-esp
|
||||
add action=accept chain=forward comment=\
|
||||
"defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
|
||||
add action=drop chain=forward comment=\
|
||||
"defconf: drop everything else not coming from LAN" in-interface-list=\
|
||||
!LAN
|
||||
/system clock
|
||||
set time-zone-name=Europe/Vienna
|
||||
/system identity
|
||||
set name=ap1
|
||||
/system logging
|
||||
add action=wantest topics=script
|
||||
75
routeros/apply-core-cutover-l3.py
Normal file
75
routeros/apply-core-cutover-l3.py
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Lade die staged L3-Cutover-Config auf crs326-core (noch NICHT enablen).
|
||||
|
||||
Creds aus ~/.claude.json. Alle operativen Objekte in der rsc sind disabled=yes,
|
||||
also bleibt der aktive Datenpfad unberührt.
|
||||
"""
|
||||
import json
|
||||
import pathlib
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
CORE_IP = "10.40.41.211"
|
||||
RSC = pathlib.Path(__file__).with_name("tp15-core-cutover-intended.rsc")
|
||||
CLAUDE_JSON = pathlib.Path.home() / ".claude.json"
|
||||
|
||||
|
||||
def load_core_creds():
|
||||
cfg = json.loads(CLAUDE_JSON.read_text())
|
||||
env = cfg.get("mcpServers", {}).get("mikromcp", {}).get("env", {})
|
||||
user = env.get("CRS326_CORE_USER") or env.get("ROUTER_USER")
|
||||
pw = env.get("CRS326_CORE_PASS") or env.get("ROUTER_PASS")
|
||||
if not user or not pw:
|
||||
raise SystemExit("CRS326_CORE_USER/PASS nicht in ~/.claude.json mikromcp.env gefunden")
|
||||
return user, pw
|
||||
|
||||
|
||||
def ssh_base(user, pw):
|
||||
return [
|
||||
"sshpass", "-p", pw,
|
||||
"ssh",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "PubkeyAuthentication=no",
|
||||
f"{user}@{CORE_IP}",
|
||||
]
|
||||
|
||||
|
||||
def run_silent(base, cmd):
|
||||
r = subprocess.run(base + [cmd], capture_output=True, text=True)
|
||||
if r.returncode != 0:
|
||||
out = (r.stdout + r.stderr).replace(pw, "***")
|
||||
raise SystemExit(f"Befehl fehlgeschlagen (rc={r.returncode}):\n{out}")
|
||||
return r
|
||||
|
||||
|
||||
def main():
|
||||
if not RSC.exists():
|
||||
raise SystemExit(f"{RSC} fehlt")
|
||||
user, pw = load_core_creds()
|
||||
base = ssh_base(user, pw)
|
||||
print(f"crs326-core L3-Cutover-Config laden ({RSC.name}) ...")
|
||||
|
||||
# 1) Datei auf Router kopieren
|
||||
r = subprocess.run(
|
||||
["sshpass", "-p", pw,
|
||||
"scp",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "PubkeyAuthentication=no",
|
||||
str(RSC),
|
||||
f"{user}@{CORE_IP}:{RSC.name}"],
|
||||
capture_output=True, text=True,
|
||||
)
|
||||
if r.returncode != 0:
|
||||
raise SystemExit(f"SCP fehlgeschlagen: {r.stderr.replace(pw, '***')}")
|
||||
|
||||
# 2) Import auslösen
|
||||
run_silent(base, f'/import file-name="{RSC.name}"')
|
||||
|
||||
print(" Import abgeschlossen (staged / disabled).")
|
||||
print(" Nächster Schritt: L2-Portplan + Cutover-Enable.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
91
routeros/backup-ap1.py
Normal file
91
routeros/backup-ap1.py
Normal file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Erstelle ein Binary-Backup + einen Text-Export von ap1 vor dem TP15-Cutover.
|
||||
|
||||
Creds aus ~/.claude.json (mikromcp-env). Backup-Dateien landen unter routeros/.
|
||||
"""
|
||||
import json
|
||||
import pathlib
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
AP1_IP = "10.40.10.1"
|
||||
CLAUDE_JSON = pathlib.Path.home() / ".claude.json"
|
||||
OUT_DIR = pathlib.Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def load_ap1_creds():
|
||||
cfg = json.loads(CLAUDE_JSON.read_text())
|
||||
env = cfg.get("mcpServers", {}).get("mikromcp", {}).get("env", {})
|
||||
user = env.get("ROUTER_AP1_USER") or env.get("ROUTER_USER")
|
||||
pw = env.get("ROUTER_AP1_PASS") or env.get("ROUTER_PASS")
|
||||
if not user or not pw:
|
||||
raise SystemExit("ROUTER_AP1_USER/PASS nicht in ~/.claude.json mikromcp.env gefunden")
|
||||
return user, pw
|
||||
|
||||
|
||||
def ssh_cmd(user, pw, remote_command):
|
||||
return [
|
||||
"sshpass", "-p", pw,
|
||||
"ssh",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "PubkeyAuthentication=no",
|
||||
f"{user}@{AP1_IP}",
|
||||
remote_command,
|
||||
]
|
||||
|
||||
|
||||
def scp_cmd(user, pw, remote_file, local_file):
|
||||
return [
|
||||
"sshpass", "-p", pw,
|
||||
"scp",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "PubkeyAuthentication=no",
|
||||
f"{user}@{AP1_IP}:{remote_file}",
|
||||
str(local_file),
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
user, pw = load_ap1_creds()
|
||||
ts = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
|
||||
backup_name = f"ap1-pre-core-cutover-{ts}"
|
||||
|
||||
print(f"ap1 Backup via SSH {user}@{AP1_IP}")
|
||||
|
||||
# 1) Binary backup + Text-Export auf ap1 erzeugen
|
||||
create_cmd = ssh_cmd(
|
||||
user, pw,
|
||||
f'/system backup save name="{backup_name}" dont-encrypt=yes; '
|
||||
f'/export file="{backup_name}"'
|
||||
)
|
||||
print(f" Erzeuge Backup/Export auf ap1 ...")
|
||||
subprocess.run(create_cmd, check=True)
|
||||
|
||||
# 2) Herunterladen
|
||||
local_backup = OUT_DIR / f"{backup_name}.backup"
|
||||
local_export = OUT_DIR / f"{backup_name}.rsc"
|
||||
|
||||
print(f" Lade {backup_name}.backup herunter ...")
|
||||
subprocess.run(scp_cmd(user, pw, f"{backup_name}.backup", local_backup), check=True)
|
||||
|
||||
print(f" Lade {backup_name}.rsc herunter ...")
|
||||
subprocess.run(scp_cmd(user, pw, f"{backup_name}.rsc", local_export), check=True)
|
||||
|
||||
# 3) Verifizieren
|
||||
backup_size = local_backup.stat().st_size
|
||||
export_size = local_export.stat().st_size
|
||||
print(f" OK: {local_backup.name} ({backup_size} Bytes)")
|
||||
print(f" OK: {local_export.name} ({export_size} Bytes)")
|
||||
|
||||
if backup_size < 1000:
|
||||
print(" WARN: Backup-Datei auffällig klein!")
|
||||
sys.exit(1)
|
||||
|
||||
print("\nNächster Schritt: Cutover-Config auf crs326-core laden.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
86
routeros/backup-core.py
Normal file
86
routeros/backup-core.py
Normal file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Erstelle ein Binary-Backup + einen Text-Export von crs326-core vor dem TP15-Cutover.
|
||||
|
||||
Creds aus ~/.claude.json (mikromcp-env, CRS326_CORE_*). Backup-Dateien landen unter routeros/.
|
||||
"""
|
||||
import json
|
||||
import pathlib
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
CORE_IP = "10.40.41.211" # VLAN1-Temp; alternativ 10.40.99.11 sobald 99T auf Uplink
|
||||
CLAUDE_JSON = pathlib.Path.home() / ".claude.json"
|
||||
OUT_DIR = pathlib.Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def load_core_creds():
|
||||
cfg = json.loads(CLAUDE_JSON.read_text())
|
||||
env = cfg.get("mcpServers", {}).get("mikromcp", {}).get("env", {})
|
||||
user = env.get("CRS326_CORE_USER") or env.get("ROUTER_USER")
|
||||
pw = env.get("CRS326_CORE_PASS") or env.get("ROUTER_PASS")
|
||||
if not user or not pw:
|
||||
raise SystemExit("CRS326_CORE_USER/PASS nicht in ~/.claude.json mikromcp.env gefunden")
|
||||
return user, pw
|
||||
|
||||
|
||||
def ssh_cmd(user, pw, remote_command):
|
||||
return [
|
||||
"sshpass", "-p", pw,
|
||||
"ssh",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "PubkeyAuthentication=no",
|
||||
f"{user}@{CORE_IP}",
|
||||
remote_command,
|
||||
]
|
||||
|
||||
|
||||
def scp_cmd(user, pw, remote_file, local_file):
|
||||
return [
|
||||
"sshpass", "-p", pw,
|
||||
"scp",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "PubkeyAuthentication=no",
|
||||
f"{user}@{CORE_IP}:{remote_file}",
|
||||
str(local_file),
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
user, pw = load_core_creds()
|
||||
ts = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
|
||||
backup_name = f"crs326-core-pre-cutover-{ts}"
|
||||
|
||||
print(f"crs326-core Backup via SSH {user}@{CORE_IP}")
|
||||
|
||||
create_cmd = ssh_cmd(
|
||||
user, pw,
|
||||
f'/system backup save name="{backup_name}" dont-encrypt=yes; '
|
||||
f'/export file="{backup_name}"'
|
||||
)
|
||||
print(f" Erzeuge Backup/Export auf crs326-core ...")
|
||||
subprocess.run(create_cmd, check=True)
|
||||
|
||||
local_backup = OUT_DIR / f"{backup_name}.backup"
|
||||
local_export = OUT_DIR / f"{backup_name}.rsc"
|
||||
|
||||
print(f" Lade {backup_name}.backup herunter ...")
|
||||
subprocess.run(scp_cmd(user, pw, f"{backup_name}.backup", local_backup), check=True)
|
||||
|
||||
print(f" Lade {backup_name}.rsc herunter ...")
|
||||
subprocess.run(scp_cmd(user, pw, f"{backup_name}.rsc", local_export), check=True)
|
||||
|
||||
backup_size = local_backup.stat().st_size
|
||||
export_size = local_export.stat().st_size
|
||||
print(f" OK: {local_backup.name} ({backup_size} Bytes)")
|
||||
print(f" OK: {local_export.name} ({export_size} Bytes)")
|
||||
|
||||
if backup_size < 1000:
|
||||
print(" WARN: Backup-Datei auffällig klein!")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
59
routeros/convert-ap1-leases.py
Normal file
59
routeros/convert-ap1-leases.py
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Konvertiert ap1-leases-export.json in RouterOS-Befehle für crs326-core.
|
||||
|
||||
Nur dynamic=false-Leases werden übernommen, mit server-Namen 1:1 übernommen
|
||||
(dhcp-v10..dhcp-v99), disabled=yes, damit sie im Cutover zusammen mit den
|
||||
DHCP-Servern enabled werden.
|
||||
|
||||
Ausgabe: routeros/ap1-leases-to-core.rsc
|
||||
"""
|
||||
import json
|
||||
import pathlib
|
||||
import shlex
|
||||
|
||||
LEASES = pathlib.Path(__file__).with_name("ap1-leases-export.json")
|
||||
OUT = pathlib.Path(__file__).with_name("ap1-leases-to-core.rsc")
|
||||
|
||||
|
||||
def escape(s):
|
||||
# RouterOS comment darf Leerzeichen enthalten; wir quotieren mit doppelten Anführungszeichen
|
||||
return s.replace('\\', '\\\\').replace('"', '\\"')
|
||||
|
||||
|
||||
def main():
|
||||
leases = json.loads(LEASES.read_text())
|
||||
static = [l for l in leases if str(l.get("dynamic")).lower() == "false"]
|
||||
lines = [
|
||||
"# ap1 static leases -> crs326-core (STAGED, disabled=yes)",
|
||||
f"# Quelle: {LEASES.name} | {len(static)} statische Leases",
|
||||
"",
|
||||
]
|
||||
for l in sorted(static, key=lambda x: (x.get("server", ""), x.get("address", ""))):
|
||||
server = l.get("server", "")
|
||||
if not server.startswith("dhcp-v"):
|
||||
lines.append(f"# SKIP unbekannter server '{server}': {l.get('address')} {l.get('mac-address')}")
|
||||
continue
|
||||
mac = l.get("mac-address", "")
|
||||
addr = l.get("address", "")
|
||||
client_id = l.get("client-id", "")
|
||||
hostname = l.get("host-name", "")
|
||||
dhcp_option = l.get("dhcp-option", "")
|
||||
comment_parts = [hostname, l.get("comment", "")]
|
||||
comment = " / ".join(p for p in comment_parts if p).strip()
|
||||
if not comment:
|
||||
comment = f"lease {addr}"
|
||||
cmd = f'/ip/dhcp-server/lease add server={server} mac-address="{mac}" address="{addr}"'
|
||||
if client_id:
|
||||
cmd += f' client-id="{client_id}"'
|
||||
if dhcp_option:
|
||||
cmd += f' dhcp-option={shlex.quote(dhcp_option)}'
|
||||
cmd += f' comment="{escape(comment)}" disabled=yes'
|
||||
lines.append(cmd)
|
||||
lines.append("")
|
||||
lines.append("# Cutover: /ip/dhcp-server/lease/enable [find comment~\"ap1 lease\"]")
|
||||
OUT.write_text("\n".join(lines) + "\n")
|
||||
print(f"{OUT} written with {len(static)} static lease commands")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
BIN
routeros/crs326-core-pre-cutover-20260806-041719.backup
Normal file
BIN
routeros/crs326-core-pre-cutover-20260806-041719.backup
Normal file
Binary file not shown.
92
routeros/crs326-core-pre-cutover-20260806-041719.rsc
Normal file
92
routeros/crs326-core-pre-cutover-20260806-041719.rsc
Normal file
@@ -0,0 +1,92 @@
|
||||
# 2025-09-04 23:25:19 by RouterOS 7.19.5
|
||||
# software id = 4W04-URHT
|
||||
#
|
||||
# model = CRS326-24G-2S+
|
||||
# serial number = HKA0AREXJFM
|
||||
/interface bridge
|
||||
add admin-mac=04:F4:1C:B4:17:76 auto-mac=no comment=defconf name=bridge \
|
||||
vlan-filtering=yes
|
||||
/interface ethernet
|
||||
set [ find default-name=ether3 ] disabled=yes
|
||||
set [ find default-name=ether4 ] disabled=yes
|
||||
set [ find default-name=ether5 ] disabled=yes
|
||||
set [ find default-name=ether6 ] disabled=yes
|
||||
set [ find default-name=ether7 ] disabled=yes
|
||||
set [ find default-name=ether8 ] disabled=yes
|
||||
set [ find default-name=ether9 ] disabled=yes
|
||||
set [ find default-name=ether10 ] disabled=yes
|
||||
set [ find default-name=ether11 ] disabled=yes
|
||||
set [ find default-name=ether12 ] disabled=yes
|
||||
set [ find default-name=ether13 ] disabled=yes
|
||||
set [ find default-name=ether14 ] disabled=yes
|
||||
set [ find default-name=ether15 ] disabled=yes
|
||||
set [ find default-name=ether16 ] disabled=yes
|
||||
set [ find default-name=ether17 ] disabled=yes
|
||||
set [ find default-name=ether18 ] disabled=yes
|
||||
set [ find default-name=ether19 ] disabled=yes
|
||||
set [ find default-name=ether20 ] disabled=yes
|
||||
set [ find default-name=ether21 ] disabled=yes
|
||||
set [ find default-name=ether22 ] disabled=yes
|
||||
set [ find default-name=ether23 ] disabled=yes
|
||||
set [ find default-name=ether24 ] disabled=yes
|
||||
set [ find default-name=sfp-sfpplus1 ] disabled=yes
|
||||
set [ find default-name=sfp-sfpplus2 ] disabled=yes
|
||||
/interface vlan
|
||||
add interface=bridge name=vlan99 vlan-id=99
|
||||
/port
|
||||
set 0 name=serial0
|
||||
/interface bridge port
|
||||
add bridge=bridge comment=defconf interface=ether1
|
||||
add bridge=bridge comment=defconf interface=ether2
|
||||
add bridge=bridge comment=defconf interface=ether3
|
||||
add bridge=bridge comment=defconf interface=ether4
|
||||
add bridge=bridge comment=defconf interface=ether5
|
||||
add bridge=bridge comment=defconf interface=ether6
|
||||
add bridge=bridge comment=defconf interface=ether7
|
||||
add bridge=bridge comment=defconf interface=ether8
|
||||
add bridge=bridge comment=defconf interface=ether9
|
||||
add bridge=bridge comment=defconf interface=ether10
|
||||
add bridge=bridge comment=defconf interface=ether11
|
||||
add bridge=bridge comment=defconf interface=ether12
|
||||
add bridge=bridge comment=defconf interface=ether13
|
||||
add bridge=bridge comment=defconf interface=ether14
|
||||
add bridge=bridge comment=defconf interface=ether15
|
||||
add bridge=bridge comment=defconf interface=ether16
|
||||
add bridge=bridge comment=defconf interface=ether17
|
||||
add bridge=bridge comment=defconf interface=ether18
|
||||
add bridge=bridge comment=defconf interface=ether19
|
||||
add bridge=bridge comment=defconf interface=ether20
|
||||
add bridge=bridge comment=defconf interface=ether21
|
||||
add bridge=bridge comment=defconf interface=ether22
|
||||
add bridge=bridge comment=defconf interface=ether23
|
||||
add bridge=bridge comment=defconf interface=ether24
|
||||
add bridge=bridge comment=defconf interface=sfp-sfpplus1
|
||||
add bridge=bridge comment=defconf interface=sfp-sfpplus2
|
||||
/interface bridge vlan
|
||||
add bridge=bridge untagged=ether1,ether2 vlan-ids=1
|
||||
add bridge=bridge tagged=ether1,ether2 vlan-ids=10
|
||||
add bridge=bridge tagged=ether1,ether2 vlan-ids=20
|
||||
add bridge=bridge tagged=ether1,ether2 vlan-ids=30
|
||||
add bridge=bridge tagged=ether1,ether2 vlan-ids=40
|
||||
add bridge=bridge tagged=ether1,ether2 vlan-ids=50
|
||||
add bridge=bridge tagged=ether1,ether2 vlan-ids=90
|
||||
add bridge=bridge tagged=ether1,ether2,bridge vlan-ids=99
|
||||
add bridge=bridge tagged=ether1,ether2 vlan-ids=100
|
||||
/ip address
|
||||
add address=10.40.41.211/24 comment=TP15-bringup-vlan1 interface=bridge \
|
||||
network=10.40.41.0
|
||||
add address=10.40.99.11/24 comment=TP15-mgmt-target interface=vlan99 network=\
|
||||
10.40.99.0
|
||||
/ip route
|
||||
add comment=TP15-bringup dst-address=0.0.0.0/0 gateway=10.40.41.1
|
||||
/ip service
|
||||
set ftp disabled=yes
|
||||
set ssh address=10.40.0.0/16
|
||||
set telnet disabled=yes
|
||||
set www address=10.40.0.0/16
|
||||
set api address=10.40.0.0/16
|
||||
set api-ssl disabled=yes
|
||||
/system identity
|
||||
set name=crs326-core
|
||||
/system routerboard settings
|
||||
set enter-setup-on=delete-key
|
||||
314
routeros/crs326-core-pre-cutover-20260806-073712-fixed.rsc
Normal file
314
routeros/crs326-core-pre-cutover-20260806-073712-fixed.rsc
Normal file
@@ -0,0 +1,314 @@
|
||||
# 2025-09-05 02:45:12 by RouterOS 7.19.5
|
||||
# software id = 4W04-URHT
|
||||
#
|
||||
# model = CRS326-24G-2S+
|
||||
# serial number = HKA0AREXJFM
|
||||
/interface bridge
|
||||
set [find name=bridge] admin-mac=04:F4:1C:B4:17:76 auto-mac=no vlan-filtering=yes
|
||||
/interface ethernet
|
||||
set [ find default-name=sfp-sfpplus1 ] disabled=yes
|
||||
set [ find default-name=sfp-sfpplus2 ] disabled=yes
|
||||
/interface wireguard
|
||||
add comment="TP10 Multi-Site VPN Hub (FM/DW spokes)" disabled=yes \
|
||||
listen-port=51821 mtu=1412 name=wg-hub
|
||||
/interface vlan
|
||||
add comment=MAIN interface=bridge name=vlan10 vlan-id=10
|
||||
add comment=INFRA interface=bridge name=vlan20 vlan-id=20
|
||||
add comment=IOT interface=bridge name=vlan30 vlan-id=30
|
||||
add comment=MEDIA interface=bridge name=vlan40 vlan-id=40
|
||||
add comment=UNTRUSTED interface=bridge name=vlan50 vlan-id=50
|
||||
add comment=GUEST interface=bridge name=vlan90 vlan-id=90
|
||||
add interface=bridge name=vlan99 vlan-id=99
|
||||
add comment=WAN interface=bridge name=vlan100 vlan-id=100
|
||||
/interface list
|
||||
add comment=TP15 name=WAN
|
||||
add comment=TP15 name=LAN
|
||||
/ip pool
|
||||
add name=pool-v10 ranges=10.40.10.100-10.40.10.200
|
||||
add name=pool-v20 ranges=10.40.20.100-10.40.20.200
|
||||
add name=pool-v30 ranges=10.40.30.100-10.40.30.250
|
||||
add name=pool-v40 ranges=10.40.40.100-10.40.40.200
|
||||
add name=pool-v50 ranges=10.40.50.100-10.40.50.200
|
||||
add name=pool-v90 ranges=10.40.90.100-10.40.90.200
|
||||
add name=pool-v99 ranges=10.40.99.100-10.40.99.200
|
||||
/ip dhcp-server
|
||||
add address-pool=pool-v10 comment=MAIN disabled=yes interface=vlan10 \
|
||||
lease-time=1d name=dhcp-v10
|
||||
add address-pool=pool-v20 comment=INFRA disabled=yes interface=vlan20 \
|
||||
lease-time=1d name=dhcp-v20
|
||||
add address-pool=pool-v30 comment=IOT disabled=yes interface=vlan30 \
|
||||
lease-time=1d name=dhcp-v30
|
||||
add address-pool=pool-v40 comment=MEDIA disabled=yes interface=vlan40 \
|
||||
lease-time=1d name=dhcp-v40
|
||||
add address-pool=pool-v50 comment=UNTRUSTED disabled=yes interface=vlan50 \
|
||||
lease-time=1d name=dhcp-v50
|
||||
add address-pool=pool-v90 comment=GUEST disabled=yes interface=vlan90 \
|
||||
lease-time=12h name=dhcp-v90
|
||||
add address-pool=pool-v99 comment=MGMT disabled=yes interface=vlan99 \
|
||||
lease-time=1d name=dhcp-v99
|
||||
/port
|
||||
set 0 name=serial0
|
||||
/interface bridge port
|
||||
set [find interface=ether2] pvid=40
|
||||
set [find interface=ether3] pvid=40
|
||||
set [find interface=ether5] pvid=40
|
||||
/interface bridge vlan
|
||||
add bridge=bridge untagged=ether1,ether2 vlan-ids=1
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 vlan-ids=10
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 vlan-ids=20
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 vlan-ids=30
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 untagged=ether2,ether3,ether5 \
|
||||
vlan-ids=40
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 vlan-ids=50
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 vlan-ids=90
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 vlan-ids=99
|
||||
add bridge=bridge tagged=ether1 untagged=ether16 vlan-ids=100
|
||||
/interface list member
|
||||
add interface=vlan100 list=WAN
|
||||
add interface=vlan10 list=LAN
|
||||
add interface=vlan20 list=LAN
|
||||
add interface=vlan30 list=LAN
|
||||
add interface=vlan40 list=LAN
|
||||
add interface=vlan50 list=LAN
|
||||
add interface=vlan90 list=LAN
|
||||
add interface=vlan99 list=LAN
|
||||
/interface wireguard peers
|
||||
add allowed-address=10.101.0.0/24 endpoint-address=\
|
||||
abxhutfgsid9snmy.myfritz.net endpoint-port=52476 interface=wg-hub name=fm \
|
||||
public-key="dzRY0lnnUygijChWe5wXZmXPeNcbdALpqBptA3fyiVE="
|
||||
add allowed-address=10.95.10.0/24 interface=wg-hub name=dw public-key=\
|
||||
"FqYZLztQ/qME5VDie5QLGH++5299WJiE1dPpQnPbzUw="
|
||||
/ip address
|
||||
add address=10.40.41.211/24 comment=TP15-bringup-vlan1 interface=bridge \
|
||||
network=10.40.41.0
|
||||
add address=10.40.99.11/24 comment=TP15-mgmt-target interface=vlan99 network=\
|
||||
10.40.99.0
|
||||
add address=10.40.10.1/24 comment="L3 SVI VLAN10" disabled=yes interface=\
|
||||
vlan10 network=10.40.10.0
|
||||
add address=10.40.20.1/24 comment="L3 SVI VLAN20" disabled=yes interface=\
|
||||
vlan20 network=10.40.20.0
|
||||
add address=10.40.30.1/24 comment="L3 SVI VLAN30" disabled=yes interface=\
|
||||
vlan30 network=10.40.30.0
|
||||
add address=10.40.40.1/24 comment="L3 SVI VLAN40" disabled=yes interface=\
|
||||
vlan40 network=10.40.40.0
|
||||
add address=10.40.50.1/24 comment="L3 SVI VLAN50" disabled=yes interface=\
|
||||
vlan50 network=10.40.50.0
|
||||
add address=10.40.90.1/24 comment="L3 SVI VLAN90" disabled=yes interface=\
|
||||
vlan90 network=10.40.90.0
|
||||
add address=10.40.99.1/24 comment="Mgmt SVI (VLAN99)" disabled=yes interface=\
|
||||
vlan99 network=10.40.99.0
|
||||
/ip dhcp-client
|
||||
add comment="TP15 WAN Liwest (Arris)" disabled=yes interface=vlan100 \
|
||||
use-peer-dns=no
|
||||
/ip dhcp-server lease
|
||||
add address=10.40.10.196 client-id=1:f2:62:4c:e1:af:9 comment=iPhone \
|
||||
disabled=yes mac-address=F2:62:4C:E1:AF:09 server=dhcp-v10
|
||||
add address=10.40.20.10 comment=nas-bf disabled=yes mac-address=\
|
||||
90:09:D0:58:20:F9 server=dhcp-v20
|
||||
add address=10.40.30.150 client-id=1:fc:ee:11:3:32:26 comment=\
|
||||
"ingenic-3226 / Ender3V3KE-3226" disabled=yes mac-address=\
|
||||
FC:EE:11:03:32:26 server=dhcp-v30
|
||||
add address=10.40.10.82 client-id=1:56:71:6c:22:e6:a9 comment=Mac disabled=\
|
||||
yes mac-address=56:71:6C:22:E6:A9 server=dhcp-v10
|
||||
add address=10.40.30.180 client-id=1:e4:bc:96:1f:b2:81 comment=\
|
||||
"espressif / Airfryer" disabled=yes mac-address=E4:BC:96:1F:B2:81 server=\
|
||||
dhcp-v30
|
||||
add address=10.40.30.202 comment=shelly-s22_kueche_steckdose3-2 disabled=yes \
|
||||
mac-address=A0:85:E3:C8:65:34 server=dhcp-v30
|
||||
add address=10.40.30.203 comment=shelly-s23_dieleug-wohnzimmer_licht \
|
||||
disabled=yes mac-address=AC:15:18:7B:62:20 server=dhcp-v30
|
||||
add address=10.40.30.204 comment=shelly-s24_bad_spiegelschrank disabled=yes \
|
||||
mac-address=14:33:5C:D8:2D:7C server=dhcp-v30
|
||||
add address=10.40.30.205 comment=shelly-s25_bad_lichtschalter disabled=yes \
|
||||
mac-address=98:A3:16:79:38:50 server=dhcp-v30
|
||||
add address=10.40.30.206 comment=shelly-s20_kueche_steckdosen2 disabled=yes \
|
||||
mac-address=98:A3:16:7C:5F:EC server=dhcp-v30
|
||||
add address=10.40.30.207 comment=shelly-s21_kueche_steckdosen4 disabled=yes \
|
||||
mac-address=20:6E:F1:01:F9:F8 server=dhcp-v30
|
||||
add address=10.40.30.208 comment=shelly-s1_weihnachten_kueche disabled=yes \
|
||||
mac-address=E4:B0:63:D7:C7:A4 server=dhcp-v30
|
||||
add address=10.40.30.209 comment=shelly-s2_weihnachten_terrasse disabled=yes \
|
||||
mac-address=28:37:2F:36:F4:7C server=dhcp-v30
|
||||
add address=10.40.30.210 comment=shelly-s3_weihnachten_kinderzimmer disabled=\
|
||||
yes mac-address=E4:B0:63:E4:EF:7C server=dhcp-v30
|
||||
add address=10.40.30.211 comment=shelly-s4_kueche_mikrowelle disabled=yes \
|
||||
mac-address=E4:B0:63:E4:0F:30 server=dhcp-v30
|
||||
add address=10.40.30.212 comment=shelly-s5_kueche_backofen disabled=yes \
|
||||
mac-address=D8:85:AC:0C:5C:C8 server=dhcp-v30
|
||||
add address=10.40.30.213 comment=shelly-s6_kueche_kuehlschrank disabled=yes \
|
||||
mac-address=D0:CF:13:D8:18:FC server=dhcp-v30
|
||||
add address=10.40.30.214 comment=shelly-s7_kueche_tiefkuehlschrank disabled=\
|
||||
yes mac-address=D0:CF:13:D9:94:E8 server=dhcp-v30
|
||||
add address=10.40.30.215 comment=shelly-s8_kueche_geschirrspueler disabled=\
|
||||
yes mac-address=E4:B0:63:FA:FD:E0 server=dhcp-v30
|
||||
add address=10.40.30.216 comment=shelly-s9_wohnzimmer_sideboard disabled=yes \
|
||||
mac-address=E8:F6:0A:61:88:08 server=dhcp-v30
|
||||
add address=10.40.30.217 comment=shelly-s10_bad_sonos disabled=yes \
|
||||
mac-address=E4:B0:63:FC:57:E4 server=dhcp-v30
|
||||
add address=10.40.30.218 comment=shelly-s11_kinderzimmer_sonos disabled=yes \
|
||||
mac-address=E4:B0:63:FA:6C:00 server=dhcp-v30
|
||||
add address=10.40.30.219 comment=shelly-s12_dieleug_steckdosen disabled=yes \
|
||||
mac-address=48:F6:EE:C8:E6:AC server=dhcp-v30
|
||||
add address=10.40.30.220 comment=shelly-s13_arbeitszimmer_technik disabled=\
|
||||
yes mac-address=48:F6:EE:DD:6A:F4 server=dhcp-v30
|
||||
add address=10.40.30.221 comment=shelly-s14_schlafzimmer_bett disabled=yes \
|
||||
mac-address=E4:B0:63:FC:59:48 server=dhcp-v30
|
||||
add address=10.40.30.222 comment=shelly-s15_technik_pve disabled=yes \
|
||||
mac-address=E4:B0:63:FA:D5:34 server=dhcp-v30
|
||||
add address=10.40.30.223 comment=shelly-s16_wohnzimmer_steckdosen disabled=\
|
||||
yes mac-address=10:20:BA:FA:F5:40 server=dhcp-v30
|
||||
add address=10.40.30.224 comment=shelly-s17_bad_steckdosen disabled=yes \
|
||||
mac-address=10:20:BA:FB:6D:64 server=dhcp-v30
|
||||
add address=10.40.30.225 comment=shelly-s18_kueche_steckdosen1 disabled=yes \
|
||||
mac-address=48:F6:EE:CC:16:E4 server=dhcp-v30
|
||||
add address=10.40.30.226 comment=shelly-s19_kueche_steckdosen3 disabled=yes \
|
||||
mac-address=10:20:BA:FB:70:FC server=dhcp-v30
|
||||
add address=10.40.30.227 comment="SwitchBot-floor-lamp / switchbot-floorlamp" \
|
||||
disabled=yes mac-address=B8:F8:62:09:F2:04 server=dhcp-v30
|
||||
add address=10.40.30.228 comment=\
|
||||
"Twinkly-2CA789 / Twinkly_Weihnachtsgirlande" disabled=yes mac-address=\
|
||||
98:F4:AB:2C:A7:88 server=dhcp-v30
|
||||
add address=10.40.30.230 comment=Withings_waage disabled=yes mac-address=\
|
||||
00:24:E4:40:2A:72 server=dhcp-v30
|
||||
add address=10.40.30.231 comment=Withings_blutdruck disabled=yes mac-address=\
|
||||
A4:7E:FA:18:2C:64 server=dhcp-v30
|
||||
add address=10.40.30.232 comment=pve-homematic-raspi-ccu disabled=yes \
|
||||
mac-address=BC:24:11:8E:0A:57 server=dhcp-v30
|
||||
add address=10.40.30.233 comment=shelly-s26_bad_luefter disabled=yes \
|
||||
mac-address=98:A3:16:7A:A3:54 server=dhcp-v30
|
||||
add address=10.40.30.236 comment=lichterkette disabled=yes mac-address=\
|
||||
A4:F0:0F:5F:D0:EC server=dhcp-v30
|
||||
add address=10.40.30.237 comment=lichterkette-mini disabled=yes mac-address=\
|
||||
24:DC:C3:9B:89:64 server=dhcp-v30
|
||||
add address=10.40.30.241 comment=NukiSmartlock disabled=yes mac-address=\
|
||||
28:DB:A7:09:7B:54 server=dhcp-v30
|
||||
add address=10.40.30.244 comment=NukiBridge disabled=yes mac-address=\
|
||||
24:62:AB:B1:63:F4 server=dhcp-v30
|
||||
add address=10.40.30.5 comment="P750W / P750W" disabled=yes mac-address=\
|
||||
4C:EB:BD:E3:25:F2 server=dhcp-v30
|
||||
add address=10.40.30.8 comment="DTUBI-414392337823 / DTUBI-414392337823" \
|
||||
disabled=yes mac-address=54:F2:9F:12:51:F0 server=dhcp-v30
|
||||
add address=10.40.40.11 comment=tv disabled=yes mac-address=70:AF:24:B8:C9:86 \
|
||||
server=dhcp-v40
|
||||
add address=10.40.40.191 client-id=1:34:7e:5c:32:37:96 comment=SonosZP \
|
||||
disabled=yes mac-address=34:7E:5C:32:37:96 server=dhcp-v40
|
||||
add address=10.40.40.192 client-id=1:34:7e:5c:32:33:b8 comment=SonosZP \
|
||||
disabled=yes mac-address=34:7E:5C:32:33:B8 server=dhcp-v40
|
||||
add address=10.40.40.193 client-id=1:78:28:ca:80:2a:f6 comment=SonosZP \
|
||||
disabled=yes mac-address=78:28:CA:80:2A:F6 server=dhcp-v40
|
||||
add address=10.40.40.194 client-id=1:48:a6:b8:14:fe:d0 comment=SonosZP \
|
||||
disabled=yes mac-address=48:A6:B8:14:FE:D0 server=dhcp-v40
|
||||
add address=10.40.40.195 client-id=1:78:28:ca:82:16:c2 comment=SonosZP \
|
||||
disabled=yes mac-address=78:28:CA:82:16:C2 server=dhcp-v40
|
||||
add address=10.40.40.196 client-id=1:48:a6:b8:16:38:ae comment=SonosZP \
|
||||
disabled=yes mac-address=48:A6:B8:16:38:AE server=dhcp-v40
|
||||
add address=10.40.40.197 client-id=1:48:a6:b8:14:fe:f2 comment=SonosZP \
|
||||
disabled=yes mac-address=48:A6:B8:14:FE:F2 server=dhcp-v40
|
||||
add address=10.40.40.198 comment="SonosZP / SonosTerrasse" disabled=yes \
|
||||
mac-address=78:28:CA:D2:0D:AC server=dhcp-v40
|
||||
add address=10.40.40.199 client-id=1:48:a6:b8:b:63:10 comment=SonosZP \
|
||||
disabled=yes mac-address=48:A6:B8:0B:63:10 server=dhcp-v40
|
||||
add address=10.40.40.200 client-id=1:48:a6:b8:69:69:7b comment=SonosZP \
|
||||
disabled=yes mac-address=48:A6:B8:69:69:7B server=dhcp-v40
|
||||
add address=10.40.40.201 client-id=1:94:9f:3e:49:59:ee comment=SonosZP \
|
||||
disabled=yes mac-address=94:9F:3E:49:59:EE server=dhcp-v40
|
||||
/ip dhcp-server network
|
||||
add address=10.40.10.0/24 dns-server=10.40.10.1 domain=bf.lan gateway=\
|
||||
10.40.10.1
|
||||
add address=10.40.20.0/24 dns-server=10.40.20.1 domain=bf.lan gateway=\
|
||||
10.40.20.1
|
||||
add address=10.40.30.0/24 dns-server=10.40.30.1 domain=bf.lan gateway=\
|
||||
10.40.30.1
|
||||
add address=10.40.40.0/24 dns-server=10.40.40.1 domain=bf.lan gateway=\
|
||||
10.40.40.1
|
||||
add address=10.40.50.0/24 dns-server=10.40.50.1 domain=bf.lan gateway=\
|
||||
10.40.50.1
|
||||
add address=10.40.90.0/24 dns-server=10.40.90.1 domain=bf.lan gateway=\
|
||||
10.40.90.1
|
||||
add address=10.40.99.0/24 dns-server=10.40.99.1 domain=bf.lan gateway=\
|
||||
10.40.99.1
|
||||
/ip dns
|
||||
set allow-remote-requests=yes mdns-repeat-ifaces=\
|
||||
vlan10,vlan20,vlan40,vlan30,vlan90 servers=1.1.1.1 use-doh-server=\
|
||||
https://px35ynlol3.cloudflare-gateway.com/dns-query verify-doh-cert=yes
|
||||
/ip dns static
|
||||
add address=10.40.99.1 comment="core = GW/Router" name=router.lan type=A
|
||||
add address=10.40.99.3 comment="ap1 = reiner AP" name=ap1.bf.lan type=A
|
||||
add address=10.40.99.2 comment="ap2 = reiner AP" name=ap2.bf.lan type=A
|
||||
add address=10.40.99.1 comment="crs326-core (L3)" name=core.bf.lan type=A
|
||||
add address=10.40.99.12 comment=crs326-branch name=branch.bf.lan type=A
|
||||
add address=10.40.20.167 name=macmini.bf.lan type=A
|
||||
add address=10.40.20.100 name=pve.bf.lan type=A
|
||||
add address=10.40.20.173 name=pve-mcp.bf.lan type=A
|
||||
add address=10.40.20.10 name=nas.bf.lan type=A
|
||||
add address=10.40.20.126 name=docker.bf.lan type=A
|
||||
add address=10.40.20.20 name=platform-pg.bf.lan type=A
|
||||
/ip firewall filter
|
||||
add action=accept chain=forward comment="defconf: accept est,rel,untracked" \
|
||||
connection-state=established,related,untracked
|
||||
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \
|
||||
connection-state=established,related hw-offload=yes
|
||||
add action=drop chain=forward comment="defconf: drop invalid" \
|
||||
connection-state=invalid
|
||||
add action=drop chain=forward comment="defconf: drop WAN !dstnat" \
|
||||
connection-nat-state=!dstnat in-interface-list=WAN
|
||||
add action=accept chain=forward comment="TP10: allow from WG spokes (FM/DW)" \
|
||||
in-interface=wg-hub
|
||||
add action=accept chain=forward comment="TP10: allow to WG spokes (FM/DW)" \
|
||||
out-interface=wg-hub
|
||||
add action=accept chain=forward comment="TP5: MAIN->MEDIA" in-interface=\
|
||||
vlan10 out-interface=vlan40
|
||||
add action=accept chain=forward comment="TP5: MEDIA->MAIN" in-interface=\
|
||||
vlan40 out-interface=vlan10
|
||||
add action=accept chain=forward comment="TP5: INFRA->MEDIA" in-interface=\
|
||||
vlan20 out-interface=vlan40
|
||||
add action=accept chain=forward comment="TP5: MEDIA->INFRA" in-interface=\
|
||||
vlan40 out-interface=vlan20
|
||||
add action=accept chain=forward comment="TP5: GUEST->MEDIA" in-interface=\
|
||||
vlan90 out-interface=vlan40
|
||||
add action=accept chain=forward comment="TP5: MEDIA->GUEST" in-interface=\
|
||||
vlan40 out-interface=vlan90
|
||||
add action=accept chain=input comment=TP10-seal-est connection-state=\
|
||||
established,related,untracked
|
||||
add action=drop chain=input comment=TP10-seal-inv connection-state=invalid
|
||||
add action=accept chain=input comment="TP10: WG hub listen" dst-port=51821 \
|
||||
protocol=udp
|
||||
add action=accept chain=input comment=TP10-seal-dhcp dst-port=68 \
|
||||
in-interface-list=WAN protocol=udp
|
||||
add action=accept chain=input comment=TP10-seal-icmp protocol=icmp
|
||||
add action=accept chain=input comment=TP10-seal-lan in-interface-list=LAN
|
||||
add action=drop chain=input comment=TP10-seal-wandrop in-interface-list=WAN
|
||||
add action=accept chain=input comment="TP5: mDNS in vlan10" dst-port=5353 \
|
||||
in-interface=vlan10 protocol=udp
|
||||
add action=accept chain=input comment="TP5: mDNS in vlan40" dst-port=5353 \
|
||||
in-interface=vlan40 protocol=udp
|
||||
add action=accept chain=input comment="TP5: mDNS in vlan20" dst-port=5353 \
|
||||
in-interface=vlan20 protocol=udp
|
||||
add action=accept chain=input comment="TP5: mDNS in vlan30" dst-port=5353 \
|
||||
in-interface=vlan30 protocol=udp
|
||||
add action=accept chain=input comment="TP5: mDNS in vlan90" dst-port=5353 \
|
||||
in-interface=vlan90 protocol=udp
|
||||
/ip firewall nat
|
||||
add action=accept chain=srcnat comment=\
|
||||
"TP4: no-NAT inter-VLAN (vor masquerade)" dst-address=10.40.0.0/16
|
||||
add action=masquerade chain=srcnat comment="defconf: masquerade WAN" \
|
||||
out-interface-list=WAN
|
||||
/ip hotspot profile
|
||||
set [ find default=yes ] html-directory=hotspot
|
||||
/ip route
|
||||
add comment=TP15-bringup dst-address=0.0.0.0/0 gateway=10.40.41.1
|
||||
add comment="TP10: FM spoke -> wg-hub" dst-address=10.101.0.0/24 gateway=\
|
||||
wg-hub
|
||||
add comment="TP10: DW spoke -> wg-hub" dst-address=10.95.10.0/24 gateway=\
|
||||
wg-hub
|
||||
/ip service
|
||||
set ftp disabled=yes
|
||||
set ssh address=10.40.0.0/16
|
||||
set telnet disabled=yes
|
||||
set www address=10.40.0.0/16
|
||||
set api address=10.40.0.0/16
|
||||
set api-ssl disabled=yes
|
||||
/system identity
|
||||
set name=crs326-core
|
||||
/system routerboard settings
|
||||
set enter-setup-on=delete-key
|
||||
BIN
routeros/crs326-core-pre-cutover-20260806-073712.backup
Normal file
BIN
routeros/crs326-core-pre-cutover-20260806-073712.backup
Normal file
Binary file not shown.
360
routeros/crs326-core-pre-cutover-20260806-073712.rsc
Normal file
360
routeros/crs326-core-pre-cutover-20260806-073712.rsc
Normal file
@@ -0,0 +1,360 @@
|
||||
# 2025-09-05 02:45:12 by RouterOS 7.19.5
|
||||
# software id = 4W04-URHT
|
||||
#
|
||||
# model = CRS326-24G-2S+
|
||||
# serial number = HKA0AREXJFM
|
||||
/interface bridge
|
||||
add admin-mac=04:F4:1C:B4:17:76 auto-mac=no comment=defconf name=bridge \
|
||||
vlan-filtering=yes
|
||||
/interface ethernet
|
||||
set [ find default-name=ether3 ] disabled=yes
|
||||
set [ find default-name=ether4 ] disabled=yes
|
||||
set [ find default-name=ether5 ] disabled=yes
|
||||
set [ find default-name=ether6 ] disabled=yes
|
||||
set [ find default-name=ether7 ] disabled=yes
|
||||
set [ find default-name=ether8 ] disabled=yes
|
||||
set [ find default-name=ether9 ] disabled=yes
|
||||
set [ find default-name=ether10 ] disabled=yes
|
||||
set [ find default-name=ether11 ] disabled=yes
|
||||
set [ find default-name=ether12 ] disabled=yes
|
||||
set [ find default-name=ether13 ] disabled=yes
|
||||
set [ find default-name=ether14 ] disabled=yes
|
||||
set [ find default-name=ether15 ] disabled=yes
|
||||
set [ find default-name=ether16 ] disabled=yes
|
||||
set [ find default-name=ether17 ] disabled=yes
|
||||
set [ find default-name=ether18 ] disabled=yes
|
||||
set [ find default-name=ether19 ] disabled=yes
|
||||
set [ find default-name=ether20 ] disabled=yes
|
||||
set [ find default-name=ether21 ] disabled=yes
|
||||
set [ find default-name=ether22 ] disabled=yes
|
||||
set [ find default-name=ether23 ] disabled=yes
|
||||
set [ find default-name=ether24 ] disabled=yes
|
||||
set [ find default-name=sfp-sfpplus1 ] disabled=yes
|
||||
set [ find default-name=sfp-sfpplus2 ] disabled=yes
|
||||
/interface wireguard
|
||||
add comment="TP10 Multi-Site VPN Hub (FM/DW spokes)" disabled=yes \
|
||||
listen-port=51821 mtu=1412 name=wg-hub
|
||||
/interface vlan
|
||||
add comment=MAIN interface=bridge name=vlan10 vlan-id=10
|
||||
add comment=INFRA interface=bridge name=vlan20 vlan-id=20
|
||||
add comment=IOT interface=bridge name=vlan30 vlan-id=30
|
||||
add comment=MEDIA interface=bridge name=vlan40 vlan-id=40
|
||||
add comment=UNTRUSTED interface=bridge name=vlan50 vlan-id=50
|
||||
add comment=GUEST interface=bridge name=vlan90 vlan-id=90
|
||||
add interface=bridge name=vlan99 vlan-id=99
|
||||
add comment=WAN interface=bridge name=vlan100 vlan-id=100
|
||||
/interface list
|
||||
add comment=TP15 name=WAN
|
||||
add comment=TP15 name=LAN
|
||||
/ip pool
|
||||
add name=pool-v10 ranges=10.40.10.100-10.40.10.200
|
||||
add name=pool-v20 ranges=10.40.20.100-10.40.20.200
|
||||
add name=pool-v30 ranges=10.40.30.100-10.40.30.250
|
||||
add name=pool-v40 ranges=10.40.40.100-10.40.40.200
|
||||
add name=pool-v50 ranges=10.40.50.100-10.40.50.200
|
||||
add name=pool-v90 ranges=10.40.90.100-10.40.90.200
|
||||
add name=pool-v99 ranges=10.40.99.100-10.40.99.200
|
||||
/ip dhcp-server
|
||||
add address-pool=pool-v10 comment=MAIN disabled=yes interface=vlan10 \
|
||||
lease-time=1d name=dhcp-v10
|
||||
add address-pool=pool-v20 comment=INFRA disabled=yes interface=vlan20 \
|
||||
lease-time=1d name=dhcp-v20
|
||||
add address-pool=pool-v30 comment=IOT disabled=yes interface=vlan30 \
|
||||
lease-time=1d name=dhcp-v30
|
||||
add address-pool=pool-v40 comment=MEDIA disabled=yes interface=vlan40 \
|
||||
lease-time=1d name=dhcp-v40
|
||||
add address-pool=pool-v50 comment=UNTRUSTED disabled=yes interface=vlan50 \
|
||||
lease-time=1d name=dhcp-v50
|
||||
add address-pool=pool-v90 comment=GUEST disabled=yes interface=vlan90 \
|
||||
lease-time=12h name=dhcp-v90
|
||||
add address-pool=pool-v99 comment=MGMT disabled=yes interface=vlan99 \
|
||||
lease-time=1d name=dhcp-v99
|
||||
/port
|
||||
set 0 name=serial0
|
||||
/interface bridge port
|
||||
add bridge=bridge comment=defconf interface=ether1
|
||||
add bridge=bridge comment=defconf interface=ether2 pvid=40
|
||||
add bridge=bridge comment=defconf interface=ether3 pvid=40
|
||||
add bridge=bridge comment=defconf interface=ether4
|
||||
add bridge=bridge comment=defconf interface=ether5 pvid=40
|
||||
add bridge=bridge comment=defconf interface=ether6
|
||||
add bridge=bridge comment=defconf interface=ether7
|
||||
add bridge=bridge comment=defconf interface=ether8
|
||||
add bridge=bridge comment=defconf interface=ether9
|
||||
add bridge=bridge comment=defconf interface=ether10
|
||||
add bridge=bridge comment=defconf interface=ether11
|
||||
add bridge=bridge comment=defconf interface=ether12
|
||||
add bridge=bridge comment=defconf interface=ether13
|
||||
add bridge=bridge comment=defconf interface=ether14
|
||||
add bridge=bridge comment=defconf interface=ether15
|
||||
add bridge=bridge comment=defconf interface=ether16
|
||||
add bridge=bridge comment=defconf interface=ether17
|
||||
add bridge=bridge comment=defconf interface=ether18
|
||||
add bridge=bridge comment=defconf interface=ether19
|
||||
add bridge=bridge comment=defconf interface=ether20
|
||||
add bridge=bridge comment=defconf interface=ether21
|
||||
add bridge=bridge comment=defconf interface=ether22
|
||||
add bridge=bridge comment=defconf interface=ether23
|
||||
add bridge=bridge comment=defconf interface=ether24
|
||||
add bridge=bridge comment=defconf interface=sfp-sfpplus1
|
||||
add bridge=bridge comment=defconf interface=sfp-sfpplus2
|
||||
/interface bridge vlan
|
||||
add bridge=bridge untagged=ether1,ether2 vlan-ids=1
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 vlan-ids=10
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 vlan-ids=20
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 vlan-ids=30
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 untagged=ether2,ether3,ether5 \
|
||||
vlan-ids=40
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 vlan-ids=50
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 vlan-ids=90
|
||||
add bridge=bridge tagged=ether1,ether4,ether8 vlan-ids=99
|
||||
add bridge=bridge tagged=ether1 untagged=ether16 vlan-ids=100
|
||||
/interface list member
|
||||
add interface=vlan100 list=WAN
|
||||
add interface=vlan10 list=LAN
|
||||
add interface=vlan20 list=LAN
|
||||
add interface=vlan30 list=LAN
|
||||
add interface=vlan40 list=LAN
|
||||
add interface=vlan50 list=LAN
|
||||
add interface=vlan90 list=LAN
|
||||
add interface=vlan99 list=LAN
|
||||
/interface wireguard peers
|
||||
add allowed-address=10.101.0.0/24 endpoint-address=\
|
||||
abxhutfgsid9snmy.myfritz.net endpoint-port=52476 interface=wg-hub name=fm \
|
||||
public-key="dzRY0lnnUygijChWe5wXZmXPeNcbdALpqBptA3fyiVE="
|
||||
add allowed-address=10.95.10.0/24 interface=wg-hub name=dw public-key=\
|
||||
"FqYZLztQ/qME5VDie5QLGH++5299WJiE1dPpQnPbzUw="
|
||||
/ip address
|
||||
add address=10.40.41.211/24 comment=TP15-bringup-vlan1 interface=bridge \
|
||||
network=10.40.41.0
|
||||
add address=10.40.99.11/24 comment=TP15-mgmt-target interface=vlan99 network=\
|
||||
10.40.99.0
|
||||
add address=10.40.10.1/24 comment="L3 SVI VLAN10" disabled=yes interface=\
|
||||
vlan10 network=10.40.10.0
|
||||
add address=10.40.20.1/24 comment="L3 SVI VLAN20" disabled=yes interface=\
|
||||
vlan20 network=10.40.20.0
|
||||
add address=10.40.30.1/24 comment="L3 SVI VLAN30" disabled=yes interface=\
|
||||
vlan30 network=10.40.30.0
|
||||
add address=10.40.40.1/24 comment="L3 SVI VLAN40" disabled=yes interface=\
|
||||
vlan40 network=10.40.40.0
|
||||
add address=10.40.50.1/24 comment="L3 SVI VLAN50" disabled=yes interface=\
|
||||
vlan50 network=10.40.50.0
|
||||
add address=10.40.90.1/24 comment="L3 SVI VLAN90" disabled=yes interface=\
|
||||
vlan90 network=10.40.90.0
|
||||
add address=10.40.99.1/24 comment="Mgmt SVI (VLAN99)" disabled=yes interface=\
|
||||
vlan99 network=10.40.99.0
|
||||
/ip dhcp-client
|
||||
add comment="TP15 WAN Liwest (Arris)" disabled=yes interface=vlan100 \
|
||||
use-peer-dns=no
|
||||
/ip dhcp-server lease
|
||||
add address=10.40.10.196 client-id=1:f2:62:4c:e1:af:9 comment=iPhone \
|
||||
disabled=yes mac-address=F2:62:4C:E1:AF:09 server=dhcp-v10
|
||||
add address=10.40.20.10 comment=nas-bf disabled=yes mac-address=\
|
||||
90:09:D0:58:20:F9 server=dhcp-v20
|
||||
add address=10.40.30.150 client-id=1:fc:ee:11:3:32:26 comment=\
|
||||
"ingenic-3226 / Ender3V3KE-3226" disabled=yes mac-address=\
|
||||
FC:EE:11:03:32:26 server=dhcp-v30
|
||||
add address=10.40.10.82 client-id=1:56:71:6c:22:e6:a9 comment=Mac disabled=\
|
||||
yes mac-address=56:71:6C:22:E6:A9 server=dhcp-v10
|
||||
add address=10.40.30.180 client-id=1:e4:bc:96:1f:b2:81 comment=\
|
||||
"espressif / Airfryer" disabled=yes mac-address=E4:BC:96:1F:B2:81 server=\
|
||||
dhcp-v30
|
||||
add address=10.40.30.202 comment=shelly-s22_kueche_steckdose3-2 disabled=yes \
|
||||
mac-address=A0:85:E3:C8:65:34 server=dhcp-v30
|
||||
add address=10.40.30.203 comment=shelly-s23_dieleug-wohnzimmer_licht \
|
||||
disabled=yes mac-address=AC:15:18:7B:62:20 server=dhcp-v30
|
||||
add address=10.40.30.204 comment=shelly-s24_bad_spiegelschrank disabled=yes \
|
||||
mac-address=14:33:5C:D8:2D:7C server=dhcp-v30
|
||||
add address=10.40.30.205 comment=shelly-s25_bad_lichtschalter disabled=yes \
|
||||
mac-address=98:A3:16:79:38:50 server=dhcp-v30
|
||||
add address=10.40.30.206 comment=shelly-s20_kueche_steckdosen2 disabled=yes \
|
||||
mac-address=98:A3:16:7C:5F:EC server=dhcp-v30
|
||||
add address=10.40.30.207 comment=shelly-s21_kueche_steckdosen4 disabled=yes \
|
||||
mac-address=20:6E:F1:01:F9:F8 server=dhcp-v30
|
||||
add address=10.40.30.208 comment=shelly-s1_weihnachten_kueche disabled=yes \
|
||||
mac-address=E4:B0:63:D7:C7:A4 server=dhcp-v30
|
||||
add address=10.40.30.209 comment=shelly-s2_weihnachten_terrasse disabled=yes \
|
||||
mac-address=28:37:2F:36:F4:7C server=dhcp-v30
|
||||
add address=10.40.30.210 comment=shelly-s3_weihnachten_kinderzimmer disabled=\
|
||||
yes mac-address=E4:B0:63:E4:EF:7C server=dhcp-v30
|
||||
add address=10.40.30.211 comment=shelly-s4_kueche_mikrowelle disabled=yes \
|
||||
mac-address=E4:B0:63:E4:0F:30 server=dhcp-v30
|
||||
add address=10.40.30.212 comment=shelly-s5_kueche_backofen disabled=yes \
|
||||
mac-address=D8:85:AC:0C:5C:C8 server=dhcp-v30
|
||||
add address=10.40.30.213 comment=shelly-s6_kueche_kuehlschrank disabled=yes \
|
||||
mac-address=D0:CF:13:D8:18:FC server=dhcp-v30
|
||||
add address=10.40.30.214 comment=shelly-s7_kueche_tiefkuehlschrank disabled=\
|
||||
yes mac-address=D0:CF:13:D9:94:E8 server=dhcp-v30
|
||||
add address=10.40.30.215 comment=shelly-s8_kueche_geschirrspueler disabled=\
|
||||
yes mac-address=E4:B0:63:FA:FD:E0 server=dhcp-v30
|
||||
add address=10.40.30.216 comment=shelly-s9_wohnzimmer_sideboard disabled=yes \
|
||||
mac-address=E8:F6:0A:61:88:08 server=dhcp-v30
|
||||
add address=10.40.30.217 comment=shelly-s10_bad_sonos disabled=yes \
|
||||
mac-address=E4:B0:63:FC:57:E4 server=dhcp-v30
|
||||
add address=10.40.30.218 comment=shelly-s11_kinderzimmer_sonos disabled=yes \
|
||||
mac-address=E4:B0:63:FA:6C:00 server=dhcp-v30
|
||||
add address=10.40.30.219 comment=shelly-s12_dieleug_steckdosen disabled=yes \
|
||||
mac-address=48:F6:EE:C8:E6:AC server=dhcp-v30
|
||||
add address=10.40.30.220 comment=shelly-s13_arbeitszimmer_technik disabled=\
|
||||
yes mac-address=48:F6:EE:DD:6A:F4 server=dhcp-v30
|
||||
add address=10.40.30.221 comment=shelly-s14_schlafzimmer_bett disabled=yes \
|
||||
mac-address=E4:B0:63:FC:59:48 server=dhcp-v30
|
||||
add address=10.40.30.222 comment=shelly-s15_technik_pve disabled=yes \
|
||||
mac-address=E4:B0:63:FA:D5:34 server=dhcp-v30
|
||||
add address=10.40.30.223 comment=shelly-s16_wohnzimmer_steckdosen disabled=\
|
||||
yes mac-address=10:20:BA:FA:F5:40 server=dhcp-v30
|
||||
add address=10.40.30.224 comment=shelly-s17_bad_steckdosen disabled=yes \
|
||||
mac-address=10:20:BA:FB:6D:64 server=dhcp-v30
|
||||
add address=10.40.30.225 comment=shelly-s18_kueche_steckdosen1 disabled=yes \
|
||||
mac-address=48:F6:EE:CC:16:E4 server=dhcp-v30
|
||||
add address=10.40.30.226 comment=shelly-s19_kueche_steckdosen3 disabled=yes \
|
||||
mac-address=10:20:BA:FB:70:FC server=dhcp-v30
|
||||
add address=10.40.30.227 comment="SwitchBot-floor-lamp / switchbot-floorlamp" \
|
||||
disabled=yes mac-address=B8:F8:62:09:F2:04 server=dhcp-v30
|
||||
add address=10.40.30.228 comment=\
|
||||
"Twinkly-2CA789 / Twinkly_Weihnachtsgirlande" disabled=yes mac-address=\
|
||||
98:F4:AB:2C:A7:88 server=dhcp-v30
|
||||
add address=10.40.30.230 comment=Withings_waage disabled=yes mac-address=\
|
||||
00:24:E4:40:2A:72 server=dhcp-v30
|
||||
add address=10.40.30.231 comment=Withings_blutdruck disabled=yes mac-address=\
|
||||
A4:7E:FA:18:2C:64 server=dhcp-v30
|
||||
add address=10.40.30.232 comment=pve-homematic-raspi-ccu disabled=yes \
|
||||
mac-address=BC:24:11:8E:0A:57 server=dhcp-v30
|
||||
add address=10.40.30.233 comment=shelly-s26_bad_luefter disabled=yes \
|
||||
mac-address=98:A3:16:7A:A3:54 server=dhcp-v30
|
||||
add address=10.40.30.236 comment=lichterkette disabled=yes mac-address=\
|
||||
A4:F0:0F:5F:D0:EC server=dhcp-v30
|
||||
add address=10.40.30.237 comment=lichterkette-mini disabled=yes mac-address=\
|
||||
24:DC:C3:9B:89:64 server=dhcp-v30
|
||||
add address=10.40.30.241 comment=NukiSmartlock disabled=yes mac-address=\
|
||||
28:DB:A7:09:7B:54 server=dhcp-v30
|
||||
add address=10.40.30.244 comment=NukiBridge disabled=yes mac-address=\
|
||||
24:62:AB:B1:63:F4 server=dhcp-v30
|
||||
add address=10.40.30.5 comment="P750W / P750W" disabled=yes mac-address=\
|
||||
4C:EB:BD:E3:25:F2 server=dhcp-v30
|
||||
add address=10.40.30.8 comment="DTUBI-414392337823 / DTUBI-414392337823" \
|
||||
disabled=yes mac-address=54:F2:9F:12:51:F0 server=dhcp-v30
|
||||
add address=10.40.40.11 comment=tv disabled=yes mac-address=70:AF:24:B8:C9:86 \
|
||||
server=dhcp-v40
|
||||
add address=10.40.40.191 client-id=1:34:7e:5c:32:37:96 comment=SonosZP \
|
||||
disabled=yes mac-address=34:7E:5C:32:37:96 server=dhcp-v40
|
||||
add address=10.40.40.192 client-id=1:34:7e:5c:32:33:b8 comment=SonosZP \
|
||||
disabled=yes mac-address=34:7E:5C:32:33:B8 server=dhcp-v40
|
||||
add address=10.40.40.193 client-id=1:78:28:ca:80:2a:f6 comment=SonosZP \
|
||||
disabled=yes mac-address=78:28:CA:80:2A:F6 server=dhcp-v40
|
||||
add address=10.40.40.194 client-id=1:48:a6:b8:14:fe:d0 comment=SonosZP \
|
||||
disabled=yes mac-address=48:A6:B8:14:FE:D0 server=dhcp-v40
|
||||
add address=10.40.40.195 client-id=1:78:28:ca:82:16:c2 comment=SonosZP \
|
||||
disabled=yes mac-address=78:28:CA:82:16:C2 server=dhcp-v40
|
||||
add address=10.40.40.196 client-id=1:48:a6:b8:16:38:ae comment=SonosZP \
|
||||
disabled=yes mac-address=48:A6:B8:16:38:AE server=dhcp-v40
|
||||
add address=10.40.40.197 client-id=1:48:a6:b8:14:fe:f2 comment=SonosZP \
|
||||
disabled=yes mac-address=48:A6:B8:14:FE:F2 server=dhcp-v40
|
||||
add address=10.40.40.198 comment="SonosZP / SonosTerrasse" disabled=yes \
|
||||
mac-address=78:28:CA:D2:0D:AC server=dhcp-v40
|
||||
add address=10.40.40.199 client-id=1:48:a6:b8:b:63:10 comment=SonosZP \
|
||||
disabled=yes mac-address=48:A6:B8:0B:63:10 server=dhcp-v40
|
||||
add address=10.40.40.200 client-id=1:48:a6:b8:69:69:7b comment=SonosZP \
|
||||
disabled=yes mac-address=48:A6:B8:69:69:7B server=dhcp-v40
|
||||
add address=10.40.40.201 client-id=1:94:9f:3e:49:59:ee comment=SonosZP \
|
||||
disabled=yes mac-address=94:9F:3E:49:59:EE server=dhcp-v40
|
||||
/ip dhcp-server network
|
||||
add address=10.40.10.0/24 dns-server=10.40.10.1 domain=bf.lan gateway=\
|
||||
10.40.10.1
|
||||
add address=10.40.20.0/24 dns-server=10.40.20.1 domain=bf.lan gateway=\
|
||||
10.40.20.1
|
||||
add address=10.40.30.0/24 dns-server=10.40.30.1 domain=bf.lan gateway=\
|
||||
10.40.30.1
|
||||
add address=10.40.40.0/24 dns-server=10.40.40.1 domain=bf.lan gateway=\
|
||||
10.40.40.1
|
||||
add address=10.40.50.0/24 dns-server=10.40.50.1 domain=bf.lan gateway=\
|
||||
10.40.50.1
|
||||
add address=10.40.90.0/24 dns-server=10.40.90.1 domain=bf.lan gateway=\
|
||||
10.40.90.1
|
||||
add address=10.40.99.0/24 dns-server=10.40.99.1 domain=bf.lan gateway=\
|
||||
10.40.99.1
|
||||
/ip dns
|
||||
set allow-remote-requests=yes mdns-repeat-ifaces=\
|
||||
vlan10,vlan20,vlan40,vlan30,vlan90 servers=1.1.1.1 use-doh-server=\
|
||||
https://px35ynlol3.cloudflare-gateway.com/dns-query verify-doh-cert=yes
|
||||
/ip dns static
|
||||
add address=10.40.99.1 comment="core = GW/Router" name=router.lan type=A
|
||||
add address=10.40.99.3 comment="ap1 = reiner AP" name=ap1.bf.lan type=A
|
||||
add address=10.40.99.2 comment="ap2 = reiner AP" name=ap2.bf.lan type=A
|
||||
add address=10.40.99.1 comment="crs326-core (L3)" name=core.bf.lan type=A
|
||||
add address=10.40.99.12 comment=crs326-branch name=branch.bf.lan type=A
|
||||
add address=10.40.20.167 name=macmini.bf.lan type=A
|
||||
add address=10.40.20.100 name=pve.bf.lan type=A
|
||||
add address=10.40.20.173 name=pve-mcp.bf.lan type=A
|
||||
add address=10.40.20.10 name=nas.bf.lan type=A
|
||||
add address=10.40.20.126 name=docker.bf.lan type=A
|
||||
add address=10.40.20.20 name=platform-pg.bf.lan type=A
|
||||
/ip firewall filter
|
||||
add action=accept chain=forward comment="defconf: accept est,rel,untracked" \
|
||||
connection-state=established,related,untracked
|
||||
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \
|
||||
connection-state=established,related hw-offload=yes
|
||||
add action=drop chain=forward comment="defconf: drop invalid" \
|
||||
connection-state=invalid
|
||||
add action=drop chain=forward comment="defconf: drop WAN !dstnat" \
|
||||
connection-nat-state=!dstnat in-interface-list=WAN
|
||||
add action=accept chain=forward comment="TP10: allow from WG spokes (FM/DW)" \
|
||||
in-interface=wg-hub
|
||||
add action=accept chain=forward comment="TP10: allow to WG spokes (FM/DW)" \
|
||||
out-interface=wg-hub
|
||||
add action=accept chain=forward comment="TP5: MAIN->MEDIA" in-interface=\
|
||||
vlan10 out-interface=vlan40
|
||||
add action=accept chain=forward comment="TP5: MEDIA->MAIN" in-interface=\
|
||||
vlan40 out-interface=vlan10
|
||||
add action=accept chain=forward comment="TP5: INFRA->MEDIA" in-interface=\
|
||||
vlan20 out-interface=vlan40
|
||||
add action=accept chain=forward comment="TP5: MEDIA->INFRA" in-interface=\
|
||||
vlan40 out-interface=vlan20
|
||||
add action=accept chain=forward comment="TP5: GUEST->MEDIA" in-interface=\
|
||||
vlan90 out-interface=vlan40
|
||||
add action=accept chain=forward comment="TP5: MEDIA->GUEST" in-interface=\
|
||||
vlan40 out-interface=vlan90
|
||||
add action=accept chain=input comment=TP10-seal-est connection-state=\
|
||||
established,related,untracked
|
||||
add action=drop chain=input comment=TP10-seal-inv connection-state=invalid
|
||||
add action=accept chain=input comment="TP10: WG hub listen" dst-port=51821 \
|
||||
protocol=udp
|
||||
add action=accept chain=input comment=TP10-seal-dhcp dst-port=68 \
|
||||
in-interface-list=WAN protocol=udp
|
||||
add action=accept chain=input comment=TP10-seal-icmp protocol=icmp
|
||||
add action=accept chain=input comment=TP10-seal-lan in-interface-list=LAN
|
||||
add action=drop chain=input comment=TP10-seal-wandrop in-interface-list=WAN
|
||||
add action=accept chain=input comment="TP5: mDNS in vlan10" dst-port=5353 \
|
||||
in-interface=vlan10 protocol=udp
|
||||
add action=accept chain=input comment="TP5: mDNS in vlan40" dst-port=5353 \
|
||||
in-interface=vlan40 protocol=udp
|
||||
add action=accept chain=input comment="TP5: mDNS in vlan20" dst-port=5353 \
|
||||
in-interface=vlan20 protocol=udp
|
||||
add action=accept chain=input comment="TP5: mDNS in vlan30" dst-port=5353 \
|
||||
in-interface=vlan30 protocol=udp
|
||||
add action=accept chain=input comment="TP5: mDNS in vlan90" dst-port=5353 \
|
||||
in-interface=vlan90 protocol=udp
|
||||
/ip firewall nat
|
||||
add action=accept chain=srcnat comment=\
|
||||
"TP4: no-NAT inter-VLAN (vor masquerade)" dst-address=10.40.0.0/16
|
||||
add action=masquerade chain=srcnat comment="defconf: masquerade WAN" \
|
||||
out-interface-list=WAN
|
||||
/ip hotspot profile
|
||||
set [ find default=yes ] html-directory=hotspot
|
||||
/ip route
|
||||
add comment=TP15-bringup dst-address=0.0.0.0/0 gateway=10.40.41.1
|
||||
add comment="TP10: FM spoke -> wg-hub" dst-address=10.101.0.0/24 gateway=\
|
||||
wg-hub
|
||||
add comment="TP10: DW spoke -> wg-hub" dst-address=10.95.10.0/24 gateway=\
|
||||
wg-hub
|
||||
/ip service
|
||||
set ftp disabled=yes
|
||||
set ssh address=10.40.0.0/16
|
||||
set telnet disabled=yes
|
||||
set www address=10.40.0.0/16
|
||||
set api address=10.40.0.0/16
|
||||
set api-ssl disabled=yes
|
||||
/system identity
|
||||
set name=crs326-core
|
||||
/system routerboard settings
|
||||
set enter-setup-on=delete-key
|
||||
119
routeros/export-ap1-cutover-data.py
Normal file
119
routeros/export-ap1-cutover-data.py
Normal file
@@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Export ap1-Daten, die im crs326-core Cutover-Fenster gebraucht werden.
|
||||
|
||||
Ausgaben (ohne Secrets im stdout):
|
||||
- routeros/ap1-leases-export.json : alle DHCP-Leases (static + dynamic)
|
||||
- routeros/ap1-wg-hub.privkey : wg-hub private-key (nur diese Zeile)
|
||||
- routeros/ap1-cutover-summary.txt : menschliche Zusammenfassung
|
||||
|
||||
Quelle: ap1 via REST (10.40.10.1), Creds aus ~/.claude.json (mikromcp-env).
|
||||
"""
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
AP1_REST = "http://10.40.10.1/rest" # VLAN10 Mgmt-IP (ap1-Mgmt nur via VLAN10)
|
||||
CLAUDE_JSON = pathlib.Path.home() / ".claude.json"
|
||||
OUT_DIR = pathlib.Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def load_ap1_creds():
|
||||
cfg = json.loads(CLAUDE_JSON.read_text())
|
||||
env = cfg.get("mcpServers", {}).get("mikromcp", {}).get("env", {})
|
||||
user = env.get("ROUTER_AP1_USER") or env.get("ROUTER_USER")
|
||||
pw = env.get("ROUTER_AP1_PASS") or env.get("ROUTER_PASS")
|
||||
if not user or not pw:
|
||||
raise SystemExit("ROUTER_AP1_USER/PASS nicht in ~/.claude.json mikromcp.env gefunden")
|
||||
return user, pw
|
||||
|
||||
|
||||
def rest_get(path, user, pw):
|
||||
url = f"{AP1_REST}{path}"
|
||||
auth = base64.b64encode(f"{user}:{pw}".encode()).decode()
|
||||
req = urllib.request.Request(url, headers={
|
||||
"Authorization": f"Basic {auth}",
|
||||
"Accept": "application/json",
|
||||
})
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=20) as resp:
|
||||
raw = resp.read()
|
||||
return json.loads(raw) if raw else []
|
||||
except urllib.error.HTTPError as e:
|
||||
sys.stderr.write(f"!! GET {url} -> {e.code} {e.read().decode()[:500]}\n")
|
||||
raise
|
||||
|
||||
|
||||
def main():
|
||||
user, pw = load_ap1_creds()
|
||||
print(f"ap1 REST {AP1_REST} (User: {user})")
|
||||
|
||||
# 1) DHCP-Leases
|
||||
leases = rest_get("/ip/dhcp-server/lease", user, pw)
|
||||
leases_path = OUT_DIR / "ap1-leases-export.json"
|
||||
leases_path.write_text(json.dumps(leases, indent=2))
|
||||
print(f" DHCP-Leases: {len(leases)} -> {leases_path}")
|
||||
|
||||
# 2) WG-Hub privkey (field may be redacted; fallback to script-run)
|
||||
wg = rest_get("/interface/wireguard", user, pw)
|
||||
hub = next((i for i in wg if i.get("name") == "wg-hub"), None)
|
||||
privkey = ""
|
||||
if hub:
|
||||
privkey = hub.get("private-key") or ""
|
||||
if not privkey:
|
||||
# REST listet privkey manchmal nicht; über system/script ausgeben lassen
|
||||
script = ':put [/interface/wireguard/get [find name="wg-hub"] private-key]'
|
||||
try:
|
||||
run_resp = rest_post("/system/script/run", {"source": script}, user, pw)
|
||||
# output format variiert
|
||||
privkey = str(run_resp).strip().strip('"')
|
||||
except Exception as e:
|
||||
sys.stderr.write(f" WG-Privkey-Fallback fehlgeschlagen: {e}\n")
|
||||
wg_path = OUT_DIR / "ap1-wg-hub.privkey"
|
||||
if privkey and privkey != "<<<none>>>":
|
||||
wg_path.write_text(privkey + "\n")
|
||||
print(f" WG-Hub Privkey -> {wg_path} ({len(privkey)} chars)")
|
||||
else:
|
||||
print(f" WARN: WG-Hub Privkey nicht ermittelt -> {wg_path} nicht geschrieben")
|
||||
|
||||
# 3) Zusammenfassung
|
||||
summary = [
|
||||
f"ap1 Cutover-Export vom {os.popen('date -Iseconds').read().strip()}",
|
||||
f"DHCP-Leases gesamt: {len(leases)}",
|
||||
f" statisch (dynamic=no): {sum(1 for l in leases if str(l.get('dynamic')).lower() == 'false')}",
|
||||
f" dynamisch: {sum(1 for l in leases if str(l.get('dynamic')).lower() != 'false')}",
|
||||
f"WG-Hub private-key erfasst: {'ja' if privkey else 'nein'}",
|
||||
"",
|
||||
"Nächste Schritte im Cutover-Fenster:",
|
||||
"1. ap1-leases-export.json filtern: nur dynamic=no, server-Namen auf core dhcp-v10..v99 mappen.",
|
||||
"2. ap1-wg-hub.privkey in core-Config einsetzen (ersetzt <<< AP1_WG_HUB_PRIVKEY >>>).",
|
||||
"3. Generate Intended Config für crs326-core erneut laufen lassen -> Nautobot-Deployment.",
|
||||
]
|
||||
summary_path = OUT_DIR / "ap1-cutover-summary.txt"
|
||||
summary_path.write_text("\n".join(summary) + "\n")
|
||||
print(f" Summary -> {summary_path}")
|
||||
|
||||
|
||||
def rest_post(path, data, user, pw):
|
||||
url = f"{AP1_REST}{path}"
|
||||
auth = base64.b64encode(f"{user}:{pw}".encode()).decode()
|
||||
body = json.dumps(data).encode()
|
||||
req = urllib.request.Request(url, data=body, headers={
|
||||
"Authorization": f"Basic {auth}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
}, method="POST")
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=20) as resp:
|
||||
raw = resp.read()
|
||||
return json.loads(raw) if raw else {}
|
||||
except urllib.error.HTTPError as e:
|
||||
sys.stderr.write(f"!! POST {url} -> {e.code} {e.read().decode()[:500]}\n")
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
51
routeros/fetch-core-cutover-config.py
Normal file
51
routeros/fetch-core-cutover-config.py
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Holt crs326-core intended config aus Nautobot, setzt WG-Privkey,
|
||||
fügt ap1 static leases hinzu, speichert als tp15-core-cutover-intended.rsc.
|
||||
"""
|
||||
import json
|
||||
import pathlib
|
||||
import re
|
||||
import urllib.request
|
||||
|
||||
NAUTOBOT_URL = "http://10.40.20.30:8080"
|
||||
TOKEN_PATH = pathlib.Path(__file__).parent.parent / "docs" / "nas-vlan20" / "stacks" / "210-nautobot.yml"
|
||||
OUT = pathlib.Path(__file__).with_name("tp15-core-cutover-intended.rsc")
|
||||
LEASES_RSC = pathlib.Path(__file__).with_name("ap1-leases-to-core.rsc")
|
||||
PRIVKEY_PATH = pathlib.Path(__file__).with_name("ap1-wg-hub.privkey")
|
||||
|
||||
|
||||
def get_token():
|
||||
text = TOKEN_PATH.read_text()
|
||||
m = re.search(r"^NAUTOBOT_SUPERUSER_API_TOKEN=(.+)$", text, re.MULTILINE)
|
||||
if not m:
|
||||
raise SystemExit("NAUTOBOT_SUPERUSER_API_TOKEN not found")
|
||||
return m.group(1).strip()
|
||||
|
||||
|
||||
def main():
|
||||
token = get_token()
|
||||
req = urllib.request.Request(
|
||||
f"{NAUTOBOT_URL}/api/plugins/golden-config/golden-config/?device=crs326-core",
|
||||
headers={"Authorization": f"Token {token}", "Accept": "application/json"},
|
||||
)
|
||||
with urllib.request.urlopen(req) as resp:
|
||||
data = json.loads(resp.read().decode())
|
||||
config = data["results"][0]["intended_config"]
|
||||
|
||||
privkey = PRIVKEY_PATH.read_text().strip()
|
||||
if "<<< AP1_WG_HUB_PRIVKEY >>>" not in config:
|
||||
raise SystemExit("placeholder missing in intended config")
|
||||
config = config.replace("<<< AP1_WG_HUB_PRIVKEY >>>", privkey)
|
||||
|
||||
leases = LEASES_RSC.read_text()
|
||||
# Entferne Kommentarblock-Lease-Datei, damit nur Befehle bleiben
|
||||
lease_lines = [line for line in leases.splitlines() if line and not line.startswith("#")]
|
||||
# Füge Leases vor dem WG-HUB-Block ein? Oder ans Ende. Ans Ende ist einfacher.
|
||||
out = config.rstrip() + "\n\n# [9] ap1 static leases -> core (STAGING)" + "\n" + "\n".join(lease_lines) + "\n"
|
||||
|
||||
OUT.write_text(out)
|
||||
print(f"{OUT} written ({len(out)} bytes)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
37
routeros/fix-core-rsc.py
Normal file
37
routeros/fix-core-rsc.py
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python3
|
||||
import re
|
||||
|
||||
src = "/Users/christophemsenhuber/dev/bf-network-r6/routeros/crs326-core-pre-cutover-20260806-073712.rsc"
|
||||
dst = "/Users/christophemsenhuber/dev/bf-network-r6/routeros/crs326-core-pre-cutover-20260806-073712-fixed.rsc"
|
||||
|
||||
with open(src) as f:
|
||||
lines = f.readlines()
|
||||
|
||||
out = []
|
||||
i = 0
|
||||
while i < len(lines):
|
||||
line = lines[i]
|
||||
if line.startswith("add admin-mac=04:F4:1C:B4:17:76 auto-mac=no comment=defconf name=bridge"):
|
||||
out.append("set [find name=bridge] admin-mac=04:F4:1C:B4:17:76 auto-mac=no vlan-filtering=yes\n")
|
||||
i += 1
|
||||
while i < len(lines) and (lines[i].startswith(" ") or lines[i].strip().startswith("vlan-filtering")):
|
||||
i += 1
|
||||
continue
|
||||
if re.match(r'set \[ find default-name=ether(3|4|5|6|7|8|9|1[0-9]|2[0-4]) \] disabled=yes', line):
|
||||
i += 1
|
||||
continue
|
||||
if line.startswith("/interface bridge port"):
|
||||
out.append(line)
|
||||
i += 1
|
||||
while i < len(lines) and not lines[i].startswith("/"):
|
||||
i += 1
|
||||
out.append("set [find interface=ether2] pvid=40\n")
|
||||
out.append("set [find interface=ether3] pvid=40\n")
|
||||
out.append("set [find interface=ether5] pvid=40\n")
|
||||
continue
|
||||
out.append(line)
|
||||
i += 1
|
||||
|
||||
with open(dst, "w") as f:
|
||||
f.writelines(out)
|
||||
print("fixed rsc written to", dst)
|
||||
58
routeros/fritzbox-bf-bridge-cutover-klickanleitung.md
Normal file
58
routeros/fritzbox-bf-bridge-cutover-klickanleitung.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# BF-FritzBox: Bridge/Passthrough + alte Tunnel abbauen — Klick-Anleitung
|
||||
|
||||
> **Methode:** Claude erklärt Absicht + Klickpfad, **du klickst** an der BF-FritzBox (FB 6660, Liwest, `10.40.41.254`).
|
||||
> ⚠️ FRITZ!OS-Labels sind versionsabhängig — wo unsicher, zählt die **Absicht**; sag mir, was die UI anbietet.
|
||||
> 🔗 Teil des permanenten Cutovers — Gesamtablauf: `routeros/wan-cutover-runbook.md` + `docs/tp10-vpn-migration.md`.
|
||||
|
||||
## Ziel
|
||||
Die BF-FB gibt die **öffentliche Liwest-IPv4 per Passthrough an ap1-ether1** weiter → **ap1 wird der Edge** (Public-IP,
|
||||
VPN-Hub). Die FB verliert ihre Router-/VPN-Rolle, **Telefonie bleibt auf der FB** (separater Voice-Pfad, von der
|
||||
IPv4-Weitergabe unberührt). Mechanismus = **LAN4-Passthrough** (= der reversible Weg aus dem Test, **kein Liwest-Anruf
|
||||
nötig**). Optionaler späterer Schritt: echter DOCSIS-Bridge/Modem via Liwest-Support (sauberer, aber nicht erforderlich).
|
||||
|
||||
## ⚠️ Reihenfolge — Hand in Hand mit ap1
|
||||
1. **FM-FB** hat die neue WG-`.conf` (bf4-Endpoint) — `fritzbox-wg-lanlan-klickanleitung.md`. DW: laut dir erledigt.
|
||||
2. **ap1-Apply** läuft (`routeros/tp10-cutover-apply.rsc`) — Hub scharf, WAN-Seal aktiv. **Erst danach** an die BF-FB.
|
||||
3. **DIESE Anleitung:** Passthrough an + ether1 umstecken. (Tunnel-Teardown unten erst **nach** Verify.)
|
||||
> Konsole während des Cutovers: **FB-WiFi → ap1 `10.40.41.1`** (WebFig) über ether2. **ether2 NIE ziehen.**
|
||||
|
||||
---
|
||||
|
||||
## Teil 1 — IPv4 an ap1 durchreichen (LAN4-Passthrough)
|
||||
`Internet → Zugangsdaten` (bzw. `Internet → ...`) → Funktion **„Gerät mit eigener öffentlicher IPv4" / „Passthrough"
|
||||
/ „Exposed Host an LAN4"** suchen.
|
||||
- **Absicht:** Die eine öffentliche Liwest-IPv4 wird **per DHCP an das Gerät an LAN4** (= ap1-ether1) übergeben.
|
||||
- Aktivieren, LAN4 als Passthrough-Port wählen, speichern.
|
||||
- Falls FRITZ!OS das nicht direkt anbietet: sag mir die vorhandenen Menüpunkte — dann lotse ich Feld für Feld
|
||||
(alternativ DOCSIS-Bridge via Liwest-Anruf, dann ist die FB reines Modem).
|
||||
|
||||
## Teil 2 — Umstecken
|
||||
- **ether1** von ap1 an den **FB-LAN4-Passthrough-Port**. **ether2 bleibt stecken** (Uplink/Konsole).
|
||||
- ap1-ether1 zieht jetzt Lease + **Public-IP**; Default-Route distance=1 übernimmt automatisch (Bridge-Fallback@2),
|
||||
Egress masquerade-ether1 greift. → Prüfen via `mcp__mikromcp__list_dhcp_clients` (ether1 status=bound) und
|
||||
`mcp__mikromcp__list_routes` (Default via ether1 aktiv).
|
||||
|
||||
## Teil 3 — 🔴 DDNS abgleichen (sonst finden die Spokes den Edge nicht)
|
||||
- ether1-Public-IP lesen: `mcp__mikromcp__run_command` → `/ip address print where interface=ether1`.
|
||||
- **`bf4.emsenhuber.net`** (Cloudflare, Zone `emsenhuber.net`, **proxied=false**, TTL 120) auf **genau diese IP** setzen,
|
||||
falls abweichend. *(ap1 kann device-mode-bedingt nicht selbst aktualisieren → vom Laptop/NAS aus.)*
|
||||
|
||||
## Teil 4 — Verify (erst danach Tunnel abbauen!)
|
||||
- `mcp__mikromcp__list_wireguard_peers` → **peer1 (FM) und peer2 (DW) Handshake**, rx/tx > 0.
|
||||
- Von einem BF-Host **per IP** (kein NetBIOS/Broadcast): SMB/445 auf je einen FM- und DW-Host.
|
||||
- **Antwort-Quelle MUSS die echte LAN-IP sein** (z.B. `10.101.0.x` / Geli-LAN), **nicht** `10.255.255.x` (= FB-NAT).
|
||||
|
||||
## Teil 5 — Alte AVM-Tunnel abbauen (nach grünem Verify)
|
||||
`Internet → Freigaben → Reiter „VPN (WireGuard)"`:
|
||||
- **Alte FM↔BF-FB-WG** **deaktivieren/löschen** — die WG-Kopplung, über die FM **bisher** lief (FM peerte mit der
|
||||
BF-FB auf `xvbeo64…myfritz:51821`). Jetzt peert FM↔**ap1** (`bf4…:51821`). *(IPsec ist längst gekillt → dort nichts zu tun.)*
|
||||
- **Alte DW/Geli-FB-WG** (Server-Port **51820**) **deaktivieren/löschen**.
|
||||
*(DW-Gotcha: Gelis FB lehnt 2 WG zum selben Zielnetz ab → der neue Geli↔ap1-Tunnel ersetzt den alten direkt; der
|
||||
Swap auf Geli-Seite ist laut dir bereits erfolgt.)*
|
||||
- Portfreigabe **51821 → 10.40.41.1** wird im Passthrough hinfällig → entfernen.
|
||||
|
||||
## Rollback (jederzeit, lockout-sicher)
|
||||
- **WAN zurück:** Passthrough an der FB aus → **ether1** zurück an einen normalen FB-LAN-Port. ap1 fällt über die
|
||||
distance-2-Route via bridge automatisch in den Double-NAT zurück. **LAN bleibt durchgehend online** (ether2 unberührt).
|
||||
- **Tunnel:** alte IPsec/WG erst nach grünem Verify abschalten → bis dahin jederzeit reaktivierbar.
|
||||
- **ap1-Seite:** per `routeros/tp10-cutover-apply.rsc`-Umkehr (Peers disabled, Seal/Routen entfernen).
|
||||
42
routeros/fritzbox-bf-static-routes-klickanleitung.md
Normal file
42
routeros/fritzbox-bf-static-routes-klickanleitung.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# BF-FritzBox: Statikrouten für die WG-Spoke-Netze (FM/DW → ap1) — Klick-Anleitung
|
||||
|
||||
> **Methode:** Claude erklärt Absicht + Klickpfad, **du klickst** an der BF-FritzBox (`10.40.41.254`,
|
||||
> kein MCP). ⚠️ FRITZ!OS-Labels sind versionsabhängig — Absicht zählt.
|
||||
>
|
||||
> 🔗 Teil von TP10 (`docs/tp10-vpn-migration.md`). **Interim-Maßnahme im Double-NAT** — beim permanenten
|
||||
> FB-Bridge-Cutover ist die FB aus dem Datenpfad → diese Routen werden gegenstandslos und können weg.
|
||||
|
||||
## 🎯 ROOT CAUSE (verifiziert 2026-06-28) + der Fix
|
||||
**Fehlerbild:** WG `peer dw` gesund (Handshake, rx/tx beidseitig), aber **dw → BF antwortet nicht**.
|
||||
Die scheinbar funktionierende Gegenrichtung lief über **WARP** (out-of-band), nicht über den Tunnel.
|
||||
|
||||
**Ursache:** Die BF-Infra hängt auf `10.40.41.0/24` (NAS .10, macmini .167, pve .100, Omada .175/.176 …).
|
||||
ap1s DHCP auf `bridge` ist **disabled** → diese Hosts beziehen DHCP von der **FritzBox** und haben
|
||||
**Default-GW `10.40.41.254` (FB)**, nicht ap1. Antwortet ein BF-Host an `10.95.10.x`, schickt er's an die
|
||||
FB — die hat **keine Route** zu den Spoke-Netzen mehr (terminiert die Tunnel nicht mehr) → **Antwort
|
||||
verschwindet** → *no response*.
|
||||
|
||||
> **DER FIX:** Der FB beibringen, dass die Spoke-Netze **über ap1 (`10.40.41.1`)** erreichbar sind.
|
||||
> Dann gehen die Antworten der `.41`-Hosts an die FB → FB → ap1 → Tunnel. Voll transparent, kein NAT.
|
||||
|
||||
## Eckdaten (beide Routen)
|
||||
| Netzwerk (Ziel) | Subnetzmaske | Gateway | Spoke |
|
||||
|---|---|---|---|
|
||||
| `10.95.10.0` | `255.255.255.0` | `10.40.41.1` (ap1) | **DW/Geli** |
|
||||
| `10.101.0.0` | `255.255.255.0` | `10.40.41.1` (ap1) | **FM** |
|
||||
|
||||
## Klickpfad
|
||||
**Heimnetz → Netzwerk → Netzwerkeinstellungen → „weitere Einstellungen" → IPv4-Routen → Neue Route.**
|
||||
Pro Route: Netzwerk + Maske + Gateway aus der Tabelle, **aktiv** setzen, übernehmen. Für beide Zeilen.
|
||||
|
||||
## Verify (entscheidend: LAN-Host, **ohne** WARP)
|
||||
1. Von Geli (`10.95.10.246/.247`, WARP **aus**) → BF-Infra **per IP**: `ping 10.40.41.10`, SMB/445 `10.40.41.10`.
|
||||
2. Quell-IP am BF-Zielhost = echte `10.95.10.x` (kein `10.255.255.x`, kein `10.40.41.1`) → bestätigt no-NAT.
|
||||
3. ap1: `list_firewall_rules out-interface=wg-hub` (*F) steigt; `list_connections` zeigt `10.95.10.x ↔ 10.40.41.x` established.
|
||||
4. FM-Quercheck: von `10.101.0.x` → BF-`.41`-Host ebenfalls grün.
|
||||
|
||||
> **Status 2026-06-28:** Beide Routen angelegt und **ohne WARP erfolgreich getestet** →
|
||||
> dw → BF und fm → BF erreichbar. ✅
|
||||
|
||||
## Reversibilität
|
||||
Routen jederzeit in der FB-UI löschbar. Keine ap1-Änderung. Entfallen automatisch beim Bridge-Cutover.
|
||||
95
routeros/fritzbox-wg-lanlan-klickanleitung.md
Normal file
95
routeros/fritzbox-wg-lanlan-klickanleitung.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# FritzBox WireGuard als LAN-LAN-Kopplung (FM/DW-Spoke → ap1-Hub) — Klick-Anleitung
|
||||
|
||||
> **Methode:** Claude erklärt Absicht + Klickpfad, **du klickst** an der FritzBox. FM-Standort
|
||||
> (`10.101.0.0/24`, GW `10.101.0.254`). **IPsec ist längst gekillt** → FM läuft bereits über **FB-WireGuard**
|
||||
> (peert aktuell mit der **BF-FB** auf `xvbeo64…myfritz:51821`; FM-FB horcht selbst auf
|
||||
> `abxhutfgsid9snmy.myfritz.net:52476`). Hub = ap1 (BF). ⚠️ FRITZ!OS-Labels sind versionsabhängig — Absicht zählt.
|
||||
>
|
||||
> 🔗 **Teil des permanenten Cutovers** (`docs/tp10-vpn-migration.md` + `routeros/wan-cutover-runbook.md`).
|
||||
> Der Hub-Endpoint ist jetzt **`bf4.emsenhuber.net:51821`** (DDNS), **nicht** mehr MyFRITZ — denn die BF-FB
|
||||
> geht in den Bridge-Mode und verliert MyFRITZ + Portfreigabe. `bf4` zeigt direkt auf ap1-ether1 (Public-IP).
|
||||
|
||||
## 🎯 ROOT CAUSE (bestätigt 2026-06-16) + der Fix
|
||||
**Messung:** Ping auf realen FM-Host `10.101.0.10` über WG → Antwort kam aus **`10.255.255.2`** (Tunnel-IP) → **die FB
|
||||
masqueradet den Tunnel.** Ursache: unsere `.conf` hatte als Interface-`Address` eine **Transfernetz-IP**
|
||||
(`10.255.255.2/32`) → FRITZ!OS behandelt das als **Einzelgerät** und NAT't.
|
||||
|
||||
**AVM-Modell:** FRITZ!OS nutzt für WG-LAN-LAN **kein Transfernetz, sondern Proxy-ARP**. Die WG-Interface-Adresse der
|
||||
FB **muss ihre eigene LAN-IP** sein → dann routet die FB ihr LAN **ohne NAT**, echte Host-IPs.
|
||||
|
||||
> **DER FIX (eine Zeile):** FB-WG-Interface-`Address` = **`10.101.0.254/24`** (FM-LAN-IP), **nicht** `10.255.255.2/32`.
|
||||
> Transfernetz `10.255.255.0/24` **komplett streichen**.
|
||||
|
||||
## Eckdaten (FM; DW analog)
|
||||
| Feld | Wert FM | Wert DW |
|
||||
|---|---|---|
|
||||
| **WG-Interface-Address (FB)** | **`10.101.0.254/24`** (LAN-IP!) | **`10.95.10.1/24`** (LAN-IP! **single**, nach Renumber) |
|
||||
| Erreichbare Netze / AllowedIPs (→Hub) | `10.40.0.0/16` | `10.40.0.0/16` |
|
||||
| Hub-Endpoint | **`bf4.emsenhuber.net:51821`** | dito (DW: CGNAT → wählt ausgehend) |
|
||||
| Hub-Public-Key | `P/bztIk13cAmLHbN6oHGGnWAKLZsqR5TXAbFP+NGGBk=` | dito |
|
||||
| MTU / Keepalive | `1412` / `25` | `1412` / `25` |
|
||||
| Vorbereitete `.conf` | `routeros/.secrets/wg-fm.conf` | `routeros/.secrets/wg-dw.conf` |
|
||||
|
||||
## ⚠️ Sicherheit (FM ist produktiv!)
|
||||
- Die **bestehende FM↔BF-FB-WG bleibt an** = Sicherheitsnetz, bis der Echt-Host-Test über ap1 grün ist.
|
||||
- ap1-Seite kommt per `routeros/tp10-cutover-apply.rsc` (Hub scharf, peer1 mit FM-Endpoint) — dort nichts klicken.
|
||||
|
||||
---
|
||||
|
||||
## ⚡ Schnellpfad (wahrscheinlich ausreichend)
|
||||
FM ist **schon** auf WG mit korrektem LAN-IP-Modell (`Address=10.101.0.254/24`) — sonst liefe es nicht sauber.
|
||||
Dann ist die ganze Migration **ein Feld**: in der bestehenden FM-WG-Verbindung den **Peer-Endpoint** von
|
||||
`xvbeo64…myfritz.net:51821` (BF-FB) auf **`bf4.emsenhuber.net:51821`** (ap1) umbiegen — fertig.
|
||||
Erlaubt FRITZ!OS kein Bearbeiten des Endpoints → Verbindung **löschen + via `wg-fm.conf` neu importieren**
|
||||
(gleicher Key/Address, nur neuer Endpoint). **Nur wenn FM noch die alte Transfernetz-Adresse hat**, brauchst du
|
||||
Teil 1+2 unten.
|
||||
|
||||
## Teil 1 — Bestehende (falsche, transfernetz-basierte) FM-WG-Verbindung entfernen
|
||||
*(Nur falls FM noch NICHT auf dem LAN-IP-Modell ist.)*
|
||||
`Internet → Freigaben → Reiter „VPN (WireGuard)"` → die FM-Verbindung **löschen** (sie hat die falsche
|
||||
Transfernetz-Adresse → NAT).
|
||||
|
||||
## Teil 2 — Neu als LAN-LAN-Kopplung anlegen
|
||||
`„Verbindung hinzufügen"` → Typ **„Netzwerke koppeln" / „LAN-LAN"** wählen (**nicht** „Einzelnes Gerät").
|
||||
- Falls FRITZ!OS dort nur den **FB↔FB**-Assistenten anbietet: stattdessen **benutzerdefinierte/importierte Config**
|
||||
und **`routeros/.secrets/wg-fm.conf`** importieren — die hat jetzt die korrekte `Address = 10.101.0.254/24`.
|
||||
- **Kernpunkt:** Die WG-Interface-Adresse dieser Verbindung muss **`10.101.0.254/24`** sein (die FB-LAN-IP),
|
||||
erreichbares Netz Richtung Hub = **`10.40.0.0/16`**. **„Gesamten Internetverkehr über VPN" = AUS.**
|
||||
- ⚠️ Falls der Import eine LAN-IP als Interface-Adresse **ablehnt** (Überlapp mit dem LAN): dann den AVM-Wizard
|
||||
„Netzwerke koppeln" nutzen und dort die **lokale FB-IP** als Verbindungs-IP eintragen (das ist genau der
|
||||
Proxy-ARP-Weg). Sag mir, was die UI anbietet — dann lotse ich Feld für Feld.
|
||||
- **Public-Key** der Verbindung notieren → mir geben, falls FRITZ!OS einen **eigenen** Key erzeugt
|
||||
(dann gleiche ich `peer1` auf ap1 ab; aktuell steht dort der Key aus unserer `.conf`).
|
||||
|
||||
## Teil 3 — ap1-Abgleich (mache ich, falls nötig)
|
||||
- Falls FB neuen Key erzeugt: `peer1`-Public-Key aktualisieren.
|
||||
- peer1 allowed-address bleibt `10.101.0.0/24` (Transfernetz-/32 ist obsolet, schadet aber nicht).
|
||||
> Sag Bescheid — nicht-disruptiv per MikroMCP.
|
||||
|
||||
## Teil 4 — Verifizieren, dann erst die alte FM↔BF-FB-WG abbauen
|
||||
1. Neuer Tunnel aktiv (alte FM↔BF-FB-WG noch an lassen). Ich pinge von ap1 sourced `10.40.20.1` → **`10.101.0.10`**
|
||||
+ `torch wg-hub`:
|
||||
- **Quelle = `10.101.0.10`** → ✅ kein NAT, echtes LAN-LAN → weiter.
|
||||
- Quelle = `10.255.255.x` → noch NAT → Adresse/Modus prüfen (Teil 2).
|
||||
2. Gegenrichtung: FM-Host → BF-Host (NAS) per IP; **SMB/445 per IP** (NetBIOS-Lehre: per IP/DNS, kein Broadcast).
|
||||
3. Beide Richtungen grün → **alte FM↔BF-FB-WG auf der BF-FB deaktivieren** → erneut testen.
|
||||
4. Stabil → FM migriert. **DW** läuft analog (CGNAT → ausgehend/Keepalive), aber Single-Address — siehe unten.
|
||||
|
||||
## DW-Spezial: Renumber auf 10.95.10.0/24 + Single-Address (LEHRE 2026-06-25)
|
||||
**Symptom war:** Tunnel stand (Handshake ✓, rx/tx ✓), aber **BF→Geli-Host per IP ging nicht**; ap1-Ping auf
|
||||
`192.168.178.1` **und** `10.95.10.1` kam immer aus `10.95.10.1` zurück.
|
||||
**Ursache:** Die WG-`Address` war **Dual** (`192.168.178.1/24, 10.95.10.1/24`). FRITZ!OS macht daraus
|
||||
`10.95.10.1` als **Primäradresse** und koppelt das echte LAN (`192.168.178.0/24`) **nicht** mehr → kein Host-Routing.
|
||||
**Regel:** WG-`Address` = **GENAU EINE** Adresse = die **aktuelle** FB-LAN-IP. Kein Dual, kein Vorab-Netz.
|
||||
|
||||
**Vorgehen bei Geli (vor Cutoff):**
|
||||
1. **FB-LAN renumbern:** `Heimnetz → Netzwerk → Netzwerkeinstellungen → IPv4-Adressen` → FB-LAN-IP **`10.95.10.1`**,
|
||||
Maske `255.255.255.0`, DHCP-Range `10.95.10.x`. (Geli-Geräte ziehen neue Leases.)
|
||||
2. **WG-`Address`** der ap1-Verbindung auf **`10.95.10.1/24`** (single) setzen — das `192.168.178.1/24` raus.
|
||||
3. ap1-Seite ist schon fertig: `peer dw` allowed-address = `10.95.10.0/24`, Route `10.95.10.0/24 → wg-hub`.
|
||||
4. **Verify:** ap1-Ping (src `10.40.20.1`) auf einen **echten** Geli-Host `10.95.10.x` → Antwort aus **derselben** IP
|
||||
(nicht aus `.1`, nicht aus `10.255.255.x`). Dann BF↔Geli per IP/SMB testen.
|
||||
|
||||
## Rollback
|
||||
- Auf der FM-FB den Peer-Endpoint zurück auf `xvbeo64…myfritz:51821` (BF-FB) biegen bzw. die alte Verbindung
|
||||
wieder aktivieren → Ausgangszustand. ap1-Seite ist inert, kann bleiben.
|
||||
96
routeros/import-core-rsc.py
Normal file
96
routeros/import-core-rsc.py
Normal file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Kopiert ein beliebiges .rsc auf crs326-core und importiert es via SSH.
|
||||
|
||||
Usage: python3 import-core-rsc.py <pfad/zur/datei.rsc> [--host 10.40.41.211]
|
||||
|
||||
Creds kommen aus ~/.claude.json (mcpServers.mikromcp.env) envPrefix CRS326_CORE_.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
CLAUDe_JSON = Path.home() / ".claude.json"
|
||||
RSC_PATH = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else None
|
||||
HOST = sys.argv[2] if len(sys.argv) > 2 and sys.argv[1] == "--host" else None
|
||||
|
||||
|
||||
def usage():
|
||||
print(__doc__, file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
if RSC_PATH is None:
|
||||
usage()
|
||||
|
||||
if not RSC_PATH.exists():
|
||||
sys.exit(f"Datei nicht gefunden: {RSC_PATH}")
|
||||
|
||||
if HOST is None:
|
||||
HOST = "10.40.41.211"
|
||||
|
||||
# Creds aus Claude-Settings laden
|
||||
env = json.loads(CLAUDe_JSON.read_text())["mcpServers"]["mikromcp"]["env"]
|
||||
get = lambda key, default=None: env.get(key, default)
|
||||
|
||||
user = get("CRS326_CORE_USER", "admin")
|
||||
pw = get("CRS326_CORE_PASS")
|
||||
if not pw:
|
||||
sys.exit("CRS326_CORE_PASS fehlt in ~/.claude.json")
|
||||
|
||||
# Remote-Dateiname: alphanumerisch + Unterstrich/Punkt/Minus
|
||||
remote_name = re.sub(r"[^A-Za-z0-9_.-]", "_", RSC_PATH.name)
|
||||
|
||||
|
||||
def ssh_cmd(remote_command: str) -> list:
|
||||
return [
|
||||
"sshpass", "-p", pw,
|
||||
"ssh",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "PubkeyAuthentication=no",
|
||||
"-o", "LogLevel=ERROR",
|
||||
f"{user}@{HOST}",
|
||||
remote_command,
|
||||
]
|
||||
|
||||
|
||||
def run_silent(cmd: list):
|
||||
r = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if r.returncode != 0:
|
||||
out = (r.stdout + r.stderr).replace(pw, "***")
|
||||
raise SystemExit(f"SSH-Befehl fehlgeschlagen (rc={r.returncode}):\n{out}")
|
||||
return r
|
||||
|
||||
|
||||
# 1) Eventuell vorhandene alte Remote-Datei entfernen
|
||||
run_silent(ssh_cmd(f"/file/remove [find name=\"{remote_name}\"]; :delay 500ms"))
|
||||
|
||||
# 2) SCP
|
||||
scp = [
|
||||
"sshpass", "-p", pw,
|
||||
"scp",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "PubkeyAuthentication=no",
|
||||
"-o", "LogLevel=ERROR",
|
||||
str(RSC_PATH),
|
||||
f"{user}@{HOST}:/{remote_name}",
|
||||
]
|
||||
r = subprocess.run(scp, capture_output=True, text=True)
|
||||
if r.returncode != 0:
|
||||
out = (r.stdout + r.stderr).replace(pw, "***")
|
||||
raise SystemExit(f"SCP fehlgeschlagen (rc={r.returncode}):\n{out}")
|
||||
|
||||
# 3) Import — mit verbose, damit wir die Zeile sehen, wenn ein Fehler auftritt
|
||||
import_cmd = f"/import file-name={remote_name} verbose=yes"
|
||||
res = subprocess.run(ssh_cmd(import_cmd), capture_output=True, text=True)
|
||||
out = (res.stdout + res.stderr).replace(pw, "***")
|
||||
if res.returncode != 0:
|
||||
raise SystemExit(f"Import fehlgeschlagen (rc={res.returncode}):\n{out}")
|
||||
|
||||
print(out)
|
||||
print(f"OK: {RSC_PATH.name} importiert auf {HOST} als /{remote_name}")
|
||||
133
routeros/push-gc-template.py
Normal file
133
routeros/push-gc-template.py
Normal file
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env python3
|
||||
r"""Push nautobot/mikrotik_routeros.j2 to the bf-golden-config Gitea repo.
|
||||
|
||||
Reads the Gitea token from ~/.secrets/credentials.env (GITEA_ACCESS_TOKEN).
|
||||
|
||||
python3 routeros/push-gc-template.py --dry-run # Diff gegen Remote zeigen
|
||||
python3 routeros/push-gc-template.py -m "TP22: AP-Zweig" # pushen
|
||||
|
||||
SECRET-GUARD (TP22, 2026-08-13)
|
||||
-------------------------------
|
||||
Vor jedem PUT wird der Template-Inhalt gegen dieselben Feld-Regexe geprueft, die die
|
||||
Nautobot-ConfigReplace-Regeln fuers Backup-Scrubbing verwenden. Findet sich ein Wert,
|
||||
der NICHT die Maske `"<<REDACTED>>"` traegt, bricht das Skript ab.
|
||||
|
||||
Grund: genau dieser Weg hat am 2026-07-22 den WG-Hub-private-key und 6 WLAN-PSKs ins
|
||||
Gitea-Repo getragen (via Backup-Job, aber dieselbe Zielablage). Das Repo musste am
|
||||
2026-08-13 neu angelegt werden. Der Guard kostet nichts und verhindert die Wiederholung.
|
||||
"""
|
||||
import argparse
|
||||
import base64
|
||||
import difflib
|
||||
import json
|
||||
import pathlib
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
|
||||
REPO = "https://gitea.emsenhuber.net/api/v1/repos/admin/bf-golden-config"
|
||||
FILE = "jinja_templates/mikrotik_routeros.j2"
|
||||
TOKEN_PATH = pathlib.Path.home() / ".secrets/credentials.env"
|
||||
SRC = pathlib.Path(__file__).resolve().parent.parent / "nautobot" / "mikrotik_routeros.j2"
|
||||
|
||||
MASK = '"<<REDACTED>>"'
|
||||
# Muss mit nautobot/ingest-gc-scrubbing.py:RULES synchron bleiben.
|
||||
SECRET_FIELDS = ["passphrase", "private-key", "pre-shared-key", "wpa-pre-shared-key", "password", "secret"]
|
||||
VAL = r'("(?:[^"\\]|\\.)*"|\S+)'
|
||||
|
||||
|
||||
def get_token():
|
||||
m = re.search(r"^GITEA_ACCESS_TOKEN=(.+)$", TOKEN_PATH.read_text(), re.MULTILINE)
|
||||
if not m:
|
||||
raise SystemExit("GITEA_ACCESS_TOKEN not found")
|
||||
return m.group(1).strip()
|
||||
|
||||
|
||||
def scan_for_secrets(text):
|
||||
"""Gibt eine Liste von (zeilennr, feld) zurueck, deren Wert nicht maskiert ist."""
|
||||
bad = []
|
||||
for lineno, line in enumerate(text.splitlines(), 1):
|
||||
# Kommentarzeilen sind Doku (nennen die Feldnamen absichtlich), nicht Config.
|
||||
if line.lstrip().startswith("#"):
|
||||
continue
|
||||
for field in SECRET_FIELDS:
|
||||
for m in re.finditer(rf"(?<![\w-]){re.escape(field)}=" + VAL, line):
|
||||
if m.group(1) != MASK:
|
||||
bad.append((lineno, field))
|
||||
return bad
|
||||
|
||||
|
||||
def api(path, method="GET", payload=None, token=""):
|
||||
req = urllib.request.Request(
|
||||
f"{REPO}/{path}",
|
||||
data=json.dumps(payload).encode() if payload else None,
|
||||
method=method,
|
||||
headers={"Authorization": f"token {token}", "Content-Type": "application/json"},
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=30) as resp:
|
||||
raw = resp.read()
|
||||
return resp.status, (json.loads(raw) if raw else {})
|
||||
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument("-m", "--message", help="Commit-Message (Default: letzter lokaler Commit-Titel)")
|
||||
p.add_argument("--dry-run", action="store_true", help="nur Diff gegen Remote zeigen")
|
||||
args = p.parse_args()
|
||||
|
||||
content = SRC.read_text()
|
||||
|
||||
# --- Secret-Guard: laeuft IMMER, auch im Dry-Run ---
|
||||
bad = scan_for_secrets(content)
|
||||
if bad:
|
||||
print("!! ABBRUCH - unmaskierte Secrets im Template:")
|
||||
for lineno, field in bad:
|
||||
print(f" Zeile {lineno}: {field}= traegt nicht die Maske {MASK}")
|
||||
sys.exit(1)
|
||||
print(f" Secret-Guard: ok (alle Secret-Felder tragen {MASK})")
|
||||
|
||||
token = get_token()
|
||||
|
||||
# Remote-Stand holen (sha optional: nach einer Repo-Neuanlage existiert die Datei ggf. nicht)
|
||||
sha, remote = None, ""
|
||||
try:
|
||||
_, meta = api(f"contents/{FILE}?ref=main", token=token)
|
||||
sha = meta.get("sha")
|
||||
remote = base64.b64decode(meta.get("content", "")).decode()
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code != 404:
|
||||
raise
|
||||
print(f" Remote: {FILE} existiert noch nicht - wird angelegt")
|
||||
|
||||
diff = list(difflib.unified_diff(
|
||||
remote.splitlines(), content.splitlines(),
|
||||
fromfile=f"remote/{FILE}", tofile=f"local/{SRC.name}", lineterm="", n=2))
|
||||
if not diff:
|
||||
print(" Kein Unterschied zum Remote - nichts zu tun.")
|
||||
return
|
||||
print(f" Diff: +{sum(1 for l in diff if l.startswith('+') and not l.startswith('+++'))}"
|
||||
f" / -{sum(1 for l in diff if l.startswith('-') and not l.startswith('---'))} Zeilen")
|
||||
if args.dry_run:
|
||||
print("\n".join(diff))
|
||||
print("\n DRY-RUN - nichts gepusht.")
|
||||
return
|
||||
|
||||
msg = args.message
|
||||
if not msg:
|
||||
try:
|
||||
msg = subprocess.run(["git", "log", "-1", "--pretty=%s"], cwd=SRC.parent.parent,
|
||||
capture_output=True, text=True, check=True).stdout.strip()
|
||||
except Exception:
|
||||
msg = "Update mikrotik_routeros.j2"
|
||||
|
||||
payload = {"content": base64.b64encode(content.encode()).decode(), "message": msg, "branch": "main"}
|
||||
if sha:
|
||||
payload["sha"] = sha
|
||||
status, res = api(f"contents/{FILE}", method="PUT" if sha else "POST", payload=payload, token=token)
|
||||
print(f" HTTP {status} commit={res.get('commit', {}).get('sha', '?')[:8]} msg={msg!r}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
99
routeros/rest-core-script.py
Normal file
99
routeros/rest-core-script.py
Normal file
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Lädt eine .rsc-/Script-Datei per RouterOS REST API auf crs326-core hoch
|
||||
und führt sie als /system/script aus.
|
||||
|
||||
Usage: python3 rest-core-script.py <pfad/zur/datei.rsc> [--host 10.40.41.211]
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
CLAUDe_JSON = Path.home() / ".claude.json"
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print(__doc__, file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
src_path = Path(sys.argv[1]).resolve()
|
||||
host = "10.40.41.211"
|
||||
if len(sys.argv) > 2 and sys.argv[2] == "--host" and len(sys.argv) > 3:
|
||||
host = sys.argv[3]
|
||||
|
||||
if not src_path.exists():
|
||||
sys.exit(f"Datei nicht gefunden: {src_path}")
|
||||
|
||||
env = json.loads(CLAUDe_JSON.read_text())["mcpServers"]["mikromcp"]["env"]
|
||||
user = env.get("CRS326_CORE_USER", "admin")
|
||||
pw = env.get("CRS326_CORE_PASS")
|
||||
if not pw:
|
||||
sys.exit("CRS326_CORE_PASS fehlt in ~/.claude.json")
|
||||
|
||||
base_url = f"http://{host}/rest"
|
||||
script_name = f"tp15_{src_path.stem}"
|
||||
source = src_path.read_text()
|
||||
|
||||
|
||||
def api(path, body=None, method="POST"):
|
||||
url = base_url + path
|
||||
data = json.dumps(body).encode() if body is not None else None
|
||||
req = urllib.request.Request(url, data=data, method=method)
|
||||
req.add_header("Content-Type", "application/json")
|
||||
import base64
|
||||
req.add_header("Authorization", "Basic " + base64.b64encode(f"{user}:{pw}".encode()).decode())
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=30) as resp:
|
||||
return resp.status, resp.read().decode()
|
||||
except urllib.error.HTTPError as e:
|
||||
return e.code, (e.read().decode() or e.reason)
|
||||
|
||||
|
||||
def api_get(path):
|
||||
url = base_url + path
|
||||
req = urllib.request.Request(url)
|
||||
import base64
|
||||
req.add_header("Authorization", "Basic " + base64.b64encode(f"{user}:{pw}".encode()).decode())
|
||||
with urllib.request.urlopen(req, timeout=30) as resp:
|
||||
return resp.status, resp.read().decode()
|
||||
|
||||
|
||||
# [1] Altes Script mit gleichem Namen entfernen
|
||||
print(f"Suche ggf. altes Script '{script_name}' ...")
|
||||
status, body = api_get("/system/script")
|
||||
if status == 200:
|
||||
try:
|
||||
for item in json.loads(body):
|
||||
if item.get("name") == script_name:
|
||||
print(f"Entferne altes Script id={item.get('.id')} ...")
|
||||
api("/system/script/remove", {"id": item[".id"]})
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# [2] Script anlegen
|
||||
print(f"Erstelle Script '{script_name}' ({len(source)} Zeichen) ...")
|
||||
status, body = api("/system/script/add", {"name": script_name, "source": source})
|
||||
print(f"add -> HTTP {status}: {body[:400]}")
|
||||
if status >= 400:
|
||||
sys.exit("Script konnte nicht angelegt werden.")
|
||||
|
||||
try:
|
||||
created = json.loads(body)
|
||||
except json.JSONDecodeError:
|
||||
created = {}
|
||||
|
||||
script_id = created.get(".id")
|
||||
|
||||
# [3] Script ausführen
|
||||
if script_id:
|
||||
print(f"Starte Script id={script_id} ...")
|
||||
status, body = api("/system/script/run", {"id": script_id})
|
||||
print(f"run -> HTTP {status}: {body[:2000]}")
|
||||
else:
|
||||
# Try to find by name
|
||||
print("Suche Script-ID per Name ...")
|
||||
status, body = api_get(f"/system/script?name={script_name}")
|
||||
print(f"getall -> HTTP {status}: {body[:800]}")
|
||||
|
||||
print("OK: REST-Aufrufe abgeschlossen")
|
||||
79
routeros/restore-core.py
Normal file
79
routeros/restore-core.py
Normal file
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Stelle das crs326-core Backup vom Cutover-Stand wieder her.
|
||||
|
||||
Creds aus ~/.claude.json (mikromcp-env, CRS326_CORE_*).
|
||||
Backup-Datei wird per SCP hochgeladen und /system backup load ausgefuehrt.
|
||||
"""
|
||||
import json
|
||||
import pathlib
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
CORE_IP = "192.168.88.1"
|
||||
BACKUP = "crs326-core-pre-cutover-20260806-073712.backup"
|
||||
CLAUDE_JSON = pathlib.Path.home() / ".claude.json"
|
||||
OUT_DIR = pathlib.Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def load_core_creds():
|
||||
cfg = json.loads(CLAUDE_JSON.read_text())
|
||||
env = cfg.get("mcpServers", {}).get("mikromcp", {}).get("env", {})
|
||||
user = env.get("CRS326_CORE_USER") or env.get("ROUTER_USER")
|
||||
pw = env.get("CRS326_CORE_PASS") or env.get("ROUTER_PASS")
|
||||
if not user or not pw:
|
||||
raise SystemExit("CRS326_CORE_USER/PASS nicht in ~/.claude.json mikromcp.env gefunden")
|
||||
return user, pw
|
||||
|
||||
|
||||
def ssh_cmd(user, pw, remote_command):
|
||||
return [
|
||||
"sshpass", "-p", pw,
|
||||
"ssh",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "PubkeyAuthentication=no",
|
||||
f"{user}@{CORE_IP}",
|
||||
remote_command,
|
||||
]
|
||||
|
||||
|
||||
def scp_cmd(user, pw, local_file, remote_file):
|
||||
return [
|
||||
"sshpass", "-p", pw,
|
||||
"scp",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "PubkeyAuthentication=no",
|
||||
str(local_file),
|
||||
f"{user}@{CORE_IP}:{remote_file}",
|
||||
]
|
||||
|
||||
|
||||
def run_silent(cmd, pw):
|
||||
r = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if r.returncode != 0:
|
||||
out = (r.stdout + r.stderr).replace(pw, "***")
|
||||
raise SystemExit(f"Befehl fehlgeschlagen (rc={r.returncode}):\n{out}")
|
||||
return r
|
||||
|
||||
|
||||
def main():
|
||||
local_backup = OUT_DIR / BACKUP
|
||||
if not local_backup.exists():
|
||||
raise SystemExit(f"{local_backup} fehlt")
|
||||
|
||||
user, pw = load_core_creds()
|
||||
|
||||
print(f"crs326-core Restore via SSH {user}@{CORE_IP}")
|
||||
print(f" Lade {BACKUP} hoch ...")
|
||||
run_silent(scp_cmd(user, pw, local_backup, BACKUP), pw)
|
||||
|
||||
print(f" Spiele Backup zurueck ...")
|
||||
run_silent(ssh_cmd(user, pw, f'/system backup load name="{BACKUP}" password=""'), pw)
|
||||
|
||||
print(" Backup geladen, Router rebootet.")
|
||||
print(" Warte auf Wiederverbindung an 10.40.41.211 ...")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
71
routeros/tp10-cutover-apply.rsc
Normal file
71
routeros/tp10-cutover-apply.rsc
Normal file
@@ -0,0 +1,71 @@
|
||||
# =====================================================================
|
||||
# TP10 Cutover-Apply (ap1) — WG-Hub scharf + WAN-Input-Seal
|
||||
# =====================================================================
|
||||
# Zweck: ap1 in einem Rutsch von "geparkt" auf "Edge + VPN-Hub" bringen.
|
||||
# WANN ANWENDEN: am Bridge-Tag, SCHRITT 2 des Runbooks — VOR dem Umstecken
|
||||
# von ether1 an den FB-Passthrough-Port.
|
||||
# SICHERHEIT: im Double-NAT harmlos — Peers warten auf die Spokes, der
|
||||
# WAN-Drop trifft nur das (noch tote) ether1. Kein LAN-Lockout
|
||||
# (Drop greift ausschliesslich in-interface-list=WAN = ether1).
|
||||
# IDEMPOTENT: alle Blöcke sind wiederholbar (find-Guards / set).
|
||||
# ROLLBACK: Peers disabled=yes, WG-Routen + TP10-seal-* Regeln entfernen.
|
||||
#
|
||||
# Anwenden via MikroMCP: upload_file -> run_script (oder /import)
|
||||
# Vorab IMMER: export_config / create_backup
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
:log info "TP10-cutover: apply start"
|
||||
|
||||
# --- A) WireGuard-Hub: Peers mit korrekten Keys + Allowed-IPs (self-healing)
|
||||
# fm: erreichbar (eigener myfritz-Endpoint, KEIN CGNAT) -> bidirektional.
|
||||
# dw: CGNAT -> Dial-in (Endpoint leer). NUR 10.95.10.0/24 (Gelis FB sourct daraus;
|
||||
# Dual-Address 192.168.178.1/24,10.95.10.1/24 auf der FB verhindert LAN-Kopplung).
|
||||
/interface/wireguard/peers
|
||||
set [find where name="fm"] public-key="dzRY0lnnUygijChWe5wXZmXPeNcbdALpqBptA3fyiVE=" \
|
||||
allowed-address=10.101.0.0/24 \
|
||||
endpoint-address=abxhutfgsid9snmy.myfritz.net endpoint-port=52476 disabled=no
|
||||
set [find where name="dw"] public-key="FqYZLztQ/qME5VDie5QLGH++5299WJiE1dPpQnPbzUw=" \
|
||||
allowed-address=10.95.10.0/24 disabled=no
|
||||
|
||||
# --- B) Routen zu den Spoke-Netzen (Gateway = Interface wg-hub)
|
||||
# RouterOS leitet aus allowed-address KEINE Routen ab -> explizit.
|
||||
/ip/route
|
||||
:if ([:len [find where dst-address="10.101.0.0/24" gateway="wg-hub"]]=0) do={ \
|
||||
add dst-address=10.101.0.0/24 gateway=wg-hub comment="TP10: FM spoke -> wg-hub" }
|
||||
:if ([:len [find where dst-address="10.95.10.0/24" gateway="wg-hub"]]=0) do={ \
|
||||
add dst-address=10.95.10.0/24 gateway=wg-hub comment="TP10: DW spoke -> wg-hub" }
|
||||
|
||||
# --- C) Input-Chain abdichten (WAN-Seal). Reihenfolge oben->unten:
|
||||
# est/rel | drop invalid | [WG 51821 vorhanden] | dhcp68 | icmp | LAN | drop WAN
|
||||
/ip/firewall/filter
|
||||
# 1+2 ueber die bestehende WG-Regel schieben (est zuerst, dann invalid)
|
||||
:if ([:len [find where comment="TP10-seal-est"]]=0) do={ \
|
||||
add chain=input action=accept connection-state=established,related,untracked \
|
||||
comment="TP10-seal-est" place-before=[find where comment="TP10: WG hub listen (51821)"] }
|
||||
:if ([:len [find where comment="TP10-seal-inv"]]=0) do={ \
|
||||
add chain=input action=drop connection-state=invalid \
|
||||
comment="TP10-seal-inv" place-before=[find where comment="TP10: WG hub listen (51821)"] }
|
||||
# 4-7 NACH der WG-Regel anhaengen (in dieser Reihenfolge)
|
||||
:if ([:len [find where comment="TP10-seal-dhcp"]]=0) do={ \
|
||||
add chain=input action=accept protocol=udp dst-port=68 in-interface-list=WAN \
|
||||
comment="TP10-seal-dhcp" }
|
||||
:if ([:len [find where comment="TP10-seal-icmp"]]=0) do={ \
|
||||
add chain=input action=accept protocol=icmp comment="TP10-seal-icmp" }
|
||||
:if ([:len [find where comment="TP10-seal-lan"]]=0) do={ \
|
||||
add chain=input action=accept in-interface-list=LAN comment="TP10-seal-lan" }
|
||||
:if ([:len [find where comment="TP10-seal-wandrop"]]=0) do={ \
|
||||
add chain=input action=drop in-interface-list=WAN comment="TP10-seal-wandrop" }
|
||||
|
||||
# --- D) ether1-DHCP-Client: kein ISP-DNS-Leak (DoH bleibt einzige Quelle)
|
||||
# default-route-distance=1 ist bereits gesetzt (Auto-Switchover < Bridge-Fallback@2)
|
||||
/ip/dhcp-client
|
||||
set [find where interface="ether1"] use-peer-dns=no
|
||||
|
||||
:log info "TP10-cutover: apply done"
|
||||
# =====================================================================
|
||||
# NICHT Teil dieses Skripts (bereits korrekt auf ap1):
|
||||
# - NAT: masquerade out-interface=ether1 (*3) + no-NAT 10.40.0.0/16 (*4)
|
||||
# - Forward-FW: accept in/out-interface=wg-hub (*E/*F)
|
||||
# - Default-Fallback-Route 0.0.0.0/0 via 10.40.41.254 distance=2
|
||||
# VPN-Traffic egresst ueber wg-hub -> matcht keine Masquerade -> echte LAN-IPs.
|
||||
# =====================================================================
|
||||
36
routeros/tp15-core-cleanup-partial.rsc
Normal file
36
routeros/tp15-core-cleanup-partial.rsc
Normal file
@@ -0,0 +1,36 @@
|
||||
# TP15 — Bereinigt den halb-importierten Zustand auf crs326-core,
|
||||
# damit die korrigierte Cutover-Config sauber neu importiert werden kann.
|
||||
# Alle entfernten Objekte werden vom korrigierten tp15-core-cutover-intended.rsc
|
||||
# wieder angelegt (disabled=yes).
|
||||
|
||||
:log info "TP15-cleanup: start"
|
||||
|
||||
# [1] Interface-Lists (incl. Members werden kaskadiert entfernt)
|
||||
:if ([:len [/interface/list/find name="WAN"]] > 0) do={
|
||||
/interface/list/remove [find name="WAN"]
|
||||
}
|
||||
:if ([:len [/interface/list/find name="LAN"]] > 0) do={
|
||||
/interface/list/remove [find name="LAN"]
|
||||
}
|
||||
|
||||
# [2] Staged GW-IPs
|
||||
:if ([:len [/ip/address/find comment~"L3 SVI VLAN"]] > 0) do={
|
||||
/ip/address/remove [find comment~"L3 SVI VLAN"]
|
||||
}
|
||||
|
||||
# [3] Staged WAN DHCP-Client
|
||||
:if ([:len [/ip/dhcp-client/find comment~"TP15 WAN"]] > 0) do={
|
||||
/ip/dhcp-client/remove [find comment~"TP15 WAN"]
|
||||
}
|
||||
|
||||
# [4] DHCP-Pools (keine Server referenzieren sie, Import blieb vor dhcp-server stehen)
|
||||
:if ([:len [/ip/pool/find name~"^pool-v"]] > 0) do={
|
||||
/ip/pool/remove [find name~"^pool-v"]
|
||||
}
|
||||
|
||||
# [5] DHCP-Server/Network-Einträge
|
||||
:if ([:len [/ip/dhcp-server/network/find address~"^10\\.40\\."]] > 0) do={
|
||||
/ip/dhcp-server/network/remove [find address~"^10\\.40\\."]
|
||||
}
|
||||
|
||||
:log info "TP15-cleanup: done"
|
||||
176
routeros/tp15-core-l3-staged.rsc
Normal file
176
routeros/tp15-core-l3-staged.rsc
Normal file
@@ -0,0 +1,176 @@
|
||||
# =====================================================================================
|
||||
# TP15 — crs326-core L3-Umzug: STAGED CONFIG (ap1 -> core)
|
||||
# =====================================================================================
|
||||
# Zweck: core zum L3-Router machen (ersetzt ap1). ALLES was den Betrieb umlenkt, wird
|
||||
# STAGED (disabled=yes) angelegt -> kein IP-Konflikt mit dem noch aktiven ap1.
|
||||
# Im Cutover-Fenster werden die disabled-Objekte in EINEM Rutsch aktiviert.
|
||||
#
|
||||
# NICHT HEUTE ausführen. Vorbereitungs-Artefakt für ein späteres Wartungsfenster.
|
||||
# Governance: braucht die zu Fensterbeginn neu zu erteilende Direkt-Ausnahme #3.
|
||||
# Ausführung: REST (/system/script PUT+run gegen http://10.40.41.211/rest) ODER
|
||||
# MikroMCP plan_changes->apply_plan (nach MCP-Neustart, ENV CRS326_CORE_* live).
|
||||
#
|
||||
# Vorlage = ap1s Live-Config, gelesen 2026-07-23 (MikroMCP). Bridge/VLAN-Filtering/Trunks
|
||||
# stehen auf core bereits (Bring-up) — hier kommt NUR die L3-Ebene dazu.
|
||||
#
|
||||
# ⚠️ ZWEI Bulk-Blöcke bewusst NICHT hier hartkodiert (Transkriptionsfehler-Risiko bei ~50
|
||||
# MACs) -> zum Fensterbeginn MASCHINELL von ap1 heben, s. Abschnitt [RESERVATIONS].
|
||||
# ⚠️ WG-Hub PRIVATE KEY ist ein Secret -> NICHT im Repo. Platzhalter unten, am Gerät setzen.
|
||||
# =====================================================================================
|
||||
|
||||
# ============================ [1] INTERFACE-LISTS ====================================
|
||||
# Voraussetzung für WAN-Seal (input) und NAT (out-interface-list=WAN).
|
||||
/interface/list add name=WAN comment="TP15"
|
||||
/interface/list add name=LAN comment="TP15"
|
||||
/interface/list/member add list=WAN interface=vlan100
|
||||
/interface/list/member add list=LAN interface=vlan10
|
||||
/interface/list/member add list=LAN interface=vlan20
|
||||
/interface/list/member add list=LAN interface=vlan30
|
||||
/interface/list/member add list=LAN interface=vlan40
|
||||
/interface/list/member add list=LAN interface=vlan50
|
||||
/interface/list/member add list=LAN interface=vlan90
|
||||
/interface/list/member add list=LAN interface=vlan99
|
||||
# bridge/VLAN1 bewusst NICHT in LAN (VLAN1 raus). vlan99-Mgmt .11 bleibt vorerst separat.
|
||||
|
||||
# ============================ [2] GW-IPs je VLAN (STAGED) ============================
|
||||
# disabled=yes -> erst im Cutover enable (sonst Duplicate-IP mit ap1).
|
||||
/ip/address add address=10.40.10.1/24 interface=vlan10 comment="MAIN GW" disabled=yes
|
||||
/ip/address add address=10.40.20.1/24 interface=vlan20 comment="INFRA GW" disabled=yes
|
||||
/ip/address add address=10.40.30.1/24 interface=vlan30 comment="IOT GW" disabled=yes
|
||||
/ip/address add address=10.40.40.1/24 interface=vlan40 comment="MEDIA GW" disabled=yes
|
||||
/ip/address add address=10.40.50.1/24 interface=vlan50 comment="UNTRUSTED GW" disabled=yes
|
||||
/ip/address add address=10.40.90.1/24 interface=vlan90 comment="GUEST GW" disabled=yes
|
||||
/ip/address add address=10.40.99.1/24 interface=vlan99 comment="MGMT GW" disabled=yes
|
||||
# KEIN 10.40.41.x-GW (VLAN1 raus). KEIN Secondary .254 (FB-Legacy, obsolet).
|
||||
# Reconcile am Gerät: Bring-up-Mgmt 10.40.99.11 vs. GW .1 auf demselben vlan99
|
||||
# -> .1 ist der Router; .11 als Secondary behalten oder droppen (Fenster-Entscheid).
|
||||
|
||||
# ============================ [3] WAN DHCP-Client (STAGED) ===========================
|
||||
/ip/dhcp-client add interface=vlan100 use-peer-dns=no add-default-route=yes \
|
||||
comment="TP15 WAN Liwest (Arris)" disabled=yes
|
||||
# Liwest ist NICHT MAC-gelockt (Public-IP kam mit eigener MAC, s. wan-macclone-test.rsc)
|
||||
# -> core zieht am WAN evtl. eine ANDERE Public-IP. Konsequenz für WG-Hub s. [7]/[8].
|
||||
|
||||
# ============================ [4] DHCP-Server je VLAN (STAGED) =======================
|
||||
/ip/pool add name=pool-v10 ranges=10.40.10.100-10.40.10.200
|
||||
/ip/pool add name=pool-v20 ranges=10.40.20.100-10.40.20.200
|
||||
/ip/pool add name=pool-v30 ranges=10.40.30.100-10.40.30.250
|
||||
/ip/pool add name=pool-v40 ranges=10.40.40.100-10.40.40.200
|
||||
/ip/pool add name=pool-v50 ranges=10.40.50.100-10.40.50.200
|
||||
/ip/pool add name=pool-v90 ranges=10.40.90.100-10.40.90.200
|
||||
/ip/pool add name=pool-v99 ranges=10.40.99.100-10.40.99.200
|
||||
# ⚠️ pool-v30 = .100-.250 (Shelly-Reservierungen liegen in-pool, s. TP17). Andere .100-.200.
|
||||
|
||||
/ip/dhcp-server/network add address=10.40.10.0/24 gateway=10.40.10.1 dns-server=10.40.10.1 domain=bf.lan
|
||||
/ip/dhcp-server/network add address=10.40.20.0/24 gateway=10.40.20.1 dns-server=10.40.20.1 domain=bf.lan
|
||||
/ip/dhcp-server/network add address=10.40.30.0/24 gateway=10.40.30.1 dns-server=10.40.30.1 domain=bf.lan
|
||||
/ip/dhcp-server/network add address=10.40.40.0/24 gateway=10.40.40.1 dns-server=10.40.40.1 domain=bf.lan
|
||||
/ip/dhcp-server/network add address=10.40.50.0/24 gateway=10.40.50.1 dns-server=10.40.50.1 domain=bf.lan
|
||||
/ip/dhcp-server/network add address=10.40.90.0/24 gateway=10.40.90.1 dns-server=10.40.90.1 domain=bf.lan
|
||||
/ip/dhcp-server/network add address=10.40.99.0/24 gateway=10.40.99.1 dns-server=10.40.99.1 domain=bf.lan
|
||||
|
||||
/ip/dhcp-server add name=dhcp-v10 interface=vlan10 address-pool=pool-v10 lease-time=1d add-dns-entries-suffix=lan comment=MAIN disabled=yes
|
||||
/ip/dhcp-server add name=dhcp-v20 interface=vlan20 address-pool=pool-v20 lease-time=1d add-dns-entries-suffix=lan comment=INFRA disabled=yes
|
||||
/ip/dhcp-server add name=dhcp-v30 interface=vlan30 address-pool=pool-v30 lease-time=1d add-dns-entries-suffix=lan comment=IOT disabled=yes
|
||||
/ip/dhcp-server add name=dhcp-v40 interface=vlan40 address-pool=pool-v40 lease-time=1d add-dns-entries-suffix=lan comment=MEDIA disabled=yes
|
||||
/ip/dhcp-server add name=dhcp-v50 interface=vlan50 address-pool=pool-v50 lease-time=1d add-dns-entries-suffix=lan comment=UNTRUSTED disabled=yes
|
||||
/ip/dhcp-server add name=dhcp-v90 interface=vlan90 address-pool=pool-v90 lease-time=12h add-dns-entries-suffix=lan comment=GUEST disabled=yes
|
||||
/ip/dhcp-server add name=dhcp-v99 interface=vlan99 address-pool=pool-v99 lease-time=1d add-dns-entries-suffix=lan comment=MGMT disabled=yes
|
||||
|
||||
# ============================ [RESERVATIONS] — MASCHINELL VON ap1 HEBEN ==============
|
||||
# ~50 statische Leases (26 Shelly, Sonos, NAS .20.10, Nuki, Withings, Sonoff, ccu,
|
||||
# Airfryer/Mac mit dhcp-option "dns 1.1.1.1", P750W, Ender, DTUBI, tv, ...).
|
||||
# NICHT abtippen -> am Fensterbeginn auf ap1:
|
||||
# /ip/dhcp-server/lease/export file=ap1-leases
|
||||
# dann: nur dynamic=no übernehmen, server-Namen matchen (dhcp-v10..v99), als disabled=yes
|
||||
# anlegen; im Cutover mit den Servern zusammen enable. Danach GraphQL/HA-Cross-Check.
|
||||
# (Alternativ MikroMCP manage_dhcp_lease je Eintrag aus dem Live-Read.)
|
||||
|
||||
# ============================ [5] DNS ==============================================
|
||||
/ip/dns set allow-remote-requests=yes servers=1.1.1.1 \
|
||||
use-doh-server=https://px35ynlol3.cloudflare-gateway.com/dns-query verify-doh-cert=yes \
|
||||
mdns-repeat-ifaces=vlan10,vlan20,vlan40,vlan30,vlan90
|
||||
# bridge/VLAN1 NICHT mehr in mdns-repeat (war auf ap1 noch drin, entfällt mit VLAN1).
|
||||
|
||||
# Statische A-Records unter bf.lan (11 von ap1; sw1/sw2 RAUS = werden abgebaut):
|
||||
/ip/dns/static add name=router.lan address=10.40.99.1 comment="core = GW/Router"
|
||||
/ip/dns/static add name=ap1.bf.lan address=10.40.99.3 comment="ap1 = reiner AP (Mgmt-IP im Fenster festlegen)"
|
||||
/ip/dns/static add name=ap2.bf.lan address=10.40.99.2 comment="ap2 = reiner AP"
|
||||
/ip/dns/static add name=core.bf.lan address=10.40.99.1 comment="crs326-core (L3)"
|
||||
/ip/dns/static add name=branch.bf.lan address=10.40.99.12 comment="crs326-branch (nach Renumber .13->.12)"
|
||||
/ip/dns/static add name=macmini.bf.lan address=10.40.20.167
|
||||
/ip/dns/static add name=pve.bf.lan address=10.40.20.100
|
||||
/ip/dns/static add name=pve-mcp.bf.lan address=10.40.20.173
|
||||
/ip/dns/static add name=nas.bf.lan address=10.40.20.10
|
||||
/ip/dns/static add name=docker.bf.lan address=10.40.20.126
|
||||
/ip/dns/static add name=platform-pg.bf.lan address=10.40.20.20
|
||||
# ⚠️ ap1/ap2/branch-Mgmt-IPs sind Fenster-Entscheide (Renumber). Oben = Zielannahme.
|
||||
|
||||
# ============================ [6] NAT =============================================
|
||||
/ip/firewall/nat add chain=srcnat dst-address=10.40.0.0/16 action=accept \
|
||||
comment="TP4: no-NAT inter-VLAN (vor masquerade)"
|
||||
/ip/firewall/nat add chain=srcnat out-interface-list=WAN action=masquerade \
|
||||
comment="defconf: masquerade WAN"
|
||||
|
||||
# ============================ [7] FIREWALL FILTER =================================
|
||||
# Reihenfolge = ap1-Live (order-sensitiv!). Gegen ap1-Export im Fenster gegenprüfen.
|
||||
# --- forward ---
|
||||
/ip/firewall/filter add chain=forward action=accept connection-state=established,related,untracked comment="defconf: accept est,rel,untracked"
|
||||
/ip/firewall/filter add chain=forward action=fasttrack-connection connection-state=established,related comment="defconf: fasttrack"
|
||||
/ip/firewall/filter add chain=forward action=drop connection-state=invalid comment="defconf: drop invalid"
|
||||
/ip/firewall/filter add chain=forward action=drop connection-nat-state=!dstnat in-interface-list=WAN comment="defconf: drop WAN !dstnat"
|
||||
/ip/firewall/filter add chain=forward action=accept in-interface=wg-hub comment="TP10: allow from WG spokes (FM/DW)"
|
||||
/ip/firewall/filter add chain=forward action=accept out-interface=wg-hub comment="TP10: allow to WG spokes (FM/DW)"
|
||||
/ip/firewall/filter add chain=forward action=accept in-interface=vlan10 out-interface=vlan40 comment="TP5: MAIN->MEDIA (AirPlay/Sonos)"
|
||||
/ip/firewall/filter add chain=forward action=accept in-interface=vlan40 out-interface=vlan10 comment="TP5: MEDIA->MAIN"
|
||||
/ip/firewall/filter add chain=forward action=accept in-interface=vlan20 out-interface=vlan40 comment="TP5: INFRA->MEDIA (HA<->Sonos)"
|
||||
/ip/firewall/filter add chain=forward action=accept in-interface=vlan40 out-interface=vlan20 comment="TP5: MEDIA->INFRA"
|
||||
/ip/firewall/filter add chain=forward action=accept in-interface=vlan90 out-interface=vlan40 comment="TP5: GUEST->MEDIA (Sonos/Cast)"
|
||||
/ip/firewall/filter add chain=forward action=accept in-interface=vlan40 out-interface=vlan90 comment="TP5: MEDIA->GUEST"
|
||||
# --- input (TP10 WAN-Seal) ---
|
||||
/ip/firewall/filter add chain=input action=accept connection-state=established,related,untracked comment="TP10-seal-est"
|
||||
/ip/firewall/filter add chain=input action=drop connection-state=invalid comment="TP10-seal-inv"
|
||||
/ip/firewall/filter add chain=input action=accept protocol=udp dst-port=51821 comment="TP10: WG hub listen"
|
||||
/ip/firewall/filter add chain=input action=accept protocol=udp dst-port=68 in-interface-list=WAN comment="TP10-seal-dhcp"
|
||||
/ip/firewall/filter add chain=input action=accept protocol=icmp comment="TP10-seal-icmp"
|
||||
/ip/firewall/filter add chain=input action=accept in-interface-list=LAN comment="TP10-seal-lan"
|
||||
/ip/firewall/filter add chain=input action=drop in-interface-list=WAN comment="TP10-seal-wandrop"
|
||||
/ip/firewall/filter add chain=input action=accept protocol=udp dst-port=5353 in-interface=vlan10 comment="TP5: mDNS in vlan10"
|
||||
/ip/firewall/filter add chain=input action=accept protocol=udp dst-port=5353 in-interface=vlan40 comment="TP5: mDNS in vlan40"
|
||||
/ip/firewall/filter add chain=input action=accept protocol=udp dst-port=5353 in-interface=vlan20 comment="TP5: mDNS in vlan20"
|
||||
/ip/firewall/filter add chain=input action=accept protocol=udp dst-port=5353 in-interface=vlan30 comment="TP5: mDNS in vlan30"
|
||||
/ip/firewall/filter add chain=input action=accept protocol=udp dst-port=5353 in-interface=vlan90 comment="TP5: mDNS in vlan90"
|
||||
# Hinweis: ipsec-passthrough-Regeln (defconf) auf ap1 vorhanden aber 0 Pakete -> weggelassen.
|
||||
|
||||
# ============================ [8] WG-HUB (TP10 Multi-Site) ========================
|
||||
# ⚠️ PRIVATE KEY = ap1s wg-hub-Privkey (SECRET, nicht im Repo). Im Fenster von ap1 holen:
|
||||
# /interface/wireguard/export ODER :put [/interface/wireguard get wg-hub private-key]
|
||||
# und HIER einsetzen -> core hält denselben Public Key -> FM/DW brauchen KEINE Reconfig.
|
||||
/interface/wireguard add name=wg-hub mtu=1412 listen-port=51821 private-key="<<< AP1_WG_HUB_PRIVKEY >>>" \
|
||||
comment="TP10 Multi-Site VPN Hub (FM/DW spokes); kein IP aufs IF (Routing via AllowedIPs)"
|
||||
/interface/wireguard/peers add interface=wg-hub name=fm allowed-address=10.101.0.0/24 \
|
||||
public-key="dzRY0lnnUygijChWe5wXZmXPeNcbdALpqBptA3fyiVE=" \
|
||||
endpoint-address=abxhutfgsid9snmy.myfritz.net endpoint-port=52476
|
||||
/interface/wireguard/peers add interface=wg-hub name=dw allowed-address=10.95.10.0/24 \
|
||||
public-key="FqYZLztQ/qME5VDie5QLGH++5299WJiE1dPpQnPbzUw="
|
||||
/ip/route add dst-address=10.101.0.0/24 gateway=wg-hub comment="TP10: FM spoke -> wg-hub"
|
||||
/ip/route add dst-address=10.95.10.0/24 gateway=wg-hub comment="TP10: DW spoke -> wg-hub"
|
||||
# ✅ GEKLÄRT (2026-07-23): FM+DW adressieren den Hub über `bf4.emsenhuber.net:51821` =
|
||||
# Cloudflare-A-Record (proxied=false, TTL 120, aktuell 90.146.35.38). KEIN Updater auf
|
||||
# ap1 (nur WANTEST/mac-clone-Scripts) -> nichts zu migrieren. bf4 folgt der Public-IP
|
||||
# MANUELL (TP10-Follow-up, nie automatisiert).
|
||||
# -> Cutover-Konsequenz: zieht core am WAN eine ANDERE Liwest-IP (Lease ist sticky,
|
||||
# eher nicht), dann via CF_API_TOKEN nachziehen: (a) bf4-A-Record, (b) CF-Access-
|
||||
# Policy `bf4-home-ip` (90.146.35.38/32). Solange die IP gleich bleibt = No-op.
|
||||
# -> Chance: core ist NICHT device-mode=home -> scheduler+fetch gehen -> hier den
|
||||
# bf4-DDNS-Auto-Updater bauen, den ap1 nie konnte (schliesst TP10-Follow-up).
|
||||
|
||||
# ============================ [CUTOVER-ENABLE] (im Fenster, EIN Rutsch) ============
|
||||
# NACH Kabel-Umstecken sw1->core und NACHDEM ap1 als Router still ist:
|
||||
# /ip/address/enable [find comment~"GW"]
|
||||
# /ip/dhcp-client/enable [find comment~"TP15 WAN"]
|
||||
# /ip/dhcp-server/enable [find name~"dhcp-v"]
|
||||
# (Reservierungen wurden mit angelegt/enabled)
|
||||
# Dann Verifikation je VLAN (Lease/GW-Ping/Internet), DNS, branch, WG-Handshake, CF/WARP.
|
||||
# Rollback: hier alles wieder disable + Kabel zurück auf sw1 + ap1 wieder enable.
|
||||
# =====================================================================================
|
||||
21
routeros/tp19-core-vlan1-address-remove.rsc
Normal file
21
routeros/tp19-core-vlan1-address-remove.rsc
Normal file
@@ -0,0 +1,21 @@
|
||||
# TP19 — VLAN1-Bring-up-Adresse vom Core entfernen.
|
||||
# Ausgerollt 2026-08-15 ueber Nautobot GC (manual Config Plan), Backup davor:
|
||||
# core-pre-tp19-vlan1-addr-20260815.backup
|
||||
#
|
||||
# `10.40.41.211/24` auf `bridge` (Kommentar TP15-bringup-vlan1) war die letzte
|
||||
# .41-Spur auf dem Core und der letzte offene Compliance-Drift (ip-address).
|
||||
# Vorher geprueft: keine DNS-Statics, kein DHCP-Server auf `bridge`, kein Netwatch,
|
||||
# keine Address-Lists mit .41; `bridge` ist NICHT Mitglied der LAN-Interface-Liste.
|
||||
# Mgmt laeuft ueber .99.1 (+ Fallback 10.40.10.1), beides unberuehrt.
|
||||
#
|
||||
# ERWARTETE NEBENWIRKUNG: die dynamische Connected-Route 10.40.41.0/24 verschwindet
|
||||
# mit der Adresse. Das ist gewollt — Restverkehr nach VLAN1 scheitert danach sofort
|
||||
# statt in einen Timeout zu laufen.
|
||||
#
|
||||
# Reihenfolge war bindend und ist erfuellt: HA zeigt auf 10.40.20.100 (Integration
|
||||
# `loaded`), pve hat 10.40.41.100 nicht mehr, Prometheus/ioBroker sind umgezogen.
|
||||
#
|
||||
# Selbstprotokollierend — der Deploy-Job zeigt den Geraete-Output nicht (E1028).
|
||||
|
||||
:do { /ip address remove [find address="10.40.41.211/24"] } on-error={ :log info "tp19: remove hat geworfen" }
|
||||
:log info ("tp19: ENDE rest-41-adressen=" . [:tostr [:len [/ip address find address~"10.40.41."]]] . " rest-41-routen=" . [:tostr [:len [/ip route find dst-address~"10.40.41."]]])
|
||||
9
routeros/tp19-ntp-ap-neustart.rsc
Normal file
9
routeros/tp19-ntp-ap-neustart.rsc
Normal file
@@ -0,0 +1,9 @@
|
||||
# NTP-Client auf dem AP neu anstossen.
|
||||
#
|
||||
# Beide APs zeigen seit jeher auf 10.40.99.1 und standen deshalb dauerhaft auf
|
||||
# `status: waiting`. Ein Client, der lange erfolglos war, verlaengert seine
|
||||
# Wartezeit — er merkt also nicht von selbst zeitnah, dass der Core seit
|
||||
# 2026-08-18 tatsaechlich Zeit liefert. Aus/ein setzt den Zustand zurueck.
|
||||
:do { /system ntp client set enabled=no } on-error={ :log info "tp19ntp: ap-off warf" }
|
||||
:do { /system ntp client set enabled=yes servers=10.40.99.1 } on-error={ :log info "tp19ntp: ap-on warf" }
|
||||
:log info ("tp19ntp: ap-client status=" . [/system ntp client get status])
|
||||
5
routeros/tp19-ntp-branch-client.rsc
Normal file
5
routeros/tp19-ntp-branch-client.rsc
Normal file
@@ -0,0 +1,5 @@
|
||||
# NTP-Client auf crs326-branch nachziehen. Er hatte GAR KEINEN Server
|
||||
# eingetragen (status=stopped) — die Uhr stimmte nur zufaellig noch.
|
||||
# Zeitquelle ist der Core (s. routeros/tp19-ntp-core-als-zeitquelle.rsc).
|
||||
:do { /system ntp client set enabled=yes servers=10.40.99.1 } on-error={ :log info "tp19ntp: branch warf" }
|
||||
:log info ("tp19ntp: branch status=" . [/system ntp client get status])
|
||||
34
routeros/tp19-ntp-core-als-zeitquelle.rsc
Normal file
34
routeros/tp19-ntp-core-als-zeitquelle.rsc
Normal file
@@ -0,0 +1,34 @@
|
||||
# NTP: den Core zur Zeitquelle des Standorts machen.
|
||||
#
|
||||
# BEFUND (2026-08-18, beim TP19-Abschluss gefunden):
|
||||
# ap1 ntp client -> 10.40.99.1, status=waiting, Uhr zufaellig noch richtig
|
||||
# ap2 ntp client -> 10.40.99.1, status=waiting, Uhr **17 Stunden nach**
|
||||
# branch ntp client -> gar keiner, status=stopped
|
||||
# core /system ntp server = enabled:no
|
||||
# Alle drei fragen also einen Zeitserver, den es nicht gibt ("waiting" heisst
|
||||
# genau das). ap2 ist nur der erste, der sichtbar weggelaufen ist — die anderen
|
||||
# folgen.
|
||||
#
|
||||
# WARUM DAS MEHR ALS KOSMETIK IST: Geraete-Logs sind das Hauptwerkzeug in diesem
|
||||
# Projekt (TP5 lebt vom Kollektor). Beim Pfadbeweis heute nacht hat ap2 einen
|
||||
# Logeintrag von 04:57 als "2026-08-17 12:19" gestempelt — eine Korrelation
|
||||
# ueber mehrere Geraete ist damit wertlos.
|
||||
#
|
||||
# WEG: der Core hat als einziger eine verlaessliche Zeit (WAN + DoH). Er wird
|
||||
# Server, die drei anderen bleiben/werden Clients auf 10.40.99.1. Kein Geraet
|
||||
# braucht dafuer Internet.
|
||||
#
|
||||
# ⚠️ Die input-Regel ist Pflicht: seit Etappe 4 endet `input` mit einem Drop.
|
||||
# Ohne sie waere der NTP-Server eingeschaltet und trotzdem unerreichbar —
|
||||
# derselbe stille Fehlschlag wie bisher, nur eine Ebene tiefer.
|
||||
#
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device crs326-core \
|
||||
# --commands-file routeros/tp19-ntp-core-als-zeitquelle.rsc \
|
||||
# --change-id TP19-NTP --deploy \
|
||||
# --assert '/system/ntp/server|enabled=true'
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
:do { /system ntp server set enabled=yes } on-error={ :log info "tp19ntp: 01 server warf" }
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E4: ntp"]] = 0) do={ /ip firewall filter add chain=input action=accept in-interface-list=LAN protocol=udp dst-port=123 comment="TP5-E4: ntp" place-before=[/ip firewall filter find comment="TP5: input log-only"] } } on-error={ :log info "tp19ntp: 02 fw warf" }
|
||||
|
||||
:log info ("tp19ntp: ENDE server-enabled=" . [:tostr [/system ntp server get enabled]] . " fw-regel=" . [:tostr [:len [/ip firewall filter find comment="TP5-E4: ntp"]]])
|
||||
18
routeros/tp19-ntp-core-client.rsc
Normal file
18
routeros/tp19-ntp-core-client.rsc
Normal file
@@ -0,0 +1,18 @@
|
||||
# NTP, zweiter Teil: der Core braucht selbst eine Zeitquelle.
|
||||
#
|
||||
# BEFUND (2026-08-18, nach dem Einschalten des Servers): die Anfragen der APs
|
||||
# kommen an (Firewall-Regel zaehlt), der Core antwortet aber nicht brauchbar —
|
||||
# `/system ntp client` ist **enabled: no**, ohne Server, `status: stopped`, und
|
||||
# `/system ntp server` steht auf `use-local-clock: no`. Ein NTP-Server, der
|
||||
# selbst nicht synchronisiert ist, liefert Stratum 16; Clients verwerfen das
|
||||
# und bleiben genau da stehen, wo ap1/ap2 stehen: `waiting`.
|
||||
#
|
||||
# Damit ist die Kette vollstaendig: der Standort hatte **an keiner Stelle** eine
|
||||
# funktionierende Zeitsynchronisation. Dass die Uhren von core/branch/ap1
|
||||
# trotzdem stimmten, war Restglueck vom letzten manuellen Stellen — ap2 ist
|
||||
# einfach als erstes weggelaufen (17 h).
|
||||
#
|
||||
# Upstream ueber Namen ist unproblematisch: der Core loest seit TP23 Stufe 1
|
||||
# selbst per DoH auf.
|
||||
:do { /system ntp client set enabled=yes servers=time.cloudflare.com,at.pool.ntp.org } on-error={ :log info "tp19ntp: client warf" }
|
||||
:log info ("tp19ntp: core-client status=" . [/system ntp client get status])
|
||||
14
routeros/tp19-ntp-dhcp-option.rsc
Normal file
14
routeros/tp19-ntp-dhcp-option.rsc
Normal file
@@ -0,0 +1,14 @@
|
||||
# NTP-Server per DHCP ausliefern (Christophs Vorschlag 2026-08-18).
|
||||
#
|
||||
# WARUM DAS BESSER IST ALS PRO GERAET EINZUTRAGEN: bisher kannte nur die
|
||||
# MikroTik-Flotte eine Zeitquelle, und die per Hand. Ueber `ntp-server=` im
|
||||
# dhcp-server network bekommt **jeder** DHCP-Client den Standort-NTP-Server
|
||||
# mitgeliefert (DHCP-Option 42) — ohne dass irgendwo eine IP gepflegt werden
|
||||
# muss. Das Gateway des jeweiligen VLAN ist immer .1, also traegt jedes Netz
|
||||
# seinen eigenen ein.
|
||||
#
|
||||
# Voraussetzung ist erfuellt: der Core ist seit heute selbst `synchronized`
|
||||
# (tp19-ntp-core-client.rsc) und laeuft als Server (tp19-ntp-core-als-zeitquelle.rsc,
|
||||
# inkl. der input-Regel, ohne die er seit TP5 Etappe 4 unerreichbar waere).
|
||||
:foreach n in=[/ip dhcp-server network find] do={ :do { /ip dhcp-server network set $n ntp-server=([/ip dhcp-server network get $n gateway]) } on-error={ :log info "tp19ntp: dhcp-option warf" } }
|
||||
:log info ("tp19ntp: dhcp-netze-mit-ntp=" . [:tostr [:len [/ip dhcp-server network find where ntp-server!=""]]] . " von " . [:tostr [:len [/ip dhcp-server network find]]])
|
||||
71
routeros/tp21-branch-bootstrap.rsc
Normal file
71
routeros/tp21-branch-bootstrap.rsc
Normal file
@@ -0,0 +1,71 @@
|
||||
# TP21.1 — crs326-branch Bootstrap (Stand 2026-08-08, Rev 4)
|
||||
#
|
||||
# Hintergrund:
|
||||
# - WinBox-MAC-Scan zeigt 0.0.0.0, solange das Gerät auf dem Discovery-VLAN keine IP hat.
|
||||
# - Sichere Bring-up-Reihenfolge: Ports → VLAN-Tabelle → VLAN-Interfaces → IPs →
|
||||
# vlan-filtering → Werkseinstellungen bereinigen.
|
||||
# - bridge MUSS in jeder Bridge-VLAN-Zeile tagged sein, sonst sieht die CPU das VLAN nicht.
|
||||
# - NAS-Ports (ether2/8) sind tagged VLAN20 (NAS spricht selbst tagged).
|
||||
#
|
||||
# Vor dem Import: ether1 (Uplink) und ether24 (ap2) abziehen.
|
||||
# Nach dem Import: WinBox auf 10.40.10.2 verbinden, dann uplink einstecken.
|
||||
|
||||
/system identity set name=crs326-branch
|
||||
|
||||
/interface bridge port
|
||||
# Trunk-Ports (Uplink + AP + NAS)
|
||||
set [find interface=ether1] pvid=1 disabled=no
|
||||
set [find interface=ether2] pvid=1 disabled=no
|
||||
set [find interface=ether8] pvid=1 disabled=no
|
||||
set [find interface=ether24] pvid=1 disabled=no
|
||||
|
||||
# ACCESS-Ports
|
||||
set [find interface=ether3] pvid=10 disabled=no
|
||||
set [find interface=ether4] pvid=10 disabled=no
|
||||
set [find interface=ether5] pvid=40 disabled=no
|
||||
set [find interface=ether6] pvid=40 disabled=no
|
||||
set [find interface=ether7] pvid=20 disabled=no
|
||||
|
||||
# Restliche Ethernet-Ports flexibel als INFRA vorbelegen, aber enabled
|
||||
set [find interface=ether9] pvid=20 disabled=no
|
||||
set [find interface=ether10] pvid=20 disabled=no
|
||||
set [find interface=ether11] pvid=20 disabled=no
|
||||
set [find interface=ether12] pvid=20 disabled=no
|
||||
set [find interface=ether13] pvid=20 disabled=no
|
||||
set [find interface=ether14] pvid=20 disabled=no
|
||||
set [find interface=ether15] pvid=20 disabled=no
|
||||
set [find interface=ether16] pvid=20 disabled=no
|
||||
set [find interface=ether17] pvid=20 disabled=no
|
||||
set [find interface=ether18] pvid=20 disabled=no
|
||||
set [find interface=ether19] pvid=20 disabled=no
|
||||
set [find interface=ether20] pvid=20 disabled=no
|
||||
set [find interface=ether21] pvid=20 disabled=no
|
||||
set [find interface=ether22] pvid=20 disabled=no
|
||||
set [find interface=ether23] pvid=20 disabled=no
|
||||
set [find interface=sfp-sfpplus1] pvid=1 disabled=yes
|
||||
set [find interface=sfp-sfpplus2] pvid=1 disabled=yes
|
||||
|
||||
/interface bridge vlan
|
||||
add bridge=bridge tagged=ether1,ether24,bridge untagged=ether3,ether4 vlan-ids=10 comment=MAIN
|
||||
add bridge=bridge tagged=ether1,ether2,ether8,ether24,bridge untagged=ether7,ether9,ether10,ether11,ether12,ether13,ether14,ether15,ether16,ether17,ether18,ether19,ether20,ether21,ether22,ether23 vlan-ids=20 comment=INFRA
|
||||
add bridge=bridge tagged=ether1,ether24,bridge vlan-ids=30 comment=IOT
|
||||
add bridge=bridge tagged=ether1,ether24,bridge untagged=ether5,ether6 vlan-ids=40 comment=MEDIA
|
||||
add bridge=bridge tagged=ether1,ether24,bridge vlan-ids=50 comment=UNTRUSTED
|
||||
add bridge=bridge tagged=ether1,ether24,bridge vlan-ids=90 comment=GUEST
|
||||
add bridge=bridge tagged=ether1,ether24,bridge vlan-ids=99 comment=MGMT
|
||||
|
||||
/interface vlan add name=vlan10 interface=bridge vlan-id=10 comment="TEMP Mgmt VLAN10"
|
||||
/interface vlan add name=vlan99 interface=bridge vlan-id=99 comment=MGMT
|
||||
|
||||
/ip address
|
||||
add address=10.40.99.2/24 interface=vlan99 comment="TP21-mgmt-target"
|
||||
add address=10.40.10.2/24 interface=vlan10 comment="TEMP Bring-up VLAN10"
|
||||
|
||||
/ip dns set servers=10.40.99.1 allow-remote-requests=no
|
||||
|
||||
/interface bridge set [find name=bridge] vlan-filtering=yes
|
||||
|
||||
/ip route add dst-address=0.0.0.0/0 gateway=10.40.99.1 comment="TP21-default"
|
||||
|
||||
:do { /ip address remove [find address="192.168.88.1/24"] } on-error={}
|
||||
:do { /ip dhcp-client disable [find interface=bridge] } on-error={}
|
||||
82
routeros/tp21-core-dhcp-from-ap1.rsc
Normal file
82
routeros/tp21-core-dhcp-from-ap1.rsc
Normal file
@@ -0,0 +1,82 @@
|
||||
# TP21.1 core DHCP restore from ap1-pre-core-cutover-20260806-073616.rsc
|
||||
## options
|
||||
:do { /ip dhcp-server option add code=6 name="dns 1.1.1.1" value=0x01010101 } on-error={}
|
||||
## pools
|
||||
:do { /ip pool add name=pool-v10 ranges=10.40.10.100-10.40.10.200 } on-error={}
|
||||
:do { /ip pool add name=pool-v20 ranges=10.40.20.100-10.40.20.200 } on-error={}
|
||||
:do { /ip pool add name=pool-v30 ranges=10.40.30.100-10.40.30.250 } on-error={}
|
||||
:do { /ip pool add name=pool-v40 ranges=10.40.40.100-10.40.40.200 } on-error={}
|
||||
:do { /ip pool add name=pool-v50 ranges=10.40.50.100-10.40.50.200 } on-error={}
|
||||
:do { /ip pool add name=pool-v90 ranges=10.40.90.100-10.40.90.200 } on-error={}
|
||||
:do { /ip pool add name=pool-v99 ranges=10.40.99.100-10.40.99.200 } on-error={}
|
||||
## dhcp-servers
|
||||
:do { /ip dhcp-server add address-pool=pool-v10 comment=MAIN interface=vlan10 lease-time=1d name=dhcp-v10 } on-error={}
|
||||
:do { /ip dhcp-server add address-pool=pool-v20 comment=INFRA interface=vlan20 lease-time=1d name=dhcp-v20 } on-error={}
|
||||
:do { /ip dhcp-server add address-pool=pool-v30 comment=IOT interface=vlan30 lease-time=1d name=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server add address-pool=pool-v40 comment=MEDIA interface=vlan40 lease-time=1d name=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server add address-pool=pool-v50 comment=UNTRUSTED interface=vlan50 lease-time=1d name=dhcp-v50 } on-error={}
|
||||
:do { /ip dhcp-server add address-pool=pool-v90 comment=GUEST interface=vlan90 lease-time=12h name=dhcp-v90 } on-error={}
|
||||
:do { /ip dhcp-server add address-pool=pool-v99 comment=MGMT interface=vlan99 lease-time=1d name=dhcp-v99 } on-error={}
|
||||
## networks
|
||||
:do { /ip dhcp-server network add address=10.40.10.0/24 comment=MAIN dns-server=10.40.10.1 gateway=10.40.10.1 } on-error={}
|
||||
:do { /ip dhcp-server network add address=10.40.20.0/24 comment=INFRA dns-server=10.40.20.1 gateway=10.40.20.1 } on-error={}
|
||||
:do { /ip dhcp-server network add address=10.40.30.0/24 comment=IOT dns-server=10.40.30.1 gateway=10.40.30.1 } on-error={}
|
||||
:do { /ip dhcp-server network add address=10.40.40.0/24 comment=MEDIA dns-server=10.40.40.1 gateway=10.40.40.1 } on-error={}
|
||||
:do { /ip dhcp-server network add address=10.40.50.0/24 comment=UNTRUSTED dns-server=10.40.50.1 gateway=10.40.50.1 } on-error={}
|
||||
:do { /ip dhcp-server network add address=10.40.90.0/24 comment=GUEST dns-server=10.40.90.1 gateway=10.40.90.1 } on-error={}
|
||||
:do { /ip dhcp-server network add address=10.40.99.0/24 comment=MGMT dns-server=10.40.99.1 gateway=10.40.99.1 } on-error={}
|
||||
## leases
|
||||
:do { /ip dhcp-server lease add address=10.40.10.82 client-id=1:56:71:6c:22:e6:a9 dhcp-option="dns 1.1.1.1" mac-address=56:71:6C:22:E6:A9 server=dhcp-v10 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.10.196 client-id=1:f2:62:4c:e1:af:9 mac-address=F2:62:4C:E1:AF:09 server=dhcp-v10 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.40.199 client-id=1:48:a6:b8:b:63:10 mac-address=48:A6:B8:0B:63:10 server=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.40.191 client-id=1:34:7e:5c:32:37:96 mac-address=34:7E:5C:32:37:96 server=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.40.192 client-id=1:34:7e:5c:32:33:b8 mac-address=34:7E:5C:32:33:B8 server=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.40.193 client-id=1:78:28:ca:80:2a:f6 mac-address=78:28:CA:80:2A:F6 server=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.40.195 client-id=1:78:28:ca:82:16:c2 mac-address=78:28:CA:82:16:C2 server=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.40.201 client-id=1:94:9f:3e:49:59:ee mac-address=94:9F:3E:49:59:EE server=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.40.196 client-id=1:48:a6:b8:16:38:ae mac-address=48:A6:B8:16:38:AE server=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.40.197 client-id=1:48:a6:b8:14:fe:f2 mac-address=48:A6:B8:14:FE:F2 server=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.40.200 client-id=1:48:a6:b8:69:69:7b mac-address=48:A6:B8:69:69:7B server=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.40.194 client-id=1:48:a6:b8:14:fe:d0 mac-address=48:A6:B8:14:FE:D0 server=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.40.198 comment=SonosTerrasse mac-address=78:28:CA:D2:0D:AC server=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.202 comment=shelly-s22_kueche_steckdose3-2 mac-address=A0:85:E3:C8:65:34 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.203 comment=shelly-s23_dieleug-wohnzimmer_licht mac-address=AC:15:18:7B:62:20 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.205 comment=shelly-s25_bad_lichtschalter mac-address=98:A3:16:79:38:50 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.206 comment=shelly-s20_kueche_steckdosen2 mac-address=98:A3:16:7C:5F:EC server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.207 comment=shelly-s21_kueche_steckdosen4 mac-address=20:6E:F1:01:F9:F8 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.208 comment=shelly-s1_weihnachten_kueche mac-address=E4:B0:63:D7:C7:A4 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.209 comment=shelly-s2_weihnachten_terrasse mac-address=28:37:2F:36:F4:7C server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.210 comment=shelly-s3_weihnachten_kinderzimmer mac-address=E4:B0:63:E4:EF:7C server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.211 comment=shelly-s4_kueche_mikrowelle mac-address=E4:B0:63:E4:0F:30 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.212 comment=shelly-s5_kueche_backofen mac-address=D8:85:AC:0C:5C:C8 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.213 comment=shelly-s6_kueche_kuehlschrank mac-address=D0:CF:13:D8:18:FC server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.214 comment=shelly-s7_kueche_tiefkuehlschrank mac-address=D0:CF:13:D9:94:E8 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.215 comment=shelly-s8_kueche_geschirrspueler mac-address=E4:B0:63:FA:FD:E0 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.216 comment=shelly-s9_wohnzimmer_sideboard mac-address=E8:F6:0A:61:88:08 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.217 comment=shelly-s10_bad_sonos mac-address=E4:B0:63:FC:57:E4 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.218 comment=shelly-s11_kinderzimmer_sonos mac-address=E4:B0:63:FA:6C:00 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.219 comment=shelly-s12_dieleug_steckdosen mac-address=48:F6:EE:C8:E6:AC server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.220 comment=shelly-s13_arbeitszimmer_technik mac-address=48:F6:EE:DD:6A:F4 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.221 comment=shelly-s14_schlafzimmer_bett mac-address=E4:B0:63:FC:59:48 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.222 comment=shelly-s15_technik_pve mac-address=E4:B0:63:FA:D5:34 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.223 comment=shelly-s16_wohnzimmer_steckdosen mac-address=10:20:BA:FA:F5:40 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.224 comment=shelly-s17_bad_steckdosen mac-address=10:20:BA:FB:6D:64 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.225 comment=shelly-s18_kueche_steckdosen1 mac-address=48:F6:EE:CC:16:E4 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.226 comment=shelly-s19_kueche_steckdosen3 mac-address=10:20:BA:FB:70:FC server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.227 comment=switchbot-floorlamp mac-address=B8:F8:62:09:F2:04 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.228 comment=Twinkly_Weihnachtsgirlande mac-address=98:F4:AB:2C:A7:88 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.230 comment=Withings_waage mac-address=00:24:E4:40:2A:72 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.231 comment=Withings_blutdruck mac-address=A4:7E:FA:18:2C:64 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.232 comment=pve-homematic-raspi-ccu mac-address=BC:24:11:8E:0A:57 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.233 comment=shelly-s26_bad_luefter mac-address=98:A3:16:7A:A3:54 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.236 comment=lichterkette mac-address=A4:F0:0F:5F:D0:EC server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.237 comment=lichterkette-mini mac-address=24:DC:C3:9B:89:64 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.241 comment=NukiSmartlock mac-address=28:DB:A7:09:7B:54 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.244 comment=NukiBridge mac-address=24:62:AB:B1:63:F4 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.8 comment=DTUBI-414392337823 mac-address=54:F2:9F:12:51:F0 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.20.10 comment=nas-bf mac-address=90:09:D0:58:20:F9 server=dhcp-v20 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.40.11 comment=tv mac-address=70:AF:24:B8:C9:86 server=dhcp-v40 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.5 comment=P750W mac-address=4C:EB:BD:E3:25:F2 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.180 client-id=1:e4:bc:96:1f:b2:81 comment=Airfryer dhcp-option="dns 1.1.1.1" mac-address=E4:BC:96:1F:B2:81 server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.204 comment=shelly-s24_bad_spiegelschrank mac-address=14:33:5C:D8:2D:7C server=dhcp-v30 } on-error={}
|
||||
:do { /ip dhcp-server lease add address=10.40.30.150 client-id=1:fc:ee:11:3:32:26 comment=Ender3V3KE-3226 mac-address=FC:EE:11:03:32:26 server=dhcp-v30 } on-error={}
|
||||
40
routeros/tp21-core-wan-wg-restore.rsc
Normal file
40
routeros/tp21-core-wan-wg-restore.rsc
Normal file
@@ -0,0 +1,40 @@
|
||||
# TP21.1 — crs326-core WAN + WG-Hub + NAT restore (2026-08-08)
|
||||
#
|
||||
# Kontext: Beim Core-Cutover (ap1 -> crs326-core als L3-Router) fehlten nach dem
|
||||
# ap1-Plattmachen auf core noch WAN-Egress und der WG-Hub. DHCP wurde separat
|
||||
# via tp21-core-dhcp-from-ap1.rsc wiederhergestellt.
|
||||
# Quelle = letztes ap1-Backup routeros/ap1-pre-core-cutover-20260806-073616.rsc.
|
||||
#
|
||||
# WICHTIG (disabled-Falle): ap1 hatte 3 Masquerade-Regeln, davon 2 disabled=yes
|
||||
# (out-interface=bridge / out-interface=ether1). Auf core NUR die WAN-Variante
|
||||
# (out-interface-list=WAN, wobei WAN-Liste = vlan100). Die disabled-Regeln NICHT
|
||||
# übernehmen.
|
||||
#
|
||||
# Der WG-Privkey ist ein Secret und steht NICHT hier -> aus routeros/ap1-wg-hub.privkey
|
||||
# (gitignored) einsetzen. Der abgeleitete Hub-Pubkey bleibt identisch
|
||||
# (P/bztIk13cAmLHbN6oHGGnWAKLZsqR5TXAbFP+NGGBk=), damit FM/DW-Spokes weiter matchen.
|
||||
|
||||
# --- WG-Hub (TP10 Multi-Site VPN) ---
|
||||
:do { /interface wireguard add name=wg-hub listen-port=51821 mtu=1412 comment="TP10 Multi-Site VPN Hub (FM/DW spokes)" } on-error={}
|
||||
:do { /interface wireguard set [find name=wg-hub] private-key="<aus routeros/ap1-wg-hub.privkey>" } on-error={}
|
||||
:do { /interface wireguard peers add interface=wg-hub name=fm comment=fm allowed-address=10.101.0.0/24 endpoint-address=abxhutfgsid9snmy.myfritz.net endpoint-port=52476 public-key="dzRY0lnnUygijChWe5wXZmXPeNcbdALpqBptA3fyiVE=" } on-error={}
|
||||
:do { /interface wireguard peers add interface=wg-hub name=dw comment=dw allowed-address=10.95.10.0/24 public-key="FqYZLztQ/qME5VDie5QLGH++5299WJiE1dPpQnPbzUw=" } on-error={}
|
||||
:do { /ip route add dst-address=10.101.0.0/24 gateway=wg-hub comment="TP10: FM spoke -> wg-hub" } on-error={}
|
||||
:do { /ip route add dst-address=10.95.10.0/24 gateway=wg-hub comment="TP10: DW spoke -> wg-hub" } on-error={}
|
||||
|
||||
# --- NAT (nur WAN-Variante; bridge/ether1-Masquerade bewusst NICHT) ---
|
||||
:do { /ip firewall nat add action=accept chain=srcnat dst-address=10.40.0.0/16 comment="TP4: no-NAT inter-VLAN (LAN-internal, before masquerade)" } on-error={}
|
||||
:do { /ip firewall nat add action=masquerade chain=srcnat out-interface-list=WAN ipsec-policy=out,none comment="defconf: masquerade" } on-error={}
|
||||
|
||||
# --- WAN dhcp-client auf vlan100 (Liwest); Blackhole-Selbst-Default-Route weg ---
|
||||
:do { /ip dhcp-client add interface=vlan100 use-peer-dns=no use-peer-ntp=no comment="WAN Arris DHCP (Liwest) via vlan100" } on-error={}
|
||||
:do { /ip route remove [find dst-address=0.0.0.0/0 gateway=10.40.99.1] } on-error={}
|
||||
|
||||
# --- DNS-Resolver (PROVISORISCH plain, DoH-TODO s.u.) ---
|
||||
# core hatte allow-remote-requests=no + leeren Upstream -> Client-DNS tot + FM-Hub
|
||||
# konnte myfritz nicht auflösen. Fix (plain, weil core keine CA-Certs hat -> certs=0,
|
||||
# verify-doh-cert unmöglich):
|
||||
:do { /ip dns set allow-remote-requests=yes servers=1.1.1.1 } on-error={}
|
||||
# TODO (spätere Session, VOR/mit WLAN-Rebuild): CA-Bundle auf core importieren, dann
|
||||
# DoH-Cloudflare-Gateway wie ap1 setzen:
|
||||
# /ip dns set use-doh-server=https://px35ynlol3.cloudflare-gateway.com/dns-query verify-doh-cert=yes
|
||||
48
routeros/tp23-stufe1-doh-core.rsc
Normal file
48
routeros/tp23-stufe1-doh-core.rsc
Normal file
@@ -0,0 +1,48 @@
|
||||
# TP23 Stufe 1 — DoH auf crs326-core (schliesst zugleich TP21.1 TODO 1).
|
||||
#
|
||||
# WARUM NUR EIN ROOT UND KEIN CA-BUNDLE
|
||||
# ------------------------------------
|
||||
# Die Kette von px35ynlol3.cloudflare-gateway.com ist
|
||||
# Leaf(CN=cloudflare-gateway.com) -> GTS WE1 -> GTS Root R4
|
||||
# (am 2026-08-17 per openssl s_client verifiziert). Fuer verify-doh-cert=yes
|
||||
# reicht der Root. Das ist hier kein Geiz, sondern Notwendigkeit: der Core hat
|
||||
# nur ~2,8 MB freien Flash, ein Mozilla-Bundle (~230 KB) waere Verschwendung
|
||||
# und muesste gepflegt werden. Der Root laeuft bis 2036, das Leaf rotiert
|
||||
# darunter ohne Zutun.
|
||||
#
|
||||
# Datei liegt schon auf dem Geraet: gtsrootr4.pem (per SFTP hochgeladen statt
|
||||
# per fetch geholt — fetch haette check-certificate=no gebraucht, also genau
|
||||
# die Pruefung ausgehebelt, die wir gerade aufbauen wollen).
|
||||
# SHA-256 des Roots, lokal gegengeprueft:
|
||||
# 34:9D:FA:40:58:C5:E2:63:12:3B:39:8A:E7:95:57:3C:4E:13:13:C8:3F:E6:8F:93:55:6C:D5:E8:03:1B:3C:7D
|
||||
#
|
||||
# servers=1.1.1.1 BLEIBT stehen: RouterOS loest damit den DoH-Hostnamen selbst
|
||||
# auf (Bootstrap). Ohne das haette man ein Henne-Ei. Alles andere laeuft danach
|
||||
# ueber DoH.
|
||||
#
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device crs326-core \
|
||||
# --commands-file routeros/tp23-stufe1-doh-core.rsc \
|
||||
# --change-id TP23-Stufe1-DoH --deploy \
|
||||
# --assert '/ip/dns|use-doh-server=https://px35ynlol3.cloudflare-gateway.com/dns-query' \
|
||||
# --assert '/ip/dns|verify-doh-cert=true'
|
||||
# Backup davor: core-pre-tp23-doh-20260817.backup
|
||||
#
|
||||
# Rollback: /ip dns set use-doh-server="" — eine Zeile, sofort wirksam.
|
||||
|
||||
# 1) Import. Idempotent: nur wenn der Root noch nicht da ist.
|
||||
:do { :if ([:len [/certificate find where common-name="GTS Root R4"]] = 0) do={ /certificate import file-name=gtsrootr4.pem passphrase="" } } on-error={ :log info "tp23s1: 01 import warf" }
|
||||
|
||||
# 2) Explizit vertrauen. Der Import allein setzt trusted nicht zuverlaessig,
|
||||
# und ohne trusted=yes scheitert verify-doh-cert=yes stumm.
|
||||
:do { /certificate set [find where common-name="GTS Root R4"] trusted=yes } on-error={ :log info "tp23s1: 02 trust warf" }
|
||||
|
||||
# 3) DoH scharf. verify-doh-cert=yes ist der ganze Punkt der Uebung — ohne
|
||||
# Pruefung waere DoH nur Verschleierung, kein Vertrauensanker.
|
||||
:do { /ip dns set use-doh-server=https://px35ynlol3.cloudflare-gateway.com/dns-query verify-doh-cert=yes } on-error={ :log info "tp23s1: 03 doh-set warf" }
|
||||
|
||||
# 4) Cache leeren, damit die naechste Antwort nachweislich ueber DoH kommt und
|
||||
# nicht aus dem Bestand von vorher.
|
||||
:do { /ip dns cache flush } on-error={ :log info "tp23s1: 04 flush warf" }
|
||||
|
||||
# Selbstprotokoll — der Deploy-Job zeigt den Geraete-Output nicht.
|
||||
:log info ("tp23s1: ENDE roots=" . [:tostr [:len [/certificate find where common-name="GTS Root R4"]]] . " trusted=" . [:tostr [/certificate get [find where common-name="GTS Root R4"] trusted]] . " doh=" . [/ip dns get use-doh-server])
|
||||
31
routeros/tp25-infra-vaps-offline.rsc
Normal file
31
routeros/tp25-infra-vaps-offline.rsc
Normal file
@@ -0,0 +1,31 @@
|
||||
# TP25 — dirtyvader-infra offline nehmen (User-Entscheid 2026-08-17).
|
||||
#
|
||||
# Begruendung: INFRA-Geraete haengen am Kabel (schon in TP3 als "vertagt, Mgmt
|
||||
# verkabelt" angelegt). Die SSID hatte auf BEIDEN APs und BEIDEN Baendern
|
||||
# 0 Clients. Zwei VAPs weniger je AP = weniger Beacon-Airtime.
|
||||
#
|
||||
# 🔑 WARUM disable UND NICHT "hidden" (Christophs Rueckfrage):
|
||||
# Eine versteckte SSID sendet ihr Beacon WEITER — sie laesst nur das
|
||||
# SSID-Feld darin leer. Verstecken spart also KEINE Airtime, es macht die
|
||||
# SSID nur unbequemer zu finden (und ist kein Sicherheitsgewinn).
|
||||
# Airtime spart ausschliesslich das Abschalten der VAP.
|
||||
#
|
||||
# Reversibel: disabled=no setzt sie zurueck. sec-infra/dp-infra/cfg-infra
|
||||
# bleiben bestehen — die Zone ist damit jederzeit ohne Neuaufbau reaktivierbar.
|
||||
#
|
||||
# ⚠️ NICHT compliance-ueberwacht: die Sektion /interface wifi hat (Stand
|
||||
# 2026-08-17) keine Compliance-Rule. Diese Aenderung ist deshalb weder
|
||||
# Drift noch drift-gesichert — sie faellt unter die offene Luecke aus
|
||||
# TP25 Schritt 6.
|
||||
#
|
||||
# Push (BEIDE APs):
|
||||
# python3 nautobot/gc-manual-plan.py --device ap2 \
|
||||
# --commands-file routeros/tp25-infra-vaps-offline.rsc \
|
||||
# --change-id TP25-infra-offline-ap2 --deploy
|
||||
# ... dasselbe mit --device ap1
|
||||
|
||||
:do { /interface/wifi/set [find name=w2-infra] disabled=yes } on-error={ :log info "tp25i: w2-infra warf" }
|
||||
:do { /interface/wifi/set [find name=w5-infra] disabled=yes } on-error={ :log info "tp25i: w5-infra warf" }
|
||||
|
||||
# Gegenprobe im Log: erwartet aktive-vaps=9 (vorher 11), infra-disabled=true/true
|
||||
:log info ("tp25i: aktive-vaps=" . [:tostr [:len [/interface/wifi/find where !disabled]]] . " w2infra=" . [:tostr [/interface/wifi/get [find name=w2-infra] disabled]] . " w5infra=" . [:tostr [/interface/wifi/get [find name=w5-infra] disabled]])
|
||||
35
routeros/tp25-schritt1-3-ap1.rsc
Normal file
35
routeros/tp25-schritt1-3-ap1.rsc
Normal file
@@ -0,0 +1,35 @@
|
||||
# TP25 Schritt 1-3 auf ap1 — identisch zu ap2, mit der auf ap2 verifizierten Syntax.
|
||||
#
|
||||
# Reihenfolge bewusst: ap2 war zuerst (weniger kritisch), dort ist die Syntax
|
||||
# am Geraet belegt. ap1 folgt erst jetzt.
|
||||
#
|
||||
# ⚠️ ap1 MUSS mit, sonst bleibt die Ueberlappung: ap1 auf 5180 mit 80 MHz
|
||||
# belegt 5170-5250 und damit auch ap2s neue 40-MHz-Zelle bei 5220.
|
||||
# Ziel: ap1 = 5180/Ce (ch36+40, 5170-5210), ap2 = 5220/Ce (ch44+48,
|
||||
# 5210-5250). Benachbart, ueberlappungsfrei, beide 18 dBm.
|
||||
#
|
||||
# ap1-Besonderheit: w2-iot traegt hier ZUSAETZLICH channel.band=2ghz-n gegen
|
||||
# einen 2ghz-ax-Master — der eigentliche Fund D. Deshalb !channel.band mit dabei.
|
||||
#
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device ap1 \
|
||||
# --commands-file routeros/tp25-schritt1-3-ap1.rsc \
|
||||
# --change-id TP25-Funkparameter-ap1 --deploy
|
||||
# Backup davor: ap1-pre-tp25-20260817.backup
|
||||
|
||||
# --- Schritt 3 zuerst: Profil auf Sollwert, damit das Leeren unten direkt greift
|
||||
:do { /interface/wifi/channel/set [find name=ch-5g] frequency=5180 width=20/40mhz } on-error={ :log info "tp25a1: 01 ch-5g warf" }
|
||||
:do { /interface/wifi/channel/set [find name=ch-2g] frequency=2412 width=20mhz } on-error={ :log info "tp25a1: 02 ch-2g warf" }
|
||||
|
||||
# --- Schritt 2: Inline-Overrides einzeln leeren (!channel allein tut NICHTS) -
|
||||
:do { /interface/wifi/set [find default-name=wifi1] !channel.width } on-error={ :log info "tp25a1: 03 wifi1 !width warf" }
|
||||
:do { /interface/wifi/set [find default-name=wifi1] !channel.band } on-error={ :log info "tp25a1: 04 wifi1 !band warf" }
|
||||
:do { /interface/wifi/set [find default-name=wifi1] !channel.skip-dfs-channels } on-error={ :log info "tp25a1: 05 wifi1 !skipdfs warf" }
|
||||
:do { /interface/wifi/set [find default-name=wifi2] !channel.width } on-error={ :log info "tp25a1: 06 wifi2 !width warf" }
|
||||
:do { /interface/wifi/set [find default-name=wifi2] !channel.band } on-error={ :log info "tp25a1: 07 wifi2 !band warf" }
|
||||
:do { /interface/wifi/set [find default-name=wifi2] !channel.skip-dfs-channels } on-error={ :log info "tp25a1: 08 wifi2 !skipdfs warf" }
|
||||
|
||||
# --- Schritt 1: Fund D — Slave-VAP-Override weg -----------------------------
|
||||
:do { /interface/wifi/set [find name=w2-iot] !channel.width } on-error={ :log info "tp25a1: 09 w2-iot !width warf" }
|
||||
:do { /interface/wifi/set [find name=w2-iot] !channel.band } on-error={ :log info "tp25a1: 10 w2-iot !band warf" }
|
||||
|
||||
:log info ("tp25a1: wifi1-width=" . [:tostr [/interface/wifi/get [find default-name=wifi1] channel.width]] . " wifi2-width=" . [:tostr [/interface/wifi/get [find default-name=wifi2] channel.width]] . " w2iot-band=" . [:tostr [/interface/wifi/get [find name=w2-iot] channel.band]])
|
||||
43
routeros/tp25-schritt1-3-ap2.rsc
Normal file
43
routeros/tp25-schritt1-3-ap2.rsc
Normal file
@@ -0,0 +1,43 @@
|
||||
# TP25 Schritt 1-3 auf ap2 — Funkparameter nach Manual statt Bauchgefuehl.
|
||||
#
|
||||
# Schritt 1: unzulaessigen channel.*-Override von w2-iot entfernen (Slave-VAP
|
||||
# kann keinen eigenen Kanal haben; auf ap1 erzwang er sogar 2ghz-n
|
||||
# gegen einen 2ghz-ax-Master).
|
||||
# Schritt 2: Inline-channel.*-Overrides auf wifi1/wifi2 leeren, damit die
|
||||
# verlinkten Profile ch-5g/ch-2g ueberhaupt greifen. Das Override
|
||||
# gewinnt sonst — deshalb lief 2,4 GHz auf 40 MHz, obwohl ch-2g
|
||||
# width=20mhz sagt.
|
||||
# Schritt 3: ch-5g auf 20/40mhz + Frequenz 5220 (Indoor-Band, statt 5745
|
||||
# ETSI-Band-C mit gedrosselter Leistung -> Messung s.u.).
|
||||
#
|
||||
# MESSZWECK: nach dem Deploy tx-power auf wifi1 lesen. Erwartung 18 dBm statt 9.
|
||||
# Bestaetigt oder widerlegt die Diagnose "ch149 kostet 9 dB" AM GERAET.
|
||||
#
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device ap2 \
|
||||
# --commands-file routeros/tp25-schritt1-3-ap2.rsc \
|
||||
# --change-id TP25-Funkparameter-ap2 --deploy
|
||||
# Backup davor: ap2-pre-tp25-20260817.backup
|
||||
#
|
||||
# ⚠️ Wirft alle Clients kurz raus (Channel-/VAP-Re-Apply, bei TP3.3 gemessen).
|
||||
|
||||
# --- Schritt 1: w2-iot Slave-Override weg -----------------------------------
|
||||
:do { /interface/wifi/set [find name=w2-iot] !channel } on-error={ :log info "tp25: 01 w2-iot !channel warf" }
|
||||
|
||||
# --- Schritt 2: Inline-Overrides auf den Master-Radios weg ------------------
|
||||
# Nur channel.* wird geleert. configuration=/configuration.manager/.mode
|
||||
# bleiben unangetastet — die sind korrekt und tragen die SSID-Bindung.
|
||||
:do { /interface/wifi/set [find default-name=wifi1] !channel } on-error={ :log info "tp25: 02 wifi1 !channel warf" }
|
||||
:do { /interface/wifi/set [find default-name=wifi2] !channel } on-error={ :log info "tp25: 03 wifi2 !channel warf" }
|
||||
|
||||
# --- Schritt 3: Profile auf Manual-konforme Werte ---------------------------
|
||||
# 5 GHz: 80 -> 40 MHz. Kostet Spitzendurchsatz, den hier niemand braucht, und
|
||||
# gewinnt ~3 dB Randabdeckung. Erst 40 MHz macht zwei ueberlappungsfreie
|
||||
# Zellen im Indoor-Band ueberhaupt moeglich (dort liegt nur EIN 80-MHz-Block).
|
||||
:do { /interface/wifi/channel/set [find name=ch-5g] frequency=5220 width=20/40mhz } on-error={ :log info "tp25: 04 ch-5g warf" }
|
||||
|
||||
# 2,4 GHz: Profil steht schon auf 20mhz — nach Schritt 2 greift es endlich.
|
||||
# Zur Sicherheit explizit, damit der Sollzustand in der SoT eindeutig ist.
|
||||
:do { /interface/wifi/channel/set [find name=ch-2g] frequency=2462 width=20mhz } on-error={ :log info "tp25: 05 ch-2g warf" }
|
||||
|
||||
# --- Selbstprotokoll (Deploy-Job zeigt den Geraete-Output nicht) ------------
|
||||
:log info ("tp25ap2: ch-5g=" . [/interface/wifi/channel/get [find name=ch-5g] frequency] . "/" . [/interface/wifi/channel/get [find name=ch-5g] width] . " ch-2g=" . [/interface/wifi/channel/get [find name=ch-2g] frequency] . "/" . [/interface/wifi/channel/get [find name=ch-2g] width])
|
||||
42
routeros/tp25-schritt2-fix-overrides-ap2.rsc
Normal file
42
routeros/tp25-schritt2-fix-overrides-ap2.rsc
Normal file
@@ -0,0 +1,42 @@
|
||||
# TP25 Schritt 2 — KORREKTUR. Die Inline-Overrides sind noch da.
|
||||
#
|
||||
# 🔴 GOTCHA (2026-08-17 am Geraet belegt): `/interface/wifi/set <if> !channel`
|
||||
# loescht die Inline-Sub-Property-Overrides NICHT. Es wirft auch nicht — es
|
||||
# tut einfach nichts Sichtbares. Nach dem Lauf stand auf ap2 wifi1 weiterhin
|
||||
# `channel.width=20/40/80mhz`, obwohl das Profil ch-5g auf 20/40mhz steht
|
||||
# und cfg-main-5g korrekt zu 20/40mhz aufloest.
|
||||
# => Sub-Properties muessen EINZELN geleert werden: !channel.width usw.
|
||||
# Gleiches Muster wie der bekannte `!configuration.ssid !security.*`-Griff
|
||||
# aus dem TP3-Bring-up (CLAUDE.md) — dort nur nie auf channel.* angewandt.
|
||||
#
|
||||
# 🔴 DRINGLICHKEIT: weil die Breite noch auf 80 MHz stand, ist ap2 mit dem
|
||||
# Frequenzwechsel auf 5220/eeCe in DENSELBEN 80-MHz-Block wie ap1
|
||||
# (5180/Ceee) gerutscht — beide belegen ch36-48. Das ist die Co-Channel-Lage,
|
||||
# die TP3 2026-06-18 ueberhaupt erst wegkonfigurieren wollte. Diese Datei
|
||||
# stellt den ueberlappungsfreien Zustand her.
|
||||
#
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device ap2 \
|
||||
# --commands-file routeros/tp25-schritt2-fix-overrides-ap2.rsc \
|
||||
# --change-id TP25-Overrides-ap2 --deploy
|
||||
# Backup: ap2-pre-tp25-20260817.backup gilt weiter.
|
||||
#
|
||||
# SOLL danach: wifi1 = 5220/ax/Ce/I (40 MHz, ch44+48), wifi2 = 2462/ax (20 MHz).
|
||||
|
||||
# --- wifi1: jede Sub-Property einzeln leeren --------------------------------
|
||||
:do { /interface/wifi/set [find default-name=wifi1] !channel.width } on-error={ :log info "tp25f: 01 wifi1 !width warf" }
|
||||
:do { /interface/wifi/set [find default-name=wifi1] !channel.band } on-error={ :log info "tp25f: 02 wifi1 !band warf" }
|
||||
:do { /interface/wifi/set [find default-name=wifi1] !channel.skip-dfs-channels } on-error={ :log info "tp25f: 03 wifi1 !skipdfs warf" }
|
||||
|
||||
# --- wifi2: dito. Danach greift ch-2g mit width=20mhz --------------------
|
||||
:do { /interface/wifi/set [find default-name=wifi2] !channel.width } on-error={ :log info "tp25f: 04 wifi2 !width warf" }
|
||||
:do { /interface/wifi/set [find default-name=wifi2] !channel.band } on-error={ :log info "tp25f: 05 wifi2 !band warf" }
|
||||
:do { /interface/wifi/set [find default-name=wifi2] !channel.skip-dfs-channels } on-error={ :log info "tp25f: 06 wifi2 !skipdfs warf" }
|
||||
|
||||
# --- w2-iot: der eigentliche Fund D ----------------------------------------
|
||||
# Ein Slave-VAP darf keinen eigenen Kanal haben. Auf ap2 ist es nur width,
|
||||
# auf ap1 zusaetzlich band=2ghz-n gegen einen 2ghz-ax-Master.
|
||||
:do { /interface/wifi/set [find name=w2-iot] !channel.width } on-error={ :log info "tp25f: 07 w2-iot !width warf" }
|
||||
:do { /interface/wifi/set [find name=w2-iot] !channel.band } on-error={ :log info "tp25f: 08 w2-iot !band warf" }
|
||||
|
||||
# --- Selbstprotokoll: die AUFGELOESTEN Interface-Werte, nicht das Profil ----
|
||||
:log info ("tp25f: wifi1-width=" . [:tostr [/interface/wifi/get [find default-name=wifi1] channel.width]] . " wifi2-width=" . [:tostr [/interface/wifi/get [find default-name=wifi2] channel.width]] . " w2iot-width=" . [:tostr [/interface/wifi/get [find name=w2-iot] channel.width]])
|
||||
48
routeros/tp26-ap-firewall-cleanup.rsc
Normal file
48
routeros/tp26-ap-firewall-cleanup.rsc
Normal 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]]])
|
||||
37
routeros/tp27-routerboot-firmware-724.rsc
Normal file
37
routeros/tp27-routerboot-firmware-724.rsc
Normal file
@@ -0,0 +1,37 @@
|
||||
# TP27 — RouterBOOT-Firmware auf 7.24 nachziehen (2026-08-17).
|
||||
#
|
||||
# KONTEXT: Christoph hat alle vier MikroTik selbst auf RouterOS 7.24 stable
|
||||
# gehoben. Verifiziert, nichts kaputt. Was dabei offen blieb, ist die zweite
|
||||
# Haelfte jedes MikroTik-Upgrades: die **RouterBOOT-Firmware** haengt zurueck.
|
||||
#
|
||||
# crs326-core 7.19.5 -> 7.24
|
||||
# crs326-branch 7.19.5 -> 7.24
|
||||
# ap1 7.23.2 -> 7.24
|
||||
# ap2 7.23.2 -> 7.24
|
||||
#
|
||||
# `/system routerboard upgrade` SCHREIBT die Firmware nur; wirksam wird sie
|
||||
# erst beim naechsten Reboot. Darum: erst schreiben, dann gezielt rebooten,
|
||||
# dann `current-firmware` gegenpruefen — vorher zeigt sie weiter den alten Wert.
|
||||
#
|
||||
# WARUM UEBER GC UND NICHT MikroMCP: `/system routerboard upgrade*` steht auf
|
||||
# der MikroMCP-Deny-Liste (zu Recht — es schreibt den Bootloader). Der
|
||||
# GC-Weg ist ohnehin der vorgeschriebene.
|
||||
#
|
||||
# Push je Geraet:
|
||||
# python3 nautobot/gc-manual-plan.py --device <name> \
|
||||
# --commands-file routeros/tp27-routerboot-firmware-724.rsc \
|
||||
# --change-id TP27-fw-<name> --deploy
|
||||
#
|
||||
# Danach Reboot (MikroMCP `reboot`), dann:
|
||||
# current-firmware muss 7.24 sein.
|
||||
#
|
||||
# REIHENFOLGE (bewusst): ap2 -> ap1 -> core -> branch.
|
||||
# branch zuletzt, weil der Arbeitsplatz per LAN daran haengt — er ist die
|
||||
# Lifeline zu allen anderen Geraeten und wird erst angefasst, wenn der Rest
|
||||
# nachweislich sauber oben ist.
|
||||
#
|
||||
# Backups davor: <geraet>-post724-pre-fw-20260817.backup
|
||||
|
||||
:do { /system routerboard upgrade } on-error={ :log info "tp27: upgrade warf" }
|
||||
|
||||
:log info ("tp27: fw-geschrieben current=" . [/system/routerboard/get current-firmware] . " upgrade=" . [/system/routerboard/get upgrade-firmware] . " (current wechselt erst nach dem Reboot)")
|
||||
63
routeros/tp28-ap-wifi-reste-abraeumen.rsc
Normal file
63
routeros/tp28-ap-wifi-reste-abraeumen.rsc
Normal file
@@ -0,0 +1,63 @@
|
||||
# TP28 — die toten Standalone-WLAN-Objekte vom CAP abraeumen.
|
||||
#
|
||||
# BEFUND (2026-08-18): ap1 und ap2 tragen weiterhin die komplette WLAN-Config aus
|
||||
# dem TP3-Standalone-Aufbau — 2 channel, 6 datapath, 6 security, 7 configuration,
|
||||
# 1 steering. Seit dem CAPsMAN-Cutover (2026-08-17) kommt all das vom Manager und
|
||||
# wird auf dem CAP als DYNAMISCHES Interface angelegt; die statischen Objekte sind
|
||||
# wirkungslos. Sie im Template als Soll zu rendern hiesse, totes Zeug zur Absicht
|
||||
# zu erklaeren — dasselbe Argument, mit dem in TP26 die defconf-Firewallregeln der
|
||||
# APs nicht ins Template geschrieben wurden.
|
||||
#
|
||||
# ⚠️ REIHENFOLGE IST PFLICHT: `configuration` referenziert security, datapath und
|
||||
# channel. Wer die Referenzierten zuerst loescht, bekommt einen Fehler und laesst
|
||||
# einen Teil-Zustand zurueck (Netmiko-Lehre aus TP5 Etappe 1).
|
||||
#
|
||||
# 🔴 `[find !dynamic]` WIRFT HIER EINEN SYNTAXFEHLER (2026-08-18 aufgeschlagen):
|
||||
# `/interface wifi configuration` und Geschwister haben gar keine `dynamic`-
|
||||
# Eigenschaft -- die gibt es nur auf `/interface wifi` selbst. Der erste Versuch
|
||||
# lief deshalb komplett in die on-error-Zweige und aenderte NICHTS, meldete aber
|
||||
# "Plan Completed". Wieder ein Beleg: nur die Gegenpruefung am Geraet zaehlt.
|
||||
# Richtig ist hier schlicht `[find]` -- diese Objekte sind ausnahmslos statisch.
|
||||
#
|
||||
# ⚠️ Die dynamischen VAPs (`/interface wifi find dynamic`) werden NICHT angefasst.
|
||||
# Sie tragen ihre Werte inline (datapath.vlan-id=..., SSID im Kommentar) und
|
||||
# referenzieren kein lokales Objekt -- am Geraet gegengeprueft.
|
||||
#
|
||||
# Erwartung: die Client-Verbindungen bleiben unberuehrt, weil kein einziges dieser
|
||||
# Objekte von einem laufenden VAP referenziert wird.
|
||||
:do { /interface wifi configuration remove [find] } on-error={ :log info "tp28c: configuration warf" }
|
||||
:do { /interface wifi steering remove [find] } on-error={ :log info "tp28c: steering warf" }
|
||||
:do { /interface wifi security remove [find] } on-error={ :log info "tp28c: security warf" }
|
||||
:do { /interface wifi datapath remove [find] } on-error={ :log info "tp28c: datapath warf" }
|
||||
:do { /interface wifi channel remove [find] } on-error={ :log info "tp28c: channel warf" }
|
||||
|
||||
:log info ("tp28c: ENDE cfg=" . [:tostr [:len [/interface wifi configuration find]]] . " sec=" . [:tostr [:len [/interface wifi security find]]] . " dp=" . [:tostr [:len [/interface wifi datapath find]]] . " ch=" . [:tostr [:len [/interface wifi channel find]]] . " st=" . [:tostr [:len [/interface wifi steering find]]] . " cap-enabled=" . [:tostr [/interface wifi cap get enabled]])
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 🔴 NACHTRAG 2026-08-18, nach rund 14 h Ausfall von IOT + MEDIA:
|
||||
# Die Annahme oben ("Client-Verbindungen bleiben unberuehrt") stimmte — das
|
||||
# Skript hat den Ausfall NICHT ausgeloest. Die Bruchstelle liegt frueher, im
|
||||
# CAPsMAN-Cutover selbst (2026-08-17): dabei wurde `/interface wifi cap
|
||||
# slaves-datapath` nie gesetzt. 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 aber nur die
|
||||
# vlan-id. Seit dem Cutover assoziierten IOT-/MEDIA-Clients also sauber, ihre
|
||||
# Frames gingen nirgendwo hin — am Core kam auf vlan30/vlan40 kein einziges
|
||||
# Paket an. Die Master-Radios (wifi1/wifi2 = dirtyvader-main) sind statische
|
||||
# Bridge-Ports und liefen weiter, deshalb sah das WLAN von aussen "halb ok" aus.
|
||||
# Belege: `slaves-datapath` kommt in keiner Provisionierungs-Referenz vor
|
||||
# (routeros/.secrets/ap*-prov-base.rsc), und die letzten IOT-/MEDIA-Leases
|
||||
# stammen vom Abend des 2026-08-17.
|
||||
#
|
||||
# Dieses Skript hat den Schaden aber ZEMENTIERT: mit den geloeschten datapath-
|
||||
# Objekten gab es lokal nichts mehr, worauf `slaves-datapath` haette zeigen
|
||||
# koennen. Der naheliegende Ein-Zeilen-Fix war damit nicht mehr moeglich.
|
||||
#
|
||||
# Reparatur (ap1 und ap2, live 2026-08-18, seither im Template als Soll):
|
||||
# /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 kommt pro VAP vom Manager.
|
||||
#
|
||||
# LEHRE: `remove [find]` ohne Ruecksicht auf Referenzen aus /interface wifi cap.
|
||||
# Vor dem Abraeumen pruefen: :put [/interface wifi cap get slaves-datapath]
|
||||
# ---------------------------------------------------------------------------
|
||||
97
routeros/tp3-capsman.rsc
Normal file
97
routeros/tp3-capsman.rsc
Normal file
@@ -0,0 +1,97 @@
|
||||
# ===== AS-BUILT 2026-06-17: TP3 WLAN/CAPsMAN — finale dirtyvader-SSIDs =====
|
||||
# Angewendet via MikroMCP (run_command) auf ap1=10.40.41.1 (Manager+AP), ap2=10.40.41.2 (CAP).
|
||||
# Ersetzt capsman-flat-asbuilt.rsc + ap1-manager.rsc + ap2-cap.rsc (alle obsolet).
|
||||
#
|
||||
# ZIEL: 5 sichtbare SSIDs, beide APs, beide Bänder, je SSID -> eigenes VLAN (wifi datapath vlan-id).
|
||||
# dirtyvader-main(10) WPA3-only FT | dirtyvader-iot(30, NUR 2,4 GHz) WPA2+3
|
||||
# dirtyvader-media(40) WPA2+3 FT | dirtyvader-untrusted(50) WPA2+3 | dirtyvader-guest(90) WPA2+3
|
||||
# VERTAGT: hidden dirtyvader-infra(20) + dirtyvader-mgmt(99) — Mgmt verkabelt; ggf. TP8-Enterprise-SSID.
|
||||
# Passphrase = gemeinsames TEMP, Platzhalter __TEMP_PSK__ vor dem Anwenden ersetzen.
|
||||
# Echter Temp-Wert liegt (gitignored) in routeros/.secrets/tp3-capsman.psk; User ersetzt später pro security-Profil.
|
||||
#
|
||||
# KERNLEKTION (verifiziert 2026-06-17, RouterOS 7.23.1 wifi-Paket):
|
||||
# - Der CAPsMAN-MANAGER kann seine EIGENEN (lokalen) Radios NICHT über Provisioning beziehen
|
||||
# ("no connection to CAPsMAN, managed locally" / "SSID not set"). configuration.manager=capsman
|
||||
# fällt auf 'local' zurück, ohne Config => kein SSID.
|
||||
# - DAHER: ap1-Radios LOKAL zuweisen (Master via set, Slaves als statische virtual interfaces).
|
||||
# ap2 (remote CAP) zieht Master+Slaves DYNAMISCH über die Provisioning-Regeln. -> Asymmetrisch,
|
||||
# funktional identisch.
|
||||
# - Bandzuordnung verifiziert: wifi1 = 5 GHz, wifi2 = 2,4 GHz (auf BEIDEN APs). iot nur auf 2,4 GHz.
|
||||
# - reset = "/interface/wifi reset <if>" (NICHT 'reset-configuration' — existiert in 7.23 nicht).
|
||||
# - CAPsMAN/CA-Cert + ap2-Adoption blieben unberührt (kein Re-Adopt).
|
||||
|
||||
# ================= ap1 = MANAGER + AP =================
|
||||
|
||||
# --- Channels (non-DFS gepinnt; diese Frequenzen gelten fuer ap2 = CAP, ap1 wird unten lokal ueberschrieben) ---
|
||||
/interface/wifi/channel
|
||||
add name=ch-2g band=2ghz-ax width=20mhz frequency=2462 ;# ch11 (ap2)
|
||||
add name=ch-5g band=5ghz-ax width=20/40/80mhz frequency=5745 ;# ch149 non-DFS (ap2)
|
||||
|
||||
# --- Security je SSID (gemeinsames Temp-PW; FT nur main+media) ---
|
||||
/interface/wifi/security
|
||||
add name=sec-main authentication-types=wpa3-psk ft=yes ft-over-ds=yes passphrase="__TEMP_PSK__"
|
||||
add name=sec-iot authentication-types=wpa2-psk,wpa3-psk ft=no passphrase="__TEMP_PSK__"
|
||||
add name=sec-media authentication-types=wpa2-psk,wpa3-psk ft=no passphrase="__TEMP_PSK__" ;# ft=no: 802.11r bricht Sonos
|
||||
add name=sec-untrusted authentication-types=wpa2-psk,wpa3-psk ft=no passphrase="__TEMP_PSK__"
|
||||
add name=sec-guest authentication-types=wpa2-psk,wpa3-psk ft=no passphrase="__TEMP_PSK__"
|
||||
|
||||
# --- Datapath = SSID->VLAN (Bridge hat vlan-filtering=yes seit TP4) ---
|
||||
/interface/wifi/datapath
|
||||
add name=dp-main bridge=bridge vlan-id=10
|
||||
add name=dp-iot bridge=bridge vlan-id=30
|
||||
add name=dp-media bridge=bridge vlan-id=40
|
||||
add name=dp-untrusted bridge=bridge vlan-id=50
|
||||
add name=dp-guest bridge=bridge vlan-id=90
|
||||
|
||||
# --- Configuration je SSID (main band-spezifisch mit channel; Slaves ohne channel) ---
|
||||
/interface/wifi/configuration
|
||||
add name=cfg-main-5g ssid=dirtyvader-main mode=ap country=Austria security=sec-main datapath=dp-main channel=ch-5g
|
||||
add name=cfg-main-2g ssid=dirtyvader-main mode=ap country=Austria security=sec-main datapath=dp-main channel=ch-2g
|
||||
add name=cfg-iot ssid=dirtyvader-iot mode=ap country=Austria security=sec-iot datapath=dp-iot
|
||||
add name=cfg-media ssid=dirtyvader-media mode=ap country=Austria security=sec-media datapath=dp-media
|
||||
add name=cfg-untrusted ssid=dirtyvader-untrusted mode=ap country=Austria security=sec-untrusted datapath=dp-untrusted
|
||||
add name=cfg-guest ssid=dirtyvader-guest mode=ap country=Austria security=sec-guest datapath=dp-guest
|
||||
|
||||
# --- CAPsMAN bleibt enabled (CA/Cert auto, ap2-Pairing unberührt) ---
|
||||
# /interface/wifi/capsman set enabled=yes interfaces=bridge ;# war bereits aktiv
|
||||
|
||||
# --- Provisioning fuer ap2 (remote CAP): Master + Slaves; iot NUR in der 2-GHz-Regel ---
|
||||
/interface/wifi/provisioning
|
||||
add action=create-dynamic-enabled supported-bands=2ghz-ax master-configuration=cfg-main-2g \
|
||||
slave-configurations=cfg-iot,cfg-media,cfg-untrusted,cfg-guest
|
||||
add action=create-dynamic-enabled supported-bands=5ghz-ax master-configuration=cfg-main-5g \
|
||||
slave-configurations=cfg-media,cfg-untrusted,cfg-guest
|
||||
|
||||
# --- ap1-EIGENE Radios LOKAL zuweisen (Manager provisioniert sich nicht selbst!) ---
|
||||
/interface/wifi
|
||||
set wifi1 configuration=cfg-main-5g configuration.manager=local disabled=no channel.frequency=5180 ;# wifi1 = 5 GHz, ch36 (override gg. ch-5g)
|
||||
set wifi2 configuration=cfg-main-2g configuration.manager=local disabled=no channel.frequency=2412 ;# wifi2 = 2,4 GHz, ch1 (override gg. ch-2g)
|
||||
# Statische Slaves je Band (5 GHz ohne iot):
|
||||
add master-interface=wifi1 configuration=cfg-media name=w5-media disabled=no
|
||||
add master-interface=wifi1 configuration=cfg-untrusted name=w5-untrusted disabled=no
|
||||
add master-interface=wifi1 configuration=cfg-guest name=w5-guest disabled=no
|
||||
add master-interface=wifi2 configuration=cfg-iot name=w2-iot disabled=no
|
||||
add master-interface=wifi2 configuration=cfg-media name=w2-media disabled=no
|
||||
add master-interface=wifi2 configuration=cfg-untrusted name=w2-untrusted disabled=no
|
||||
add master-interface=wifi2 configuration=cfg-guest name=w2-guest disabled=no
|
||||
|
||||
# ================= ap2 = CAP (zieht alles vom Manager) =================
|
||||
# Keine Objekte noetig — ap2 war bereits adoptiert (remote-cap state=Ok). Nach Provisioning-Update
|
||||
# erscheinen dynamisch: wifi1(5G)=main + media/untrusted/guest ; wifi2(2,4G)=main + iot/media/untrusted/guest.
|
||||
# Falls je noetig: /interface/wifi/capsman/remote-cap provision [find]
|
||||
|
||||
# ================= VERIFIKATION (durchgefuehrt 2026-06-18) =================
|
||||
# ap1: monitor wifi1,wifi2 -> running, ch36/5180 (5G) + ch1/2412 (2,4G), tx-power ~18-25/15 dBm, 2 Clients FT-WPA3 VLAN10
|
||||
# ap2: print brief -> 9 IFs MBR/DBR running, ch149/5745 (5G) + ch11/2462 (2,4G), "managed by CAPsMAN 10.40.41.1"
|
||||
# ap1: /interface/wifi/capsman/remote-cap print -> ap2 STATE=Ok
|
||||
# Kanaele distinkt + non-DFS auf beiden Baendern (Co-Channel beseitigt). KANAL-AENDERUNG an ap2 braucht
|
||||
# manuellen Push: /interface/wifi/capsman/remote-cap provision [find]
|
||||
# Offen (User-Geraetetest): Client je SSID -> DHCP aus 10.40.{10,30,40,50,90}.x, list_wifi_clients vlan-id.
|
||||
|
||||
# ================= OFFENE PUNKTE / TUNING =================
|
||||
# - Echte Passphrasen pro security-Profil setzen (Temp ersetzen). User macht das selbst.
|
||||
# - Kanal-Plan erledigt: ap1 ch36/ch1, ap2 ch149/ch11 (alle non-DFS, ueberlappungsfrei).
|
||||
# - hidden dirtyvader-infra(20)/-mgmt(99) bei Bedarf nachziehen (sec WPA3-only, configuration.hide-ssid=yes).
|
||||
# - Sonos-Migration (TP7-Anschluss): 7 WLAN-Sonos noch auf FB-WLAN (VLAN1) -> auf dirtyvader-media (VLAN40)
|
||||
# holen, dann ist der Household geschlossen und mDNS-Repeater vlan10<->vlan40 liefert MAIN volle Discovery.
|
||||
# - TP8: eine 802.1X-SSID (dirtyvader-secure) mit FreeRADIUS-Dynamic-VLAN -> dann PSK-main/infra retiren.
|
||||
33
routeros/tp3.1-ap2-vlan.rsc
Normal file
33
routeros/tp3.1-ap2-vlan.rsc
Normal file
@@ -0,0 +1,33 @@
|
||||
# TP3.1 — ap2 VLAN-Trunk-Fix (As-built, 2026-07-01)
|
||||
# Kontext: ap2 (CAP, local forwarding) hatte bridge vlan-filtering=no → datapath.vlan-id
|
||||
# wurde nie auf die Leitung geschrieben → ALLE WLAN-Clients (main/media/iot/…) egressten
|
||||
# ungetaggt in VLAN1 (defconf/10.40.41.x). Fix: ap2-Bridge VLAN-scharf machen wie ap1.
|
||||
#
|
||||
# WICHTIG (Lockout): ap2-Mgmt (10.40.41.2) liegt untagged auf VLAN1 über die Bridge; MCP/SSH
|
||||
# läuft darüber. VLAN1 MUSS untagged=bridge,ether2 bleiben. Reihenfolge: erst Tabelle, dann Flip.
|
||||
# Kein Scheduler auf ap2 (device-mode=home) → kein Auto-Revert; Recovery = Power-Cycle im OG.
|
||||
#
|
||||
# Diese Datei ist ap2-LOKAL (nicht CAPsMAN-verwaltet). Auf ap2 ausführen.
|
||||
# Die master-Radios wifi1(5G)/wifi2(2.4G) tragen alle Client-VLANs getaggt; die Slave-VAPs
|
||||
# (media/iot/untrusted/guest) forwarden über ihren Master → nur wifi1/wifi2 müssen tagged-Member sein.
|
||||
# wifi1 (5G): main10 + media40 + untrusted50 + guest90
|
||||
# wifi2 (2.4G): main10 + iot30 + media40 + untrusted50 + guest90
|
||||
|
||||
/interface bridge vlan
|
||||
add bridge=bridge vlan-ids=1 untagged=bridge,ether2
|
||||
add bridge=bridge vlan-ids=10 tagged=ether2,wifi1,wifi2
|
||||
add bridge=bridge vlan-ids=30 tagged=ether2,wifi2
|
||||
add bridge=bridge vlan-ids=40 tagged=ether2,wifi1,wifi2
|
||||
add bridge=bridge vlan-ids=50 tagged=ether2,wifi1,wifi2
|
||||
add bridge=bridge vlan-ids=90 tagged=ether2,wifi1,wifi2
|
||||
|
||||
# Flip als LETZTER Schritt:
|
||||
/interface bridge set [find name=bridge] vlan-filtering=yes
|
||||
|
||||
# Danach auf ap1 einmalig re-provisionieren, damit der CAP sauber neu bindet:
|
||||
# /interface wifi capsman remote-cap provision [find identity=ap2]
|
||||
#
|
||||
# Verifikation:
|
||||
# /interface bridge vlan print detail → current-tagged je VLAN = ether2,wifi1(,wifi2)
|
||||
# OG-Client-Test: Handy auf dirtyvader-main im OG → auf ap1 muss der Lease server=dhcp-v10
|
||||
# (10.40.10.x) sein, NICHT defconf/10.40.41.x.
|
||||
50
routeros/tp5-e5-main-iot.rsc
Normal file
50
routeros/tp5-e5-main-iot.rsc
Normal file
@@ -0,0 +1,50 @@
|
||||
# TP5 Etappe 5 — MAIN -> IOT aufmachen.
|
||||
#
|
||||
# BEFUND (User-Meldung 2026-08-19: Brother P750W und die Shellys aus VLAN10
|
||||
# nicht erreichbar). Der Deny-by-default aus Etappe 3 arbeitet korrekt — es
|
||||
# gab schlicht nie eine vlan10->vlan30-Zeile. Offen waren nur MAIN->MEDIA,
|
||||
# MAIN->INFRA, MAIN->MGMT; IOT fehlte in der Liste.
|
||||
#
|
||||
# QUELLE: /opt/tp5-syslog/log/tp5-would-drop.log auf dem Docker-LXC,
|
||||
# gefiltert auf "in:vlan10 out:vlan30". Aggregiert:
|
||||
# 497 ICMP (Ping auf .30.5 und die Shellys)
|
||||
# 489 udp 5353 mDNS
|
||||
# 489 udp 137 NetBIOS
|
||||
# 237 udp 3722 Apple-Continuity -> .30.201
|
||||
# 40 udp 161 SNMP -> 10.40.30.5 (Brother P750W)
|
||||
# Quellen: .10.183 (1596, Subnetz-Sweep), .10.180 (118), .10.82 (38).
|
||||
#
|
||||
# MERKREGEL AUS DEM LOG: der Drucker faellt mit udp/161 auf, NICHT mit 631.
|
||||
# macOS fragt zuerst den SNMP-Status ab und bricht ab, bevor es zu IPP kommt.
|
||||
# Wer nur 631 whitelistet, repariert nichts.
|
||||
#
|
||||
# ENTSCHEID (User, 2026-08-19): voll einbahnig, kein Portfilter.
|
||||
# - MAIN ist das vertrauenswuerdige VLAN und steht zu INFRA/MEDIA/MGMT
|
||||
# ohnehin schon vollstaendig offen — INFRA haelt NAS, Proxmox und
|
||||
# Nautobot, also deutlich mehr Wert als die Shellys. MAIN->IOT eng zu
|
||||
# filtern waere an dieser Stelle Symbolik, kostet aber bei jedem neuen
|
||||
# IoT-Geraet eine Runde Fehlersuche.
|
||||
# - Der Sicherheitswert der Segmentierung sitzt in der GEGENRICHTUNG:
|
||||
# IOT->MAIN bekommt bewusst KEIN accept und bleibt gedroppt. Antworten
|
||||
# auf Anfragen aus MAIN laufen ueber "defconf: accept est,rel,untracked",
|
||||
# dafuer braucht es keine Regel.
|
||||
#
|
||||
# NEBENWIRKUNG, bewusst in Kauf genommen: der Subnetz-Sweep von .10.183
|
||||
# (137/5353 an alle 254 Adressen) laeuft ab jetzt durch, statt im Drop-Log
|
||||
# aufzulaufen. Betriebsneutral, aber der Log wird an dieser Stelle leiser —
|
||||
# nicht mit "Problem geloest" verwechseln.
|
||||
#
|
||||
# INPUT-KETTE: unveraendert. "TP5-E4: MAIN->core admin" und
|
||||
# "TP5: mDNS in vlan30" stehen bereits, der Core braucht nichts.
|
||||
#
|
||||
# BLOCKIERT NICHTS: ausschliesslich action=accept.
|
||||
#
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device crs326-core \
|
||||
# --commands-file routeros/tp5-e5-main-iot.rsc \
|
||||
# --change-id TP5-E5-MAIN-IOT --deploy \
|
||||
# --assert '/ip/firewall/filter?comment=TP5-E5: MAIN->IOT|count=1'
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# 1) MAIN -> IOT, einbahnig. place-before die Log-Regel, damit sie vor dem
|
||||
# Drop greift und der Log weiter zeigt, was uebrig bleibt.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E5: MAIN->IOT"]] = 0) do={ /ip firewall filter add chain=forward action=accept in-interface=vlan10 out-interface=vlan30 comment="TP5-E5: MAIN->IOT" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e5: 01 MAIN->IOT warf" }
|
||||
74
routeros/tp5-etappe1-log-lauf.rsc
Normal file
74
routeros/tp5-etappe1-log-lauf.rsc
Normal file
@@ -0,0 +1,74 @@
|
||||
# TP5 Etappe 1 — Log-Lauf auf crs326-core. Blockiert NICHTS.
|
||||
# Ausgerollt 2026-08-14 ueber Nautobot GC als manual Config Plans (Governance TP22),
|
||||
# nicht per Direkt-Write. Backup davor: core-pre-tp5-etappe1-20260814.backup
|
||||
#
|
||||
# Diese Datei bildet den AUSGEROLLTEN Endzustand ab. Der Weg dorthin brauchte
|
||||
# mehrere Anlaeufe; die Lehren stehen unten, damit Etappe 2-4 sie nicht wiederholen.
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device crs326-core \
|
||||
# --commands-file routeros/tp5-etappe1-log-lauf.rsc --change-id TP5-Etappe1 --deploy
|
||||
|
||||
# --- 1) Syslog-Ziel ---------------------------------------------------------
|
||||
# Der Core hat nur ~3 MB freien Flash -> Disk-Logging faellt aus (Platz + Flash-Verschleiss),
|
||||
# und der Memory-Ring fasst 1000 Zeilen, den wickelt der Log-Lauf in Minuten um.
|
||||
# Kollektor: syslog-ng auf dem Docker-LXC, 10.40.20.18:514 (Container `tp5-syslog`,
|
||||
# Config /opt/tp5-syslog/config/syslog-ng.conf, Logs /opt/tp5-syslog/log/).
|
||||
# ACHTUNG Name ohne Bindestrich — s. Lehre 1.
|
||||
:do { /system logging action add name="tp5syslog" target=remote } on-error={ :log info "tp5: action add hat geworfen" }
|
||||
:do { /system logging action set [find name="tp5syslog"] remote=10.40.20.18 remote-port=514 } on-error={ :log info "tp5: action set hat geworfen" }
|
||||
|
||||
# --- 2) firewall-Topic an den Kollektor -------------------------------------
|
||||
:do { /system logging add action="tp5syslog" topics=firewall } on-error={ :log info "tp5: logging rule hat geworfen" }
|
||||
|
||||
# --- 3) firewall aus dem Memory-Ring nehmen ---------------------------------
|
||||
# Sonst besteht der 1000-Zeilen-Puffer tagelang zu 100 % aus TP5-Zeilen und der
|
||||
# On-Box-Log ist fuer jede andere Fehlersuche wertlos — genau dann, wenn man ihn braucht.
|
||||
# Matcher live geprueft: topics=info trifft NICHT (Listen-Property), topics~"info" trifft genau 1.
|
||||
# Rueckbau am Ende von Etappe 1: topics=info
|
||||
/system logging set [find topics~"info" and action=memory] topics=info,!firewall
|
||||
|
||||
# --- 4) Die Log-Regel ans ENDE der forward-Kette ----------------------------
|
||||
# action=log ist nicht-terminierend: das Paket laeuft weiter und faellt danach aus
|
||||
# der Kette in die Default-Policy (accept). Es wird nichts blockiert.
|
||||
/ip firewall filter add action=log chain=forward comment="TP5: log-only, Vorstufe zum deny-by-default" log-prefix="TP5-WOULD-DROP"
|
||||
|
||||
# --- 5) Einengung auf Nicht-WAN --------------------------------------------
|
||||
# Der erste Lauf zeigte, dass die Regel auch saemtlichen Internet-Verkehr faengt
|
||||
# (out:vlan100) — bei 242 Zeilen/min war ein Viertel davon WAN-bound, unter Last mehr.
|
||||
# LAN->WAN ist eine GARANTIERTE Whitelist-Zeile (ohne sie hat kein VLAN Internet,
|
||||
# auch die "Internet-only"-VLANs 50/90 nicht), also reines Rauschen fuer die Matrix,
|
||||
# die Etappe 2 ableiten soll.
|
||||
# 🔴 MERKPOSTEN FUER ETAPPE 3: der spaetere drop DARF NICHT bare ans Kettenende —
|
||||
# davor gehoert `accept out-interface-list=WAN`, sonst ist das ganze Haus offline.
|
||||
# Diese Zeile ist bekannt und muss nicht aus dem Log wiederentdeckt werden.
|
||||
/ip firewall filter set [find comment="TP5: log-only, Vorstufe zum deny-by-default"] out-interface-list="!WAN"
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# LEHREN AUS DEM ROLLOUT (jede am Geraet belegt, nicht vermutet)
|
||||
# ===========================================================================
|
||||
#
|
||||
# 1) 🔴 BINDESTRICHE IN `name=` WERDEN ABGELEHNT — der teuerste Fund.
|
||||
# /system logging action add name="tp5-remote" target=remote -> wirft
|
||||
# /system logging action add name="tp5-abc" target=remote -> wirft
|
||||
# /system logging action add name="tp5syslog" target=remote -> geht
|
||||
# Quoten hilft NICHT. Isoliert per :do/on-error-Plan mit Zaehler-Checkpoints.
|
||||
# Zwischenzeitlich hatte ich das faelschlich der Reihenfolge `target=`/`remote=`
|
||||
# im selben add-Statement zugeschrieben — diese Erklaerung ist WIDERLEGT
|
||||
# (`set remote=... remote-port=...` in einem Statement laeuft anstandslos).
|
||||
#
|
||||
# 2) 🔴 EIN GESCHEITERTER NETMIKO-DEPLOY HINTERLAESST EINEN TEIL-ZUSTAND.
|
||||
# Die TP22-Notiz "gescheiterter Deploy = sauberer Fehlschlag" galt dem NAPALM-Weg,
|
||||
# der scheiterte, BEVOR er das Geraet anfasste. Netmiko schickt Zeile fuer Zeile
|
||||
# und laesst Abgesetztes stehen: der erste Push hier hinterliess Zeile 3+4 auf dem
|
||||
# Geraet, ohne 1+2. **Nach jedem Fehlschlag den Geraete-Ist-Stand pruefen.**
|
||||
#
|
||||
# 3) KEINE `print`-ZEILEN IN EINEN CONFIG PLAN. Ein `/system identity print` als
|
||||
# Kanarienzeile hat die unmittelbar folgende Zeile verschluckt und eine
|
||||
# Fehldiagnose erzeugt. Config Plans enthalten nur schreibende Kommandos.
|
||||
#
|
||||
# 4) SELBSTPROTOKOLLIERENDE PLAENE SIND DIE DIAGNOSE-METHODE DER WAHL.
|
||||
# Der Deploy-Job liefert nur "E1028: found bad/failed/failure in output" und
|
||||
# zeigt den Geraete-Output NICHT. Wickelt man jedes Kommando in
|
||||
# `:do {...} on-error={ :log info "..." }` und setzt danach eine Zaehlzeile
|
||||
# `:log info ("... count=" . [:tostr [:len [... find ...]]])`, liest man das
|
||||
# Ergebnis anschliessend per get_log zeilengenau aus — ohne Direkt-Write.
|
||||
32
routeros/tp5-etappe1-pause.rsc
Normal file
32
routeros/tp5-etappe1-pause.rsc
Normal file
@@ -0,0 +1,32 @@
|
||||
# TP5 Etappe 1 — PAUSE (User-Entscheid 2026-08-14).
|
||||
# Grund: erst die .41.x -> .20.x-Migration fertigstellen (Prometheus-Scrape-Ziele,
|
||||
# HA-pve-Integration). Daten, die davor gesammelt werden, gelten danach nicht mehr —
|
||||
# 76 % des Inter-VLAN-Verkehrs waren genau dieses Altlast-Rauschen.
|
||||
#
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device crs326-core \
|
||||
# --commands-file routeros/tp5-etappe1-pause.rsc --change-id TP5-Etappe1-Pause --deploy
|
||||
|
||||
# 1) Log-Regel stilllegen. Bleibt als Objekt stehen (Kommentar = Idempotenz-Schluessel),
|
||||
# das Wiederanschalten ist damit eine Zeile.
|
||||
:do { /ip firewall filter set [find comment="TP5: log-only, Vorstufe zum deny-by-default"] disabled=yes } on-error={ :log info "tp5p: disable hat geworfen" }
|
||||
|
||||
# 2) Memory-Logging zurueckbauen. Der Ausschluss war nur wegen der Flut noetig;
|
||||
# waehrend der Pause faellt keine an, und der On-Box-Log wird fuer die
|
||||
# Migrationsarbeit wieder gebraucht.
|
||||
:do { /system logging set [find topics~"info" and action=memory] topics=info } on-error={ :log info "tp5p: topics-restore hat geworfen" }
|
||||
|
||||
:log info ("tp5p: ENDE regel-disabled=" . [:tostr [/ip firewall filter get [find comment="TP5: log-only, Vorstufe zum deny-by-default"] disabled]] . " memory-topics=" . [:tostr [/system logging get [find topics~"info" and action=memory] topics]])
|
||||
|
||||
# ===========================================================================
|
||||
# WIEDERAUFNAHME (Etappe 1 fortsetzen)
|
||||
# ===========================================================================
|
||||
# Der Kollektor laeuft weiter (Container `tp5-syslog` auf dem Docker-LXC,
|
||||
# restart=unless-stopped, 10.40.20.18:514) und die Logging-Action `tp5syslog`
|
||||
# samt Regel `topics=firewall` bleibt auf dem Core stehen — beides ist ohne die
|
||||
# Filter-Regel wirkungslos. Zum Fortsetzen genuegen zwei Zeilen:
|
||||
#
|
||||
# /ip firewall filter set [find comment="TP5: log-only, Vorstufe zum deny-by-default"] disabled=no
|
||||
# /system logging set [find topics~"info" and action=memory] topics=info,!firewall
|
||||
#
|
||||
# Vorher aufraeumen, sonst mischt sich Altes unter die neue Sammelphase:
|
||||
# ssh root@10.40.20.100 'pct exec 400 -- sh -c ": > /opt/tp5-syslog/log/tp5-would-drop.log"'
|
||||
26
routeros/tp5-etappe1-resume.rsc
Normal file
26
routeros/tp5-etappe1-resume.rsc
Normal file
@@ -0,0 +1,26 @@
|
||||
# TP5 Etappe 1 — WIEDERAUFNAHME nach der Pause vom 2026-08-14.
|
||||
# Gegenstueck zu routeros/tp5-etappe1-pause.rsc.
|
||||
#
|
||||
# Der Grund fuer die Pause ist weg: die .41.x-Altlasten sind abgeraeumt
|
||||
# (HA -> 10.40.20.100, pve .41.100 entfernt, Core .41.211 entfernt,
|
||||
# Prometheus bereinigt, ioBroker korrigiert). Vorher waren 76 % des
|
||||
# Inter-VLAN-Verkehrs `vlan20 -> bridge`, also genau dieses Rauschen.
|
||||
#
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device crs326-core \
|
||||
# --commands-file routeros/tp5-etappe1-resume.rsc \
|
||||
# --change-id TP5-Etappe1-Resume --deploy
|
||||
# Backup davor: core-pre-tp5-resume-20260815.backup
|
||||
#
|
||||
# ABNAHME danach: `out:bridge` im Kollektor-Log muss auf 0 stehen.
|
||||
# Die Logdatei ist vor dem Scharfschalten geleert worden.
|
||||
|
||||
# 1) Log-Regel wieder scharf. Blockiert nichts: action=log ist nicht-terminierend,
|
||||
# und out-interface-list="!WAN" haelt den Internet-Verkehr draussen.
|
||||
:do { /ip firewall filter set [find comment="TP5: log-only, Vorstufe zum deny-by-default"] disabled=no } on-error={ :log info "tp5r: enable hat geworfen" }
|
||||
|
||||
# 2) firewall wieder aus dem Memory-Ring nehmen. Sonst besteht der 1000-Zeilen-Puffer
|
||||
# waehrend der Sammelphase zu 100 % aus TP5-Zeilen und der On-Box-Log ist fuer
|
||||
# jede andere Fehlersuche wertlos — genau dann, wenn man ihn braucht.
|
||||
:do { /system logging set [find topics~"info" and action=memory] topics=info,!firewall } on-error={ :log info "tp5r: topics hat geworfen" }
|
||||
|
||||
:log info ("tp5r: ENDE disabled=" . [:tostr [/ip firewall filter get [find comment="TP5: log-only, Vorstufe zum deny-by-default"] disabled]] . " memory-topics=" . [:tostr [/system logging get [find topics~"info" and action=memory] topics]])
|
||||
65
routeros/tp5-etappe2-nachtrag.rsc
Normal file
65
routeros/tp5-etappe2-nachtrag.rsc
Normal file
@@ -0,0 +1,65 @@
|
||||
# TP5 Etappe 2 — NACHTRAG. Vier Luecken, die der Kollektor nach dem ersten
|
||||
# Etappe-2-Deploy gezeigt hat, plus eine Vorratsregel.
|
||||
#
|
||||
# QUELLE: /opt/tp5-syslog/log/tp5-would-drop.log auf dem Docker-LXC,
|
||||
# Fenster 2026-08-17 15:00 .. 18:38 (nach dem E2-Deploy um 14:17:16).
|
||||
# 119 Zeilen, aggregiert:
|
||||
# 92 vlan30->vlan20 udp 10.40.30.227:5540 -> 10.40.20.105
|
||||
# 18 vlan20->vlan99 tcp 10.40.20.31 -> .99.2/.99.11/.99.12:22
|
||||
# 8 vlan99->vlan20 tcp .99.x:8728 -> 10.40.20.105
|
||||
# 1 vlan30->vlan20 tcp 10.40.30.225:80 -> 10.40.20.105
|
||||
#
|
||||
# Die Behauptung "die Log-Regel ist verstummt" stammte aus einem 70-Sekunden-
|
||||
# Fenster. Ueber dreieinhalb Stunden gemessen stimmt sie nicht. Das ist genau
|
||||
# der Grund, warum das Runbook ein mehrtaegiges Fenster verlangt.
|
||||
#
|
||||
# BLOCKIERT NICHTS: ausschliesslich action=accept.
|
||||
#
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device crs326-core \
|
||||
# --commands-file routeros/tp5-etappe2-nachtrag.rsc \
|
||||
# --change-id TP5-Etappe2-Nachtrag --deploy \
|
||||
# --assert '/ip/firewall/filter?comment=TP5-E2: IOT->INFRA Matter|count=1'
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# 1) MATTER. 92 der 119 Zeilen. 10.40.30.227 = SwitchBot-Stehlampe (DHCP-
|
||||
# Reservierung "SwitchBot-floor-lamp"), die per Matter ueber udp/5540 an HA
|
||||
# pusht. Die E2-Regel "IOT->INFRA Dienste" ist protocol=tcp — Matter faellt
|
||||
# komplett durch. Ohne diese Zeile toetet Etappe 3 die Matter-Anbindung.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: IOT->INFRA Matter"]] = 0) do={ /ip firewall filter add chain=forward action=accept in-interface=vlan30 out-interface=vlan20 protocol=udp dst-port=5540 comment="TP5-E2: IOT->INFRA Matter" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5n: 01 Matter warf" }
|
||||
|
||||
# 2) NAUTOBOT-DEPLOY-PFAD. Der Netmiko-Deploy kommt NICHT von 10.40.20.30
|
||||
# (Web-Container), sondern von 10.40.20.31 = nautobot-worker. Beleg: die
|
||||
# E2-Regel "Nautobot->MGMT ssh" auf .20.30 steht auf 0 Paketen, waehrend im
|
||||
# Log 18 SYNs von .20.31 auf .99.{2,11,12}:22 stehen.
|
||||
# Address-List statt Einzel-IP, weil der scheduler (.20.32) dieselben Jobs
|
||||
# faehrt und ein Stack-Redeploy die Rollen tauschen kann.
|
||||
# ⚠️ Ohne diese Zeile sperrt Etappe 3 den einzigen legitimen Config-Weg aus —
|
||||
# also genau das Werkzeug fuer den Rueckzieher.
|
||||
:do { :if ([:len [/ip firewall address-list find list=nautobot address=10.40.20.30]] = 0) do={ /ip firewall address-list add list=nautobot address=10.40.20.30 comment="nautobot web" } } on-error={ :log info "tp5n: 02a al-30 warf" }
|
||||
:do { :if ([:len [/ip firewall address-list find list=nautobot address=10.40.20.31]] = 0) do={ /ip firewall address-list add list=nautobot address=10.40.20.31 comment="nautobot worker = der Deploy-Pfad" } } on-error={ :log info "tp5n: 02b al-31 warf" }
|
||||
:do { :if ([:len [/ip firewall address-list find list=nautobot address=10.40.20.32]] = 0) do={ /ip firewall address-list add list=nautobot address=10.40.20.32 comment="nautobot scheduler" } } on-error={ :log info "tp5n: 02c al-32 warf" }
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: Nautobot->MGMT ssh (list)"]] = 0) do={ /ip firewall filter add chain=forward action=accept src-address-list=nautobot out-interface=vlan99 protocol=tcp dst-port=22 comment="TP5-E2: Nautobot->MGMT ssh (list)" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5n: 02d regel warf" }
|
||||
|
||||
# 3) RUECKRICHTUNG DES MGMT-PFADS. .99.x:8728 -> HA, als connection-state:new
|
||||
# im Log. Das sind Pakete einer TCP-Sitzung, deren Conntrack-Eintrag
|
||||
# abgelaufen ist, waehrend HA weiterpollt. Ein blanker Drop wuerde sie
|
||||
# verschlucken und die mikrotik-Integrationen ins Timeout laufen lassen.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: MGMT->INFRA api-rueckweg"]] = 0) do={ /ip firewall filter add chain=forward action=accept in-interface=vlan99 out-interface=vlan20 protocol=tcp src-port=8728 comment="TP5-E2: MGMT->INFRA api-rueckweg" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5n: 03 api-rueckweg warf" }
|
||||
|
||||
# 4) SHELLY-ANTWORT auf demselben Muster (tcp/80 -> HA, als new gesehen).
|
||||
# Nur 1 Zeile im Fenster, aber dieselbe Ursache wie 3 und bei 22 gepollten
|
||||
# Shellys jederzeit wieder faellig.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: IOT->INFRA http-rueckweg"]] = 0) do={ /ip firewall filter add chain=forward action=accept in-interface=vlan30 out-interface=vlan20 protocol=tcp src-port=80 comment="TP5-E2: IOT->INFRA http-rueckweg" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5n: 04 http-rueckweg warf" }
|
||||
|
||||
# 5) VORRATSREGEL DNS -> AdGuard (10.40.20.16).
|
||||
# AGH ist per Christophs Vorgabe eingerichtet, aber NICHT scharf geschaltet:
|
||||
# die DHCP-Scopes liefern weiter 10.40.X.1 aus. Diese Zeile aendert daran
|
||||
# nichts. Sie sorgt dafuer, dass das spaetere Umstellen ein reiner
|
||||
# DHCP-Change bleibt und die dann scharfe Firewall nicht angefasst werden
|
||||
# muss. Ohne sie waere die Reihenfolge eine Falle: DNS umgestellt, Drop
|
||||
# scharf, Haus ohne Namensaufloesung.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: LAN->AGH dns (Vorrat)"]] = 0) do={ /ip firewall filter add chain=forward action=accept dst-address=10.40.20.16 protocol=udp dst-port=53 comment="TP5-E2: LAN->AGH dns (Vorrat)" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5n: 05a dns-udp warf" }
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: LAN->AGH dns-tcp (Vorrat)"]] = 0) do={ /ip firewall filter add chain=forward action=accept dst-address=10.40.20.16 protocol=tcp dst-port=53 comment="TP5-E2: LAN->AGH dns-tcp (Vorrat)" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5n: 05b dns-tcp warf" }
|
||||
|
||||
# Zaehlzeile: 17 TP5-E2-Regeln erwartet (11 aus Etappe 2 + 6 hier).
|
||||
:log info ("tp5n: ENDE e2-regeln=" . [:tostr [:len [/ip firewall filter find comment~"TP5-E2:"]]] . " nautobot-liste=" . [:tostr [:len [/ip firewall address-list find list=nautobot]]])
|
||||
100
routeros/tp5-etappe2-whitelists.rsc
Normal file
100
routeros/tp5-etappe2-whitelists.rsc
Normal file
@@ -0,0 +1,100 @@
|
||||
# TP5 Etappe 2 — Whitelists auf crs326-core.
|
||||
#
|
||||
# Quelle: NICHT geraten, sondern aus 43.027 Zeilen Log-Lauf abgeleitet
|
||||
# (Kollektor 10.40.20.18, Fenster 2026-08-16T17:21 .. 2026-08-17T14:05).
|
||||
# Beobachtete Matrix (in -> out):
|
||||
# 20682 vlan20->vlan99 8082 vlan10->vlan20 7123 vlan20->vlan10
|
||||
# 6238 vlan20->vlan30 306 vlan30->vlan20 237 vlan10->vlan30
|
||||
# 214 vlan10->vlan99 17 vlan10->vlan10 2 vlan30->vlan10
|
||||
# 137 cf-mesh->{vlan20,vlan99}
|
||||
# vlan40/50/90: NULL Inter-VLAN -> Internet-only ist risikofrei (D6).
|
||||
#
|
||||
# Entscheidungen (User 2026-08-17):
|
||||
# D1 = MAIN->INFRA pauschal accept (MAIN ist das Trusted-VLAN, INFRA die
|
||||
# eigene Serverzone; Least-Privilege bleibt bei IOT/UNTRUSTED/GUEST/MGMT).
|
||||
# D4 = MGMT named sources: HA:8728 + Nautobot:22 + vlan10 + cf-mesh, Rest drop.
|
||||
# D5 = IOT->INFRA: beobachtet ist nur 8123; MQTT 1883/8883 als dokumentierte
|
||||
# Absicht mit aufgenommen (Shelly-Push kann jederzeit dazukommen).
|
||||
#
|
||||
# BLOCKIERT NICHTS: ausschliesslich action=accept. Der Drop kommt in Etappe 3.
|
||||
#
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device crs326-core \
|
||||
# --commands-file routeros/tp5-etappe2-whitelists.rsc \
|
||||
# --change-id TP5-Etappe2-Whitelists --deploy
|
||||
# Backup davor: core-pre-tp5-etappe2-20260817.backup
|
||||
#
|
||||
# ABNAHMEKRITERIUM: der Zaehler der Log-Regel muss danach (nahezu) stehen
|
||||
# bleiben. Solange sie Nutzverkehr sieht, ist die Whitelist unvollstaendig —
|
||||
# das ist das Gate fuer Etappe 3.
|
||||
#
|
||||
# ---------------------------------------------------------------------------
|
||||
# WICHTIG — place-before: alle Zeilen muessen VOR die Log-Regel. Sonst laeuft
|
||||
# die Log-Regel weiter voll und das Abnahmekriterium oben ist nicht messbar
|
||||
# (action=log ist nicht-terminierend, funktional waere es egal - messbar nicht).
|
||||
# Alle Adds sind per :if [:len [find comment=...]]=0 idempotent, ein zweiter
|
||||
# Lauf legt also nichts doppelt an. Jede Zeile eigenes on-error (Lehre aus
|
||||
# Etappe 1: ein gescheiterter Netmiko-Deploy hinterlaesst Teil-Zustand).
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# 1) LAN -> WAN. Ohne diese Zeile nimmt der spaetere Drop das ganze Haus vom
|
||||
# Netz, inklusive der "Internet-only"-VLANs 50/90. Bekannt, braucht keinen
|
||||
# Logbeleg, und aus demselben Grund stand schon die Log-Regel auf "!WAN".
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: LAN->WAN"]] = 0) do={ /ip firewall filter add chain=forward action=accept out-interface-list=WAN comment="TP5-E2: LAN->WAN" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e2: 01 LAN->WAN warf" }
|
||||
|
||||
# 2) Cloudflare Mesh (TP16.1/TP16.3). 137 Logtreffer belegen den Pfad.
|
||||
# Ohne diese beiden Zeilen sperrt der Drop den kompletten Fernzugang aus —
|
||||
# und zwar genau den, mit dem man den Fehler zuruecknehmen wollte.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: mesh->LAN"]] = 0) do={ /ip firewall filter add chain=forward action=accept in-interface=cf-mesh comment="TP5-E2: mesh->LAN" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e2: 02 mesh->LAN warf" }
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: LAN->mesh"]] = 0) do={ /ip firewall filter add chain=forward action=accept out-interface=cf-mesh comment="TP5-E2: LAN->mesh" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e2: 03 LAN->mesh warf" }
|
||||
|
||||
# 3) D1 — MAIN <-> INFRA pauschal. Beobachtet waren 13 Dienste (macmini
|
||||
# udp/3722 Continuity 6234x, NAS 6690 1578x, Nautobot 8080, AirPlay 7000,
|
||||
# pve-mcp 3000, ssh auf pve/NAS/macmini, Ollama 11434, ...). Die
|
||||
# Rueckrichtung braucht eine eigene Zeile, weil Continuity je Richtung
|
||||
# eigene Flows oeffnet (7123 "new" aus vlan20).
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: MAIN->INFRA"]] = 0) do={ /ip firewall filter add chain=forward action=accept in-interface=vlan10 out-interface=vlan20 comment="TP5-E2: MAIN->INFRA" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e2: 04 MAIN->INFRA warf" }
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: INFRA->MAIN"]] = 0) do={ /ip firewall filter add chain=forward action=accept in-interface=vlan20 out-interface=vlan10 comment="TP5-E2: INFRA->MAIN" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e2: 05 INFRA->MAIN warf" }
|
||||
|
||||
# 4) INFRA -> IOT. HA (10.40.20.105) pollt ~22 Shellys auf tcp/80, 6238 Zeilen.
|
||||
# Richtungsasymmetrisch gewollt: INFRA darf IOT anfassen, nicht umgekehrt.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: INFRA->IOT"]] = 0) do={ /ip firewall filter add chain=forward action=accept in-interface=vlan20 out-interface=vlan30 comment="TP5-E2: INFRA->IOT" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e2: 06 INFRA->IOT warf" }
|
||||
|
||||
# 5) D5 — IOT -> INFRA, nur Dienste. Beobachtet: 10.40.30.249 -> HA:8123 (203x).
|
||||
# MQTT mit drin, weil die Doku es als Absicht nennt und ein Shelly-Push
|
||||
# jederzeit dazukommen kann. Influx 8086 NICHT: nie beobachtet, und der
|
||||
# Weg dorthin laeuft ueber HA.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: IOT->INFRA Dienste"]] = 0) do={ /ip firewall filter add chain=forward action=accept in-interface=vlan30 out-interface=vlan20 protocol=tcp dst-port=8123,1883,8883 comment="TP5-E2: IOT->INFRA Dienste" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e2: 07 IOT->INFRA warf" }
|
||||
|
||||
# 6) D4 — MGMT (vlan99). Drei named sources, sonst nichts:
|
||||
# a) MAIN komplett = Arbeitsplatz (.10.82 -> ssh/80/443 auf branch/ap1/ap2)
|
||||
# b) HA .20.105:8728 = mikrotik-Integration, 20.667 Polls. Ohne diese Zeile
|
||||
# brechen die HA-Integrationen.
|
||||
# c) Nautobot .20.30:22 = Netmiko-Deploy der Golden Config. Ohne diese Zeile
|
||||
# sperrt sich TP22 selbst aus — der Weg, ueber den dieser Push laeuft.
|
||||
# cf-mesh ist bereits durch Zeile 2 gedeckt.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: MAIN->MGMT"]] = 0) do={ /ip firewall filter add chain=forward action=accept in-interface=vlan10 out-interface=vlan99 comment="TP5-E2: MAIN->MGMT" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e2: 08 MAIN->MGMT warf" }
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: HA->MGMT api"]] = 0) do={ /ip firewall filter add chain=forward action=accept src-address=10.40.20.105 out-interface=vlan99 protocol=tcp dst-port=8728 comment="TP5-E2: HA->MGMT api" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e2: 09 HA->MGMT warf" }
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: Nautobot->MGMT ssh"]] = 0) do={ /ip firewall filter add chain=forward action=accept src-address=10.40.20.30 out-interface=vlan99 protocol=tcp dst-port=22 comment="TP5-E2: Nautobot->MGMT ssh" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e2: 10 Nautobot->MGMT warf" }
|
||||
|
||||
# 7) Same-VLAN mDNS. vlan10 -> vlan10 udp/5353, erzeugt vom mDNS-Repeater auf
|
||||
# dem Core selbst (17 Zeilen). Erreicht die forward-Kette und wuerde von
|
||||
# einem blanken Drop getroffen -> Discovery INNERHALB von MAIN kaputt.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E2: same-VLAN mDNS"]] = 0) do={ /ip firewall filter add chain=forward action=accept in-interface=vlan10 out-interface=vlan10 protocol=udp dst-port=5353 comment="TP5-E2: same-VLAN mDNS" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e2: 11 same-VLAN mDNS warf" }
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# BEWUSST NICHT AUFGENOMMEN:
|
||||
#
|
||||
# vlan10 -> vlan30 (237x udp/3722) und vlan30 -> vlan10 (2x): das ist das
|
||||
# iPhone 10.40.30.201, das im IOT-SSID haengt. D2 ist entschieden — es wird
|
||||
# ins MAIN-SSID umgehaengt (Hands-on bei Christoph), dann verschwindet die
|
||||
# Richtung von selbst. Eine Whitelist auf .30.201 waere ausserdem instabil:
|
||||
# iOS vergibt pro SSID eine eigene Private Address.
|
||||
# => Vor Etappe 3 pruefen, ob die Zeilen aus dem Log verschwunden sind.
|
||||
#
|
||||
# MAIN -> IOT ICMP (lanscan.app, D3): keine Dauerregel. Gehoert in die
|
||||
# JIT-Admin-Gruppe (address-list mit timeout), Etappe 4.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Zaehlzeile: 11 Whitelist-Regeln erwartet. Per get_log zeilengenau auslesen —
|
||||
# der Deploy-Job zeigt den Geraete-Output nicht (Lehre aus Etappe 1).
|
||||
:log info ("tp5e2: ENDE whitelist-regeln=" . [:tostr [:len [/ip firewall filter find comment~"TP5-E2:"]]] . " logregel-disabled=" . [:tostr [/ip firewall filter get [find comment="TP5: log-only, Vorstufe zum deny-by-default"] disabled]])
|
||||
14
routeros/tp5-etappe3-autorevert-abbestellen.rsc
Normal file
14
routeros/tp5-etappe3-autorevert-abbestellen.rsc
Normal file
@@ -0,0 +1,14 @@
|
||||
# TP5 Etappe 3 — Auto-Revert abbestellen.
|
||||
#
|
||||
# Der Scheduler aus tp5-etappe3-drop.rsc haette den Drop nach 10 Minuten selbst
|
||||
# wieder abgeschaltet. Die Abnahme ist durch, also wird er entfernt und der
|
||||
# Drop bleibt stehen. Abnahme am 2026-08-18 (Drop live):
|
||||
# INFRA->IOT Shelly .30.211:80 = 200
|
||||
# INFRA->WAN cloudflare.com = 301
|
||||
# INFRA->MAIN MacBook = erreichbar
|
||||
# INFRA->MGMT branch:22 von pve = ZU (korrekt: pve ist keine Mgmt-Quelle)
|
||||
# GC-Deploy nautobot-worker -> ap2:22 = SUCCESS (der Pfadbeweis)
|
||||
# Gedroppt wurden in der Testphase 11 Pakete — ausschliesslich die eigene
|
||||
# pve->branch:22-Sonde.
|
||||
:do { /system scheduler remove [find name="tp5autorevert"] } on-error={ :log info "tp5e3: abbestellen warf" }
|
||||
:log info ("tp5e3: AUTO-REVERT entfernt, drop-disabled=" . [:tostr [/ip firewall filter get [find comment="TP5: deny-by-default"] disabled]])
|
||||
44
routeros/tp5-etappe3-drop.rsc
Normal file
44
routeros/tp5-etappe3-drop.rsc
Normal file
@@ -0,0 +1,44 @@
|
||||
# TP5 Etappe 3 — Deny-by-default am Ende von forward.
|
||||
#
|
||||
# WAS HIER PASSIERT
|
||||
# -----------------
|
||||
# Die forward-Kette endet heute nach der Log-Regel ohne Drop: alles, was keine
|
||||
# Whitelist trifft, laeuft trotzdem durch. Diese Datei schliesst genau das.
|
||||
# Der Drop kommt HINTER die Log-Regel, nicht an ihre Stelle — dann protokolliert
|
||||
# der Kollektor weiter exakt das, was der Drop frisst. Ohne diese Sicht waere
|
||||
# jede spaetere Fehlersuche Raten.
|
||||
#
|
||||
# VORBEDINGUNGEN, die am 2026-08-18 erfuellt sind:
|
||||
# - 17 Whitelist-Regeln (11 aus Etappe 2 + 6 aus dem Nachtrag) stehen VOR der
|
||||
# Log-Regel; Positionen 14..30, Log auf 31, live gegengeprueft.
|
||||
# - Der Nachtrag hat die vier Luecken geschlossen, die der Kollektor nach dem
|
||||
# ersten E2-Deploy gezeigt hat (Matter, nautobot-worker .20.31, die beiden
|
||||
# Rueckwege). Ohne sie haette dieser Drop den GC-Deploy-Pfad selbst gekappt.
|
||||
#
|
||||
# ⚠️ REIHENFOLGE IM SKRIPT IST ABSICHT: erst der Auto-Revert-Scheduler, DANN der
|
||||
# Drop. Andersherum gibt es ein Fenster, in dem der Drop scharf ist und die
|
||||
# Sicherung noch nicht steht.
|
||||
#
|
||||
# 🛟 AUTO-REVERT: schaltet den Drop nach 10 Minuten selbst wieder ab und entfernt
|
||||
# sich. Wer zufrieden ist, loescht den Scheduler von Hand — dann bleibt der Drop.
|
||||
# Name OHNE Bindestrich: RouterOS lehnt "tp5-autorevert" ab (bekannte Falle,
|
||||
# hat schon vier Deploys gekostet).
|
||||
#
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device crs326-core \
|
||||
# --commands-file routeros/tp5-etappe3-drop.rsc \
|
||||
# --change-id TP5-Etappe3-Drop --deploy
|
||||
# Backup davor: core-pre-tp5-etappe3-20260818.backup
|
||||
#
|
||||
# Rollback sofort: /ip firewall filter set [find comment="TP5: deny-by-default"] disabled=yes
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# 1) Sicherung zuerst.
|
||||
:do { :if ([:len [/system scheduler find name="tp5autorevert"]] = 0) do={ /system scheduler add name="tp5autorevert" interval=10m on-event="/ip firewall filter set [find comment=\"TP5: deny-by-default\"] disabled=yes; /system scheduler remove [find name=\"tp5autorevert\"]; :log warning \"tp5e3: AUTO-REVERT hat den Drop abgeschaltet\"" } } on-error={ :log info "tp5e3: 01 scheduler warf" }
|
||||
|
||||
# 2) Der Drop. Hinter die Log-Regel, damit der Kollektor weiterlaeuft.
|
||||
# KEIN place-before: ein add haengt ans Kettenende an, und dort steht die
|
||||
# Log-Regel bereits als letzte. Ein place-before auf die Log-Regel wuerde den
|
||||
# Drop DAVOR setzen -- dann sieht der Kollektor nie wieder, was gedroppt wird.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5: deny-by-default"]] = 0) do={ /ip firewall filter add chain=forward action=drop comment="TP5: deny-by-default" } } on-error={ :log info "tp5e3: 02 drop warf" }
|
||||
|
||||
:log info ("tp5e3: ENDE drop=" . [:tostr [:len [/ip firewall filter find comment="TP5: deny-by-default"]]] . " autorevert=" . [:tostr [:len [/system scheduler find name="tp5autorevert"]]])
|
||||
13
routeros/tp5-etappe4-autorevert-abbestellen.rsc
Normal file
13
routeros/tp5-etappe4-autorevert-abbestellen.rsc
Normal file
@@ -0,0 +1,13 @@
|
||||
# TP5 Etappe 4 — Auto-Revert abbestellen. Abnahme 2026-08-18 (input-Drop live):
|
||||
# DNS aus VLAN20 an den Core core.bf.lan -> 10.40.99.1, heise.de -> 193.99.144.80
|
||||
# AGH unveraendert nas.bf.lan -> 10.40.20.10
|
||||
# MAIN->core admin 57 Pakete (MikroMCP/SSH laufen weiter)
|
||||
# HA->core api 3 Pakete
|
||||
# Die 5 mDNS-input-Regeln erstmals scharf: vlan30=87, vlan20=13 Pakete
|
||||
# (standen seit dem Bau am 2026-08-14 auf 0)
|
||||
# CAPsMAN ap1 + ap2 state=Ok
|
||||
# Gedroppt wurde ausschliesslich Broadcast-Rauschen, fuer das der Core nie
|
||||
# zustaendig war: MNDP (inzwischen explizit erlaubt), NetBIOS 137/138 aus
|
||||
# VLAN20, SSDP-Announcements einer Sonos aus VLAN40.
|
||||
:do { /system scheduler remove [find name="tp5e4autorevert"] } on-error={ :log info "tp5e4: abbestellen warf" }
|
||||
:log info ("tp5e4: AUTO-REVERT entfernt, input-drop-disabled=" . [:tostr [/ip firewall filter get [find comment="TP5: input deny-by-default"] disabled]] . " seal-lan-disabled=" . [:tostr [/ip firewall filter get [find comment="TP10-seal-lan"] disabled]])
|
||||
77
routeros/tp5-etappe4-input-mgmt.rsc
Normal file
77
routeros/tp5-etappe4-input-mgmt.rsc
Normal file
@@ -0,0 +1,77 @@
|
||||
# TP5 Etappe 4 — input-Kette haerten, MGMT isolieren, JIT-Admin-Gruppe.
|
||||
#
|
||||
# WARUM DAS DER RISKANTERE TEIL IST (riskanter als der Drop in forward)
|
||||
# --------------------------------------------------------------------
|
||||
# Der Core ist DNS- UND DHCP-Server fuer alle sieben VLANs. Beides ist
|
||||
# input-Verkehr und wird heute allein von `TP10-seal-lan`
|
||||
# (in-interface-list=LAN, accept) durchgewunken. Wer seal-lan naiv auf vlan10
|
||||
# verengt, nimmt in derselben Sekunde jedem anderen VLAN DHCP und DNS.
|
||||
# Deshalb strikt: erst die Ersatzregeln, dann seal-lan abschalten, dann Drop.
|
||||
#
|
||||
# GEPRUEFTE VORAUSSETZUNGEN (2026-08-18, live am Geraet):
|
||||
# - /system ntp server = enabled:no -> die Clients nutzen den Core NICHT als
|
||||
# Zeitquelle, es braucht also KEINE udp/123-Regel.
|
||||
# - /ip service ist bereits auf 10.40.0.0/16 + 100.96.0.0/12 eingegrenzt;
|
||||
# diese Kette ist die zweite, grobkoernigere Schranke davor.
|
||||
# - Die 5 `TP5: mDNS in vlanXX`-Regeln stehen hinter seal-lan und zaehlen
|
||||
# deshalb 0. Sobald seal-lan faellt, werden sie scharf — das ist Absicht
|
||||
# und war beim Bau 2026-08-14 schon so vorgesehen.
|
||||
#
|
||||
# ⚠️ Wie in Etappe 3 gilt: erst Sicherung, dann Schnitt. Und die Log-Regel steht
|
||||
# VOR dem Drop, damit der Kollektor zeigt, was der Drop frisst.
|
||||
#
|
||||
# Push: python3 nautobot/gc-manual-plan.py --device crs326-core \
|
||||
# --commands-file routeros/tp5-etappe4-input-mgmt.rsc \
|
||||
# --change-id TP5-Etappe4-Input --deploy
|
||||
# Backup davor: core-pre-tp5-etappe4-20260818.backup
|
||||
#
|
||||
# Rollback sofort: /ip firewall filter set [find comment="TP10-seal-lan"] disabled=no
|
||||
# /ip firewall filter set [find comment="TP5: input deny-by-default"] disabled=yes
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# 0) Sicherung zuerst — schaltet BEIDE Schnitte zurueck, nicht nur einen.
|
||||
:do { :if ([:len [/system scheduler find name="tp5e4autorevert"]] = 0) do={ /system scheduler add name="tp5e4autorevert" interval=10m on-event="/ip firewall filter set [find comment=\"TP5: input deny-by-default\"] disabled=yes; /ip firewall filter set [find comment=\"TP10-seal-lan\"] disabled=no; /system scheduler remove [find name=\"tp5e4autorevert\"]; :log warning \"tp5e4: AUTO-REVERT hat input-Drop und seal-lan zurueckgesetzt\"" } } on-error={ :log info "tp5e4: 00 scheduler warf" }
|
||||
|
||||
# 1) DNS. Der Core ist Resolver fuer jedes VLAN (dhcp-server network liefert
|
||||
# ueberall 10.40.X.1 aus). Ohne diese zwei Zeilen ist nach dem Drop das
|
||||
# ganze Haus ohne Namensaufloesung.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E4: dns udp"]] = 0) do={ /ip firewall filter add chain=input action=accept in-interface-list=LAN protocol=udp dst-port=53 comment="TP5-E4: dns udp" place-before=[/ip firewall filter find comment="TP10-seal-lan"] } } on-error={ :log info "tp5e4: 01a dns-udp warf" }
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E4: dns tcp"]] = 0) do={ /ip firewall filter add chain=input action=accept in-interface-list=LAN protocol=tcp dst-port=53 comment="TP5-E4: dns tcp" place-before=[/ip firewall filter find comment="TP10-seal-lan"] } } on-error={ :log info "tp5e4: 01b dns-tcp warf" }
|
||||
|
||||
# 2) DHCP. 7 Server, 54 Reservierungen — alle haengen an udp/67 auf dem Core.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E4: dhcp"]] = 0) do={ /ip firewall filter add chain=input action=accept in-interface-list=LAN protocol=udp dst-port=67 comment="TP5-E4: dhcp" place-before=[/ip firewall filter find comment="TP10-seal-lan"] } } on-error={ :log info "tp5e4: 02 dhcp warf" }
|
||||
|
||||
# 3) MAIN = die Admin-Zone. Das ist das verengte seal-lan: ssh/www/winbox/api
|
||||
# kommen ab jetzt nur noch aus vlan10 (plus Mesh, s. 6).
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E4: MAIN->core admin"]] = 0) do={ /ip firewall filter add chain=input action=accept in-interface=vlan10 comment="TP5-E4: MAIN->core admin" place-before=[/ip firewall filter find comment="TP10-seal-lan"] } } on-error={ :log info "tp5e4: 03 main warf" }
|
||||
|
||||
# 4) HA pollt den Core selbst auf 8728. Live belegt: /ip service zeigt offene
|
||||
# api-Verbindungen local=10.40.99.1 remote=10.40.20.105. Das ist input, nicht
|
||||
# forward — die forward-Regel aus Etappe 2 deckt es NICHT ab.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E4: HA->core api"]] = 0) do={ /ip firewall filter add chain=input action=accept src-address=10.40.20.105 protocol=tcp dst-port=8728 comment="TP5-E4: HA->core api" place-before=[/ip firewall filter find comment="TP10-seal-lan"] } } on-error={ :log info "tp5e4: 04 ha warf" }
|
||||
|
||||
# 5) Nautobot deployt auch auf den Core selbst -> ssh als input. Address-List
|
||||
# aus dem Etappe-2-Nachtrag (.20.30/.31/.32).
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E4: Nautobot->core ssh"]] = 0) do={ /ip firewall filter add chain=input action=accept src-address-list=nautobot protocol=tcp dst-port=22 comment="TP5-E4: Nautobot->core ssh" place-before=[/ip firewall filter find comment="TP10-seal-lan"] } } on-error={ :log info "tp5e4: 05 nautobot warf" }
|
||||
|
||||
# 6) Der Fernzugang. Ohne diese Zeile sperrt der input-Drop den Mesh aus — also
|
||||
# genau den Weg, ueber den man von auswaerts korrigieren wuerde.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E4: mesh->core admin"]] = 0) do={ /ip firewall filter add chain=input action=accept in-interface=cf-mesh comment="TP5-E4: mesh->core admin" place-before=[/ip firewall filter find comment="TP10-seal-lan"] } } on-error={ :log info "tp5e4: 06 mesh warf" }
|
||||
|
||||
# 7) Jetzt erst der Schnitt: seal-lan ausschalten (nicht loeschen — disabled ist
|
||||
# der schnellere Rueckweg und der Auto-Revert greift genau hier an).
|
||||
:do { /ip firewall filter set [find comment="TP10-seal-lan"] disabled=yes } on-error={ :log info "tp5e4: 07 seal-lan warf" }
|
||||
|
||||
# 8) Log VOR Drop, gleiche Doktrin wie in forward: der Kollektor zeigt weiter,
|
||||
# was der Drop frisst. Ohne diese Zeile ist jede spaetere Fehlersuche Raten.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5: input log-only"]] = 0) do={ /ip firewall filter add chain=input action=log log-prefix="TP5-INPUT-WOULD-DROP" comment="TP5: input log-only" } } on-error={ :log info "tp5e4: 08 log warf" }
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5: input deny-by-default"]] = 0) do={ /ip firewall filter add chain=input action=drop comment="TP5: input deny-by-default" } } on-error={ :log info "tp5e4: 09 drop warf" }
|
||||
|
||||
# 9) JIT-Admin-Gruppe (D3 aus dem Runbook). Dauerregel, LEERE Liste: solange
|
||||
# niemand drinsteht, oeffnet sie nichts. Wer scannen oder ein IoT-Geraet
|
||||
# anlernen will, traegt sich selbst mit timeout ein:
|
||||
# /ip firewall address-list add list=jit-admin address=10.40.10.183 timeout=1h
|
||||
# Das ersetzt die Dauerregel MAIN->IOT, die lanscan.app sonst braeuchte.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E4: JIT-Admin aus MAIN"]] = 0) do={ /ip firewall filter add chain=forward action=accept in-interface=vlan10 src-address-list=jit-admin comment="TP5-E4: JIT-Admin aus MAIN" place-before=[/ip firewall filter find comment="TP5: log-only, Vorstufe zum deny-by-default"] } } on-error={ :log info "tp5e4: 10 jit warf" }
|
||||
|
||||
:log info ("tp5e4: ENDE input-regeln=" . [:tostr [:len [/ip firewall filter find chain=input]]] . " seal-lan-disabled=" . [:tostr [/ip firewall filter get [find comment="TP10-seal-lan"] disabled]] . " input-drop=" . [:tostr [:len [/ip firewall filter find comment="TP5: input deny-by-default"]]] . " jit=" . [:tostr [:len [/ip firewall filter find comment="TP5-E4: JIT-Admin aus MAIN"]]])
|
||||
32
routeros/tp5-etappe4-nachtrag-discovery.rsc
Normal file
32
routeros/tp5-etappe4-nachtrag-discovery.rsc
Normal file
@@ -0,0 +1,32 @@
|
||||
# TP5 Etappe 4 — NACHTRAG: Discovery-Protokolle in den input lassen.
|
||||
#
|
||||
# BEFUND (2026-08-18, unmittelbar nach dem input-Drop):
|
||||
# Die input-Log-Regel fing MNDP-Broadcasts (udp/5678) von crs326-branch
|
||||
# (04:F4:1C:B4:15:58), ap1 (D0:EA:11:4D:40:E0/E1) und ap2 (D0:EA:11:4D:40:39/3A).
|
||||
#
|
||||
# WARUM DAS NICHT HARMLOS IST:
|
||||
# `/interface/wifi/cap` auf ap1 zeigt
|
||||
# discovery-interfaces: vlan99
|
||||
# current-caps-man-address: 04:F4:1C:B4:17:76%vlan99
|
||||
# — eine MAC, keine IP. Die CAPs finden ihren Manager also per Layer-2-Discovery
|
||||
# auf vlan99, nicht ueber eine konfigurierte Adresse. Ein Drop dieser Pakete
|
||||
# bricht die Manager-Findung. Die BESTEHENDEN CAPWAP-Sitzungen laufen weiter
|
||||
# (sie sind established und werden von TP10-seal-est akzeptiert), das Problem
|
||||
# schlaegt also erst beim naechsten AP- oder Manager-Neustart zu — genau die
|
||||
# Sorte Spaetschaden, die man im Log sehen und sofort schliessen will.
|
||||
#
|
||||
# Sicherheitlich billig: MNDP ist link-lokal (Broadcast, verlaesst das Segment
|
||||
# nicht), CAPWAP wird auf vlan99 begrenzt.
|
||||
#
|
||||
# ⚠️ place-before ist Pflicht: ein blankes `add` haengt hinter den Drop und
|
||||
# waere wirkungslos.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# MNDP. Aus der LAN-Liste, weil es auch die Winbox-Neighbors-Anzeige speist und
|
||||
# als Broadcast ohnehin nicht routbar ist.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E4: MNDP discovery"]] = 0) do={ /ip firewall filter add chain=input action=accept in-interface-list=LAN protocol=udp dst-port=5678 comment="TP5-E4: MNDP discovery" place-before=[/ip firewall filter find comment="TP5: input log-only"] } } on-error={ :log info "tp5e4n: 01 mndp warf" }
|
||||
|
||||
# CAPsMAN/CAPWAP, eng auf das Mgmt-VLAN begrenzt.
|
||||
:do { :if ([:len [/ip firewall filter find comment="TP5-E4: CAPsMAN capwap"]] = 0) do={ /ip firewall filter add chain=input action=accept in-interface=vlan99 protocol=udp dst-port=5246,5247 comment="TP5-E4: CAPsMAN capwap" place-before=[/ip firewall filter find comment="TP5: input log-only"] } } on-error={ :log info "tp5e4n: 02 capwap warf" }
|
||||
|
||||
:log info ("tp5e4n: ENDE mndp=" . [:tostr [:len [/ip firewall filter find comment="TP5-E4: MNDP discovery"]]] . " capwap=" . [:tostr [:len [/ip firewall filter find comment="TP5-E4: CAPsMAN capwap"]]])
|
||||
19
routeros/tp7.1-core-ether13-trunk.rsc
Normal file
19
routeros/tp7.1-core-ether13-trunk.rsc
Normal file
@@ -0,0 +1,19 @@
|
||||
# TP7.1 — core ether13 (pve) um VLAN10 + VLAN40 erweitern.
|
||||
#
|
||||
# WOFUER: der SSDP-Relay fuer die macOS-Sonos-App braucht ein Bein in BEIDEN
|
||||
# VLANs. SSDP ist link-lokales Multicast mit TTL 1: der M-SEARCH des MacBooks
|
||||
# verlaesst VLAN10 nie, die ssdp:alive-NOTIFYs der Sonos verlassen VLAN40 nie.
|
||||
# Ein Relay kann nur kopieren, was es selbst hoert — Routing hilft nicht, und
|
||||
# `forward accept vlan10<->vlan40` ist laengst offen. Es scheitert VOR dem
|
||||
# Verbindungsaufbau, an der Entdeckung.
|
||||
#
|
||||
# IST-STAND (live 2026-08-18): pve haengt an ether13, das nur `tagged vlan20`
|
||||
# traegt (pvid=1). Tags hinzuzufuegen stoert VLAN20 nicht.
|
||||
#
|
||||
# ⚠️ tagged= wird VOLLSTAENDIG gesetzt, nicht angehaengt — die bestehenden
|
||||
# Mitglieder ether1,ether8,ether15 stehen deshalb explizit mit drin. Ein
|
||||
# `set tagged=ether13` allein wuerde die anderen entfernen und AP1 sowie den
|
||||
# branch-Uplink aus dem VLAN werfen.
|
||||
:do { /interface bridge vlan set [find vlan-ids=10 and !dynamic] tagged=ether1,ether8,ether13,ether15 } on-error={ :log info "tp71: vlan10 warf" }
|
||||
:do { /interface bridge vlan set [find vlan-ids=40 and !dynamic] tagged=ether1,ether8,ether13,ether15 } on-error={ :log info "tp71: vlan40 warf" }
|
||||
:log info ("tp71: ENDE v10-tagged=" . [:tostr [/interface bridge vlan get [find vlan-ids=10 and !dynamic] tagged]] . " v40-tagged=" . [:tostr [/interface bridge vlan get [find vlan-ids=40 and !dynamic] tagged]])
|
||||
119
routeros/wan-cutover-runbook.md
Normal file
119
routeros/wan-cutover-runbook.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# WAN-Cutover Runbook + Tutorial (ap1 / Liwest FB-Passthrough)
|
||||
|
||||
> ## 🟢 UPDATE 2026-06-25: jetzt der PERMANENTE Cutover (TP10 gekoppelt)
|
||||
> Die Tunnel-Sperre ist gelöst: TP10 ist **cutover-ready**. Der permanente Ablauf (FM-FB → ap1-Apply → Passthrough →
|
||||
> DDNS → Verify → alte Tunnel abbauen) steht in `docs/tp10-vpn-migration.md` + den Klick-Anleitungen
|
||||
> `routeros/fritzbox-bf-bridge-cutover-klickanleitung.md` (BF-FB) und `routeros/fritzbox-wg-lanlan-klickanleitung.md` (FM-FB).
|
||||
> ap1-Apply = **`routeros/tp10-cutover-apply.rsc`**. Das Folgende bleibt als **Test-/Diagnose- und Rollback-Referenz** gültig
|
||||
> (Verkabelung, Konsolenpfad, `wantest-*`/`wanmac-*`, Sicherheitsnetze — alles weiterhin korrekt).
|
||||
|
||||
> ## ⚠️ Ursprünglich: REVERSIBLER TEST — die Reversibilität gilt weiter bis zum Tunnel-Teardown
|
||||
> Die FritzBox bleibt **produktiver Router + VPN-Endpunkt + Telefon**. Wir testen nur, ob der
|
||||
> Bridge/Passthrough-Mode sauber funktioniert, sammeln Diagnose-Daten und **bauen danach zurück**.
|
||||
> **Grund:** Die BF-FritzBox terminiert aktuell **2 Site-to-Site-Tunnel** (AVM LAN-LAN: 1× IPsec +
|
||||
> 1× WireGuard). Voller Bridge-Mode macht die FB zum reinen Modem → **die Tunnel sterben**. Permanenter
|
||||
> Umstieg erst, wenn **TP10** diese Tunnel auf ap1 migriert hat (Ziel: 2× WireGuard, Hub auf ap1).
|
||||
|
||||
---
|
||||
|
||||
## Was ist `wantest-run`?
|
||||
Ein **blockierendes Loop-Script auf ap1**, das 24×@15s (~6 min) die schichtweise WAN-Probe wiederholt
|
||||
und persistent nach `wan-test.0.txt` loggt. Es ist der **autonome Mitschnitt**, der weiterläuft, während
|
||||
Claude/MikroMCP während des Cutovers offline ist (kein Scheduler — device-mode blockt den; siehe unten).
|
||||
Jede Probe misst: ether1-IP/Status, Default-Gateway, WAN-Erreichbarkeit (`:resolve`@1.1.1.1 = Routing+NAT
|
||||
ohne DNS-Abhängigkeit) und DoH-Auflösung (= was die Clients als DNS nutzen).
|
||||
|
||||
---
|
||||
|
||||
## Verkabelung — was wohin (ap1 hAP ax²)
|
||||
|
||||
```
|
||||
┌─────────────────────── ap1 (hAP ax²) ───────────────────────┐
|
||||
Liwest ─ FritzBox ──────┤ ether1 = WAN ◀── HIER umstecken (an FB-Passthrough-Port) │
|
||||
(Kabel) .254 │ ether2 = LAN-Trunk ◀── Uplink zu ALLNET — NIEMALS ZIEHEN! │
|
||||
│ │ ether3/4/5 = frei │
|
||||
│ └──────────────────────────────────────────────────────────────┘
|
||||
│ (FB bleibt Router/DHCP/VPN/Telefon — flaches 10.40.41.0/24)
|
||||
└─ FB-WiFi ─ dein Laptop ◀── Console-Pfad: erreicht ap1 auf 10.40.41.1
|
||||
```
|
||||
|
||||
- **ether2 (LAN-Trunk → ALLNET):** der Management-/Uplink-Pfad. Läuft NICHT über ether1/FB-LAN4 →
|
||||
übersteht den Cutover. **Auf keinen Fall ziehen** (sonst sind ap1 UND du vom Netz).
|
||||
- **ether1 (WAN → FB):** der einzige Port, der in diesem Test umgesteckt wird.
|
||||
|
||||
## WiFi / Netz — welches wofür
|
||||
|
||||
| Zweck | Verbinde mit | Du landest in | ap1 erreichst du auf |
|
||||
|---|---|---|---|
|
||||
| **Console während Cutover** | **FritzBox-eigenes WiFi** | flach 10.40.41.0/24 | **`10.40.41.1`** (WebFig → New Terminal) |
|
||||
| **DHCP-Funktionstest** | `install-10` … `install-99` (ap1-Radios, PW `jgp4ap3cwcnz`) | VLAN = SSID-Nummer, z.B. `install-10` → 10.40.10.x | Gateway `10.40.<vlan>.1`, Lease `.100–.200` |
|
||||
|
||||
> Die FB-WiFi-Console (10.40.41.1 via ether2) ist bewusst der Steuer-Pfad: unabhängig von ether1/LAN4,
|
||||
> bleibt also stehen, egal was am WAN passiert.
|
||||
|
||||
---
|
||||
|
||||
## Schritt-für-Schritt
|
||||
|
||||
### 0 — Vorbereitung
|
||||
- FB-WAN-MAC notiert: **`0C:72:74:36:90:99`** (CM-MAC, schon als Default im Clone-Script hinterlegt).
|
||||
- Mit **FritzBox-WiFi** verbinden → WebFig `http://10.40.41.1` → **New Terminal**.
|
||||
- Scripts sind installiert: `wantest-probe`, `wantest-run`, `wanmac-clone`, `wanmac-revert`.
|
||||
|
||||
### 1 — Auto-Capture starten (Terminal auf 10.40.41.1)
|
||||
```
|
||||
:global WTN 40 # optional: 40 Proben (~10 min). Ohne = Default 24 (~6 min)
|
||||
/system script run wantest-run
|
||||
```
|
||||
→ läuft im Hintergrund weiter, auch wenn die Session abreißt. (Das Terminal blockiert während des Laufs —
|
||||
einfach ein zweites WebFig-Fenster für den Log öffnen.)
|
||||
|
||||
### 2 — FritzBox umstellen + ether1 umstecken
|
||||
- FB-UI → LAN4 auf Passthrough/IP-Client (FB-Klickanleitung aus dem Chat / `docs/`).
|
||||
- **ether1** von ap1 an den FB-Passthrough-Port. **ether2 bleibt stecken!**
|
||||
|
||||
### 3 — Live mitlesen (zweites WebFig-Fenster)
|
||||
```
|
||||
/log print where message~"WANTEST"
|
||||
```
|
||||
Interpretation:
|
||||
- `ether1 ... addr=86.x.x.x` → externe Liwest-IP gezogen ✓ (Bridge greift)
|
||||
- `wan-reach via-1.1.1.1 ok ...` → **Routing+NAT ok** (ohne DNS). `FAIL` → WAN-Routing kaputt.
|
||||
- `dns-doh ok ...` → DoH-Auflösung ok. `FAIL` → DNS/DoH kaputt = „nach .1 nichts" per Name.
|
||||
|
||||
### 4 — (optional) MAC-Clone testen, ~90 s, selbst-revertierend
|
||||
```
|
||||
/system script run wanmac-clone
|
||||
```
|
||||
→ setzt CM-MAC, release/renew, 4 Proben, dann **garantierter Auto-Revert** auf Werks-MAC.
|
||||
Not-Revert sofort: `/system script run wanmac-revert`.
|
||||
|
||||
### 5 — ZURÜCKBAUEN (Pflicht — Test-Ende)
|
||||
- FB-LAN4 wieder auf normal (Passthrough aus) → FB ist wieder voller Router.
|
||||
- **ether1** zurück an den ursprünglichen FB-LAN-Port (Double-NAT-Zustand wie vorher).
|
||||
- Damit laufen FB-VPN-Tunnel + Telefon ungestört weiter.
|
||||
- `wantest-run` endet von selbst („WANTEST run done"). Früher stoppen:
|
||||
`/system script job print` → `/system script job remove [find script=wantest-run]`.
|
||||
|
||||
### 6 — Auswerten
|
||||
Claude wieder online holen → liest `wan-test.0.txt` → bestimmt Root-Cause für „nach .1 ging nichts mehr"
|
||||
(Arbeitshypothese: DoH-Bootstrap, weil im Passthrough die FB als `dynamic-servers` wegfällt).
|
||||
|
||||
---
|
||||
|
||||
## Sicherheitsnetze (eingebaut)
|
||||
- **Fallback-Route:** statische Default-Route via bridge (distance=2) bleibt — fällt ether1 aus, geht
|
||||
Internet automatisch wieder über die FB (Double-NAT). Kein Totalausfall.
|
||||
- **MAC-Auto-Revert:** im Clone-Lauf fest eingebaut (~90 s), läuft im Hintergrund garantiert zu Ende.
|
||||
- **Console bleibt:** FB-WiFi → 10.40.41.1 via ether2 ist vom Cutover unabhängig.
|
||||
|
||||
## Notfall
|
||||
- ether1 zieht keine externe IP / kein Internet: `/system script run wanmac-revert`, dann FB-LAN4 zurück
|
||||
auf normal — Fallback-Route hält das LAN online.
|
||||
- ap1 nicht erreichbar: ether2-Kabel prüfen (Uplink zu ALLNET), NICHT ether1.
|
||||
- Hängendes Script killen: `/system script job print` → `/system script job remove <id>`.
|
||||
|
||||
## Hintergrund-Gotchas (ap1, RouterOS 7.23, device-mode=home)
|
||||
- **scheduler + fetch blockiert** → Mechanismus ist bewusst scheduler-frei (Loop-Script).
|
||||
- **`[/ping]` gibt nil zurück** und ICMP ist hier geblockt → Reachability via `:resolve`, nie ping.
|
||||
- Quelle der Scripts: `routeros/wan-cutover-test.rsc`, `routeros/wan-macclone-test.rsc`.
|
||||
58
routeros/wan-cutover-test.rsc
Normal file
58
routeros/wan-cutover-test.rsc
Normal file
@@ -0,0 +1,58 @@
|
||||
# ===== ap1 — Offline-fähiger WAN-Cutover-Test (scheduler-frei) =====
|
||||
# RouterOS 7.23.x, device-mode=home. Schichtweise Diagnose für FB-Bridge/Passthrough-Cutover.
|
||||
#
|
||||
# ⚠️ device-mode blockiert /system scheduler (scheduler=false) UND /tool fetch (fetch=false).
|
||||
# Daher: KEINE Scheduler — Autonomie via blockierendem Loop-Script (läuft im Hintergrund
|
||||
# weiter, auch wenn die Console-Session abreißt). Raw-Internet-Test via :resolve gegen feste
|
||||
# IP (ICMP/fetch sind hier unbrauchbar/geblockt).
|
||||
#
|
||||
# Apply: per REST/MikroMCP ODER /import wan-cutover-test.rsc
|
||||
# Lesen: /log print where message~"WANTEST" bzw. Datei wan-test.0.txt (persistent)
|
||||
# Einzel: /system script run wantest-probe
|
||||
# Lauf: /system script run wantest-run (24 Proben @15s = ~6 min; Hintergrund-fähig)
|
||||
# vorher optional: :global WTN 40 (mehr Iterationen)
|
||||
# Stop: /system script job print → /system script job remove [find script=wantest-run]
|
||||
|
||||
# --- idempotent: alte Versionen entfernen ---
|
||||
/system scheduler remove [find name~"^wantest-"]
|
||||
/system script remove [find name~"^wantest-"]
|
||||
/system logging remove [find action="wantest"]
|
||||
/system logging action remove [find name="wantest"]
|
||||
|
||||
# --- persistentes Logging auf Disk (überlebt Offline-Fenster + Reboot) ---
|
||||
# topics=script greift NUR auf script-generierte :log-Zeilen → genau unsere WANTEST-Zeilen
|
||||
/system logging action add name=wantest target=disk disk-file-name=wan-test disk-lines-per-file=2000
|
||||
/system logging add topics=script action=wantest
|
||||
|
||||
# --- Probe: eine schichtweise Messung, jede Zeile mit Timestamp + WANTEST-Prefix ---
|
||||
/system script add name=wantest-probe policy=read,write,test,policy source={
|
||||
:local ts ([/system clock get date] . " " . [/system clock get time])
|
||||
:local e1stat "?"
|
||||
:do { :set e1stat [/ip dhcp-client get [find interface=ether1] status] } on-error={}
|
||||
:local e1addr "-"
|
||||
:do { :set e1addr [/ip dhcp-client get [find interface=ether1] address] } on-error={}
|
||||
:local e1mac [/interface ethernet get [find name=ether1] mac-address]
|
||||
:log info ("WANTEST [" . $ts . "] ether1 status=" . $e1stat . " addr=" . $e1addr . " mac=" . $e1mac)
|
||||
:local gw "-"
|
||||
:do { :set gw [/ip route get [find dst-address="0.0.0.0/0" active=yes] gateway] } on-error={}
|
||||
:log info ("WANTEST route default-gw=" . $gw)
|
||||
# WAN-Routing+NAT: Router -> public 1.1.1.1 (UDP/53). UNABHÄNGIG von ap1-DNS-Config.
|
||||
# (ICMP/HTTPS sind hier geblockt -> :resolve gegen feste IP ist das robuste Signal.)
|
||||
:do { :local w [:resolve "google.com" server=1.1.1.1] ; :log info ("WANTEST wan-reach via-1.1.1.1 ok google.com=" . $w) } on-error={ :log info "WANTEST wan-reach via-1.1.1.1 FAIL (Routing/NAT?)" }
|
||||
# DoH end-to-end: ap1-Resolver = was die Clients als DNS bekommen
|
||||
:do { :local d [:resolve "google.com"] ; :log info ("WANTEST dns-doh ok google.com=" . $d) } on-error={ :log info "WANTEST dns-doh FAIL (DoH/Bootstrap?)" }
|
||||
}
|
||||
|
||||
# --- Run: blockierender Loop, probt N×@15s. Hintergrund-fähig (überlebt Session-Abbruch). ---
|
||||
/system script add name=wantest-run policy=read,write,test,policy source={
|
||||
:global WTN
|
||||
:if (([:typeof $WTN] = "nothing") or ($WTN = "")) do={ :set WTN 24 }
|
||||
:log info ("WANTEST run start (" . $WTN . "x @15s, ~" . ($WTN * 15 / 60) . " min)")
|
||||
:for i from=1 to=$WTN do={
|
||||
/system script run wantest-probe
|
||||
:delay 15s
|
||||
}
|
||||
:log info "WANTEST run done"
|
||||
}
|
||||
|
||||
:log info "WANTEST cutover-test installiert (probe + run, scheduler-frei, disk-logging)"
|
||||
57
routeros/wan-macclone-test.rsc
Normal file
57
routeros/wan-macclone-test.rsc
Normal file
@@ -0,0 +1,57 @@
|
||||
# ===== ap1 — WAN MAC-Clone-Test (FB CM-MAC → ether1), scheduler-frei =====
|
||||
# RouterOS 7.23.x, device-mode=home. Setzt wan-cutover-test.rsc voraus (nutzt wantest-probe).
|
||||
#
|
||||
# FB-WAN-MAC = CM-MAC 0C:72:74:36:90:99 (DOCSIS-SW 7.3.5.3.521, vom User aus FB-UI).
|
||||
# ⚠️ CM-MAC = Cable-Modem-/DOCSIS-Layer. Im echten Bridge-Modus nutzt die FB diese MAC
|
||||
# selbst → MAC-Konflikt-Risiko. Public-IP kam bereits mit ether1-eigener MAC → Clone ist
|
||||
# Verifikation, kein Muss.
|
||||
#
|
||||
# device-mode blockiert /system scheduler → Auto-Revert ist hier KEIN Scheduler, sondern fest
|
||||
# in den Clone-Lauf eingebaut (linearer Ablauf, ~90 s Clone-Fenster, dann garantierter Revert —
|
||||
# läuft im Hintergrund zu Ende, auch wenn die Console-Session abreißt).
|
||||
#
|
||||
# Ablauf (Console über altes WiFi auf 10.40.41.1):
|
||||
# 1) Baseline-Cutover mit ether1-eigener MAC (wantest-run) → Public-IP geloggt
|
||||
# 2) /system script run wanmac-clone → setzt CM-MAC, release/renew, 4 Proben, AUTO-REVERT
|
||||
# 3) Log prüfen: IP/Schichten mit FB-MAC vs. Baseline (/log print where message~"WANTEST")
|
||||
# Not-Revert jederzeit: /system script run wanmac-revert
|
||||
|
||||
# --- idempotent ---
|
||||
/system scheduler remove [find name~"^wanmac-"]
|
||||
/system script remove [find name~"^wanmac-"]
|
||||
|
||||
# --- Clone: orig sichern → CM-MAC → release/renew → 4 Proben → GARANTIERTER Auto-Revert ---
|
||||
/system script add name=wanmac-clone policy=read,write,test,policy source={
|
||||
:global FBMAC
|
||||
:if (([:typeof $FBMAC] = "nothing") or ($FBMAC = "")) do={ :set FBMAC "0C:72:74:36:90:99" }
|
||||
:global E1ORIG
|
||||
:set E1ORIG [/interface ethernet get [find name=ether1] mac-address]
|
||||
:log info ("WANTEST macclone: orig=" . $E1ORIG . " -> fb=" . $FBMAC . " (Auto-Revert in ~90s)")
|
||||
/interface ethernet set [find name=ether1] mac-address=$FBMAC
|
||||
:do { /ip dhcp-client release [find interface=ether1] } on-error={}
|
||||
:delay 2s
|
||||
:do { /ip dhcp-client renew [find interface=ether1] } on-error={}
|
||||
:delay 25s
|
||||
:for i from=1 to=4 do={ /system script run wantest-probe ; :delay 15s }
|
||||
# --- garantierter Auto-Revert im selben Lauf (kein Scheduler nötig) ---
|
||||
/interface ethernet reset-mac-address [find name=ether1]
|
||||
:do { /ip dhcp-client release [find interface=ether1] } on-error={}
|
||||
:delay 2s
|
||||
:do { /ip dhcp-client renew [find interface=ether1] } on-error={}
|
||||
:delay 15s
|
||||
/system script run wantest-probe
|
||||
:log info ("WANTEST macclone done -> revert auf factory-MAC (orig war " . $E1ORIG . ")")
|
||||
}
|
||||
|
||||
# --- Not-Revert: sofort Werks-MAC zurück (falls man früher raus will) ---
|
||||
/system script add name=wanmac-revert policy=read,write,test,policy source={
|
||||
/interface ethernet reset-mac-address [find name=ether1]
|
||||
:do { /ip dhcp-client release [find interface=ether1] } on-error={}
|
||||
:delay 2s
|
||||
:do { /ip dhcp-client renew [find interface=ether1] } on-error={}
|
||||
:delay 10s
|
||||
/system script run wantest-probe
|
||||
:log info "WANTEST macclone manual-revert -> factory-MAC"
|
||||
}
|
||||
|
||||
:log info "WANTEST macclone-test installiert (clone mit eingebautem Auto-Revert + manual-revert)"
|
||||
Reference in New Issue
Block a user