TP15: CRS326-Core als L3-Router aktiviert
- crs326-core nimmt Routing/DHCP/DNS/NAT/WAN/WireGuard von ap1 ueber. - L2-Portplan korrigiert (ap1 #15, Arris WAN #16, branch #8, Sonos #2/3/5/6, IoT #14, VLAN10-Access #11, VLAN1-Hybrid #3/7/9/10/12/17-24). - Backup-RSC gefixt (ether3-24 disabled) und via fixed-RSC eingespielt. - Gestagede L3-Config enabled in einem Rutsch. - Falsche statische Default-Route 0.0.0.0/0 -> 10.40.41.1 entfernt, WAN-DHCP via 90.146.33.177/24 aktiv. - SFP-Ports bleiben disabled (Stromersparnis). - ap1 ist L3-stillgelegt und wird in naechster Session reiner AP. Backup-Dateien (*.backup) und leases-export.json bleiben lokal. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,3 +11,5 @@ docs/nas-vlan20/inspect_*.json
|
||||
|
||||
# RouterOS-Config-Exports/Backups enthalten Live-Secrets (WiFi-Passphrasen etc.) → nicht committen
|
||||
routeros/state-backups/
|
||||
routeros/ap1-wg-hub.privkey
|
||||
routeros/tp15-core-cutover-intended.rsc
|
||||
|
||||
81
PLAN.md
Normal file
81
PLAN.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# TP15/TP21 Kritischer Pfad — Plan (Stand 2026-08-05, aktualisiert)
|
||||
|
||||
> **User-Entscheidung:** Cutover morgen (2026-08-06). Heuteiger Fokus = **Nautobot-Datenmodell für `crs326-core` ausbauen**, damit der Cutover über Nautobot Golden Config geplant/gesteuert werden kann. Governance-Ausnahme #3 damit obsolet für den Config-Teil; die physischen Cutover-Schritte bleiben ein geplantes Wartungsfenster.
|
||||
|
||||
## Aktueller Stand (Read-only Checks)
|
||||
|
||||
| Komponente | Befund |
|
||||
|---|---|
|
||||
| **ap1** | Noch aktiver L3-Router, 53 DHCP-Reservierungen, Public-IP `90.146.35.38`, WG-Hub live. RouterOS 7.23.2. |
|
||||
| **crs326-core** | Erreichbar nur über VLAN1-Temp `10.40.41.211`. **Keine L3-Config** auf dem Gerät. `10.40.99.11` tot, weil sw1 #12 kein VLAN99 tagged trägt. |
|
||||
| **crs326-branch** | Produktiv auf `10.40.99.13`, läuft. |
|
||||
| **Nautobot** | App live (`10.40.20.30:8080`), Golden-Config-App installiert, Git-Repo zu Gitea verbunden. **Aber:** `crs326-core` nur rudimentär modelliert (7 Interfaces, keine VLAN-SVIs, keine SecretsGroup), GC-Templates/Regeln nur PoC-Niveau, Scheduler+Worker unhealthy. |
|
||||
| **MikroMCP** | In dieser Session **nicht** für core/branch geladen — Env-Variablen-Mismatch (`~/.secrets` exportiert `CRS326_*`, `routers.yaml` erwartet `ROUTER_CRS326_*`). |
|
||||
| **Portainer ep14** | API-Token stale/ungültig → Docker-Management auf NAS gestört. |
|
||||
| **Postgres / pve-mcp / Gitea / CF-Token** | Grün. |
|
||||
|
||||
## Heutiges Ziel (2026-08-05)
|
||||
|
||||
**Nautobot-Datenmodell für `crs326-core` so weit vervollständigen, dass morgen ein Config-Render für den L3-Router möglich ist.**
|
||||
|
||||
Konkrete Arbeitspakete:
|
||||
1. MikroMCP reparieren & neu starten (core/branch schreibbar für Tests).
|
||||
2. Portainer-Token rotieren (damit Nautobot-Container-Logs/Health prüfbar sind).
|
||||
3. Nautobot worker/scheduler healen.
|
||||
4. `crs326-core` Device-Modell in Nautobot vervollständigen:
|
||||
- Interfaces `ether6`–`ether24`, `sfp-sfpplus1`, `sfp-sfpplus2`.
|
||||
- VLAN-SVIs (`vlan10`–`vlan100`) + IP-Adressen (GW `.1` je VLAN).
|
||||
- Access/Trunk-Ports mit korrekten untagged/tagged VLANs gemäß Ziel-Layout.
|
||||
- `SecretsGroup` mit RouterOS-Credentials.
|
||||
- `Platform` = RouterOS.
|
||||
- Status = `Planned` (morgen nach Cutover `Active`).
|
||||
5. DHCP-Scopes, statische DNS-Einträge, Firewall-Zonen/-Regeln, NAT, WireGuard-Peers, CAKE-Parameter im Datenmodell abbilden (Custom Fields oder native Modelle, je nach Nautobot-Möglichkeit).
|
||||
6. Golden-Config SoT-Aggregation Query erweitern.
|
||||
7. RouterOS-Jinja-Template für L3-Core vervollständigen (ggf. anhand von `routeros/tp15-core-l3-staged.rsc`).
|
||||
8. GC Compliance-Features/Regeln für kritische Bereiche definieren.
|
||||
9. Backup/Intended-Job auf `crs326-branch` testen (Proof-of-Concept für MikroTik-Switch).
|
||||
10. ap1-Reservierungen + WG-Privkey maschinell exportieren (Input für Datenmodell + Template).
|
||||
|
||||
## Morgiges Ziel (2026-08-06) — Cutover
|
||||
|
||||
Voraussetzungen vor dem Fenster:
|
||||
- `crs326-core` in Nautobot vollständig modelliert.
|
||||
- Golden Config kann ein `intended`-Config für core rendern.
|
||||
- MikroMCP schreibbar, dryRun auf core erfolgreich.
|
||||
- ap1-Voll-Backup frisch gezogen.
|
||||
- Port-Umzugsplan final: core #4=ap1, #8=branch, #16=Arris/WAN; sw1-Rest stilllegen.
|
||||
- iPhone-Hotspot als Rettungspfad parat.
|
||||
- Wartungsfenster mit Hausmitteilung (ca. 60 Min).
|
||||
|
||||
Cutover-Ablauf:
|
||||
1. Nautobot `intended` Config für core rendern/exportieren.
|
||||
2. ap1 als Router stilllegen (DHCP/DNS/NAT/GW-IPs/WAN-Client/WG-Hub disable).
|
||||
3. ap1-Uplink `ether2` → `ether1` (PoE), `poe-out=off`.
|
||||
4. Kabel von sw1 auf core umstecken.
|
||||
5. core-L3-Config aktivieren (Nautobot-Deploy oder REST/MikroMCP-Apply).
|
||||
6. Abnahme je VLAN, branch, WG-Handshake, CF/WARP, Public-IP.
|
||||
7. Rollback-Test (optional, aber empfohlen).
|
||||
|
||||
## Nach dem Cutover
|
||||
|
||||
- Mgmt-Renumber (branch `.99.13` → `.99.12`, core `.99.11` konsolidieren).
|
||||
- VLAN1-Temp-IPs entfernen.
|
||||
- Nautobot: core `Planned` → `Active`.
|
||||
- Doku aktualisieren (`teilprojekte.md`, `CLAUDE.md`, `ip-plan.md`).
|
||||
- WLAN-Neuprovisionierung (CAPsMAN-Abbau) als eigene Session.
|
||||
- TP5/TP6 danach.
|
||||
|
||||
## Rollback (während Cutover)
|
||||
|
||||
1. core-L3 deaktivieren / Config zurückziehen.
|
||||
2. Kabel zurück auf sw1.
|
||||
3. ap1 DHCP/DNS/NAT/GW-IPs/WAN-Client/WG-Hub wieder aktivieren.
|
||||
4. Netz wieder im heutigen Zustand.
|
||||
|
||||
## Erste Schritte jetzt
|
||||
|
||||
1. Task-Liste anlegen.
|
||||
2. MikroMCP envPrefix/Secrets fixen + Neustart.
|
||||
3. Portainer-Token rotieren.
|
||||
4. Nautobot worker/scheduler healen.
|
||||
5. Dann in das `crs326-core`-Datenmodell einsteigen.
|
||||
@@ -344,7 +344,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
### TP14.5 — Session E: Freigabe-Gate → TP5-Firewall ▸ 🔜 (ZULETZT)
|
||||
- Erst wenn TP14.1–14.3 durch (alle Origins/Connectoren in VLAN20) → dann TP5 (Deny-by-default) starten. Reines Reihenfolge-Gate, kein eigener Change.
|
||||
|
||||
### TP15 — HW-Refresh: Switching + Router + DC-USV ▸ 🟢 **CRS326-Bring-up + Branch-Tausch DURCH (2026-07-23)**; Core-Tausch/L3-Umzug offen (eigene Session) — `docs/hw-refresh-requirements.md`, Memory `project_mikrotik_commit_nautobot_gc`
|
||||
### TP15 — HW-Refresh: Switching + Router + DC-USV ▸ 🟢 **CRS326-Bring-up + Branch-Tausch DURCH (2026-07-23)**; Core-Tausch/L3-Umzug **vorbereitet, Cutover-Config materialisiert (2026-08-05)**, Cutover = nächstes Wartungsfenster — `docs/hw-refresh-requirements.md`, Memory `project_mikrotik_commit_nautobot_gc`
|
||||
- ✅ **BRING-UP BEIDER CRS326 + BRANCH-TAUSCH gegen sw2 — DURCH (2026-07-23, Claude via REST unter Governance-Ausnahme #2).** Ablauf/As-built:
|
||||
- **Zugriffsweg (Henne-Ei gelöst):** Erst-Reihenfolge war **core zuerst** (User-Korrektur — core hängt an sw1 und ist der L2-Pfad, über den branch überhaupt erreichbar wird; branch war isoliert). Zugriff auf die Werks-`192.168.88.1` über **temporäre ap1-Zweit-IP `192.168.88.2/24` + srcnat-Masquerade `192.168.88.0/24`** (beide `TP15-temp`, nach Bring-up wieder entfernt — Rückweg nötig, weil die Werks-Box keine Route zu VLAN10 hat). Config dann komplett per **REST** (`/system/script` PUT+run), kein Winbox-Paste. **Winbox-MAC-Connect scheiterte reproduzierbar** („macconnection sync timeout" über WLAN/quer durch den Fabric — braucht selben Draht).
|
||||
- **Identitäten am Gerät verifiziert (nicht nur Doku):** `core` = sw-id **4W04-URHT**, MAC `04:F4:1C:B4:17:76`, Serial `HKA0AREXJFM`, PW `X9…`; `branch` = sw-id **RGZJ-UK0T**, MAC `04:F4:1C:B4:15:58`, Serial `HKA0AJJA52F`, PW `PHR…` (ap2 hängt an branch **ether24** — bridge-host bestätigt = definitiv branch). **PWs in `~/.secrets/credentials.env`.**
|
||||
@@ -354,6 +354,8 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
- 🐞 **Gotchas festgehalten:** (1) **Kabel ether3↔ether5 waren beim Umstecken vertauscht** → ein AZ-Sonos landete als Access-VLAN10 in `10.40.10.190` **und** blutete via SonosNet nach VLAN40 (= Dual-Homing-Muster, `project_dual_homing_slowness_incident`) → Kabeltausch gefixt, beide AZ-Sonos jetzt sauber VLAN40 (`.191`/`.192` bound). (2) RouterOS-Script-`policy`-Feld per REST wählerisch → **weglassen** (admin-Default = volle Policy). (3) Disable-Regex mit `^…$`-Ankern griff nicht → `[find name!="ether1" and …]` nutzen. (4) REST-`PUT`-Antwort mit mehrzeiligem `source` ist kein sauberes JSON → ID separat via `?.proplist=.id` holen. (5) Claude-Code-Auto-Mode-Classifier blockt Device-Config-*Writes* per Bash (Reads ok) → `autoMode.allow`-Regel in `.claude/settings.local.json` nötig (kann Claude sich nicht selbst setzen).
|
||||
- **🔜 Als Nächstes (eigene Session, Übergabe): Core-Tausch = L3-Umzug** (Routing/DHCP/DNS/CF-Mesh von ap1 → crs326-core) — **Vollausfall-Fenster**, s. `docs/tp15-core-swap-session-handoff-prompt.md`. Danach WLAN-Neuprovisionierung (TP3, CAPsMAN-Abbau). Finaler Mgmt-Renumber dann: branch `.99.13`→`.99.12`, core bleibt `.99.11`.
|
||||
- ✅ **Core-Swap VORBEREITET (2026-07-23, reine Prep-Session, kein Netz-Eingriff):** ap1s Live-L3-Config vollständig gelesen (MikroMCP) und als **staged Config** materialisiert → `routeros/tp15-core-l3-staged.rsc` (alles Betriebsumlenkende `disabled=yes`, im Cutover in einem Rutsch `enable`; ~50 Reservierungen + WG-Privkey bewusst erst im Fenster maschinell von ap1 geholt statt abgetippt). Runbook/Rollback/Verifikation im Plan. **3 Fenster-Start-Entscheide festgelegt:** (1) **WG-Hub (TP10 FM/DW-VPN) migriert MIT** — war im Handoff-Prompt übersehen, hängt an ap1s Public-Edge und kann dort nicht bleiben; (2) Governance = **frische Direkt-Ausnahme #3** (REST/MikroMCP), danach intended→Nautobot; (3) Rettungspfad = **iPhone-Hotspot**.
|
||||
- ✅ **Nautobot-Modell + Golden-Config-Template für L3-Cutover vervollständigt (2026-08-05):** `crs326-core` jetzt Rolle *Router*, alle VLAN-SVIs (`vlan10/20/30/40/50/90/99/100`) + Gateway-IPs (`.1`) modelliert; `nautobot/mikrotik_routeros.j2` (Gitea `bf-golden-config`) erzeugt für `crs326-core` die vollständige staged L3-Konfig (Interface-Lists, GW-IPs, WAN-DHCP, DHCP-Server/Pools, DNS, NAT, Firewall, WG-Hub) und für alle anderen MikroTik-Geräte nur die Identität. Git-Sync + Generate Intended Config erfolgreich getestet; intended config für `crs326-core` liegt in Nautobot vor.
|
||||
- ✅ **ap1-Cutover-Daten exportiert + in Cutover-Config eingebaut (2026-08-05):** 54 statische DHCP-Leases aus ap1 (`dhcp-v10`/`v20`/`v30`/`v40`) nach `routeros/ap1-leases-to-core.rsc` überführt; WG-Hub-Privkey von ap1 geholt und in die lokale Cutover-Config `routeros/tp15-core-cutover-intended.rsc` eingesetzt (der **WG-Privkey landet NICHT im Git-Template** — Secret).
|
||||
- 🐞 **Prep-Gotchas:** (a) **MikroMCP kann core noch nicht schreiben** — `ROUTER_CRS326_CORE_*` im MCP-Prozess nicht geladen (jeder Zugriff „Missing environment variable") → vor dem Fenster MCP neu starten oder REST-curl gegen `http://10.40.41.211/rest`. (b) Mgmt-`.99.11` tot (sw1 #12 trägt kein 99T), nur VLAN1-Temp `.41.211` erreichbar. (c) **WG-Hub:** Privkey von ap1 mitnehmen (sonst FM/DW-Reconfig nötig). (d) core-vlan99 wird GW `.1`; Bring-up-`.11` dadurch redundant (Fenster-Reconcile). (e) VLAN1 raus: Hybrid-VLAN1-Drops sw1 GE3/7/10 beim Umstecken einem echten VLAN zuordnen oder stilllegen.
|
||||
- ✅ **WG-Endpoint-Frage geklärt (2026-07-23):** Spokes adressieren den Hub über `bf4.emsenhuber.net:51821` = CF-A-Record (proxied=false, TTL 120, aktuell `90.146.35.38`). **Kein Updater auf ap1** → nichts zu migrieren; `bf4` folgt der IP manuell (offener TP10-Follow-up). Zieht core am WAN eine neue IP (Lease sticky, eher nicht), via `CF_API_TOKEN` nachziehen: `bf4`-Record + Access-Policy `bf4-home-ip` (`90.146.35.38/32`). **Chance:** core ist nicht `device-mode=home` → scheduler/fetch gehen → `bf4`-DDNS-Auto-Updater dort bauen (schließt TP10-Follow-up).
|
||||
- 📋 **Session-Handover** für die Cutover-Session: `docs/tp15-core-swap-session-handover.md` (Einstieg + Pre-Window-Checkliste + Kurz-Runbook; Original-Auftrag bleibt `docs/tp15-core-swap-session-handoff-prompt.md`).
|
||||
@@ -523,7 +525,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
- **Verwandt/Abgrenzung:** vw ist auch in **TP16** offen (CF-Access: `bypass`→WARP-geschützt) — **DB-HA ≠ Access**, getrennt behandeln. Reziprokes 2-Site-Muster analog **TP16**/**TP18**.
|
||||
- Abh.: **TP20** (Tier-1 Postgres muss stehen), **TP10** (WG-Transport für Phase-2), **TP18** (Backup-Schirm). Kein Blocker für TP21.
|
||||
|
||||
### TP21 — Nautobot Golden Config (config-as-code Control-Plane) ▸ ⏳ **Plattform + Golden-Config-App live** (App-Install nachträglich verifiziert 2026-07-22, Doku war stale), **Datenmodell/Git-Backend/Device-Adoption noch offen** — Memory `project_mikrotik_commit_nautobot_gc`
|
||||
### TP21 — Nautobot Golden Config (config-as-code Control-Plane) ▸ 🟢 **Plattform + Golden-Config-App live** (App-Install nachträglich verifiziert 2026-07-22), **Basisdaten + Git-Backend + L3-Core-Template vervollständigt (2026-08-05)**; Device-Adoption/Compliance-Push noch offen — Memory `project_mikrotik_commit_nautobot_gc`
|
||||
- **Ziel:** modellierter Control-Plane über den MikroTik-**RouterOS**-Kern: GUI-SoT + **Config-Compliance/Drift** + intended-config + Push. **Ergänzt** MikroMCP (interaktiv/Debug), **ersetzt es nicht** (deklarativ/DR/Compliance). Aus User-Recherche 2026-07-14: MikroTik in Golden Config **erstklassig** (`mikrotik_routeros` + `_api`, Nornir/NAPALM, backup+deploy).
|
||||
- **Scope-Grenze:** RouterOS in-model = **Router (ap1/ap2, dauerhaft — kein RB5009) + beide CRS326-Switches** (RouterOS-Boot) → Golden Config deckt den **ganzen Kabel-Fabric**. Außerhalb bleibt nur **Omada-WLAN** (eigener Controller, spielt aber laut TP15-Korrektur ohnehin keine Rolle mehr).
|
||||
- 🔒 **Wird zum alleinigen Config-Weg für Netzgeräte (Governance-Entscheid 2026-07-16, s. oben):** ab hier keine ad-hoc MikroMCP-Writes/Switch-UI-Klicks mehr auf Dauer — Nautobot managed den Fleet.
|
||||
@@ -539,8 +541,11 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
|
||||
- **ap1-Interfaces (26):** ether1-5, bridge, lo, wg-hub, vlan10-100, wifi1/wifi2, 7 VAPs — inkl. MACs, `ether2` als Trunk (untagged VLAN1 + tagged 10-100), VAPs als Access-Ports auf ihrem VLAN. 9 Gateway-IPs an ihren Interfaces. Platzhalter-Interface `mgmt` auf ap1 gelöscht (existiert real nicht).
|
||||
- **WLAN:** logischer Controller `bf-wlan` (**kein** CAPsMAN — `controller_device` bewusst leer, die Control-Plane *ist* Nautobot GC) + Gruppe `BF-WLAN-APs` (ap1+ap2) + **6 WirelessNetworks mit VLAN-Bindung** + 2 RadioProfiles (2,4 GHz ch1 / 5 GHz ch36, Domain AT).
|
||||
- 🐞 **API-Gotcha:** `tagged_vlans` wird vom REST-Serializer in Detail-/List-Views als `null` zurückgegeben, **obwohl korrekt gespeichert** — Verifikation nur über **GraphQL** verlässlich. Kostet sonst eine Stunde Fehlersuche an einem Nicht-Problem. Ebenso: Relationen kommen per Default ohne `display` (`?depth=1` nötig), und `VLANGroup`/`Prefix`/`VLAN` brauchen passende `content_types` am LocationType, sonst 400.
|
||||
- ⚠️ **Offen/nachzutragen:** exaktes Modell von sw1 + cudy1 (aktuell `… (Modell TBD)`); Standort von sw1/sw2/cudy1 (hängen an `BF` statt an einem Bereich); ap2s `primary_ip4` zeigt noch auf das tote `10.40.41.2`; CRS326-Ports bewusst noch nicht angelegt (erst wenn die Portbelegung steht).
|
||||
- **Offen:** Git-Backend-Anbindung an Gitea; ap1/ap2-Adoption via RouterOS-API; ob OpenWrt je in-model muss (custom Nornir-Dispatcher — nur relevant falls der Router-Pfad je auf OpenWrt+cake-autorate wechselt, aktuell nicht geplant).
|
||||
- ✅ **CRS326-Core L3-Device-Modell + Ports angelegt (2026-08-05):** `crs326-core` jetzt Rolle *Router*, alle VLAN-SVIs (`vlan10/20/30/40/50/90/99/100`) + Gateway-IPs `.1` (außer vlan100) in Nautobot; Portbelegung via `nautobot/ingest-crs326-ports.py` aktualisiert. `crs326-branch` bleibt *Switch* mit Mgmt-IP `.99.13` (Zielrenumber `.12` im Cutover-Fenster).
|
||||
- ⚠️ **Offen/nachzutragen:** exaktes Modell von sw1 + cudy1 (aktuell `… (Modell TBD)`); Standort von sw1/sw2/cudy1 (hängen an `BF` statt an einem Bereich); ap2s `primary_ip4` zeigt noch auf das tote `10.40.41.2` (Ziel `.99.2`, Cutover-Fenster).
|
||||
- ✅ **Git-Backend an Gitea angebunden (2026-08-05):** Repository `bf-golden-config` (`jinja_templates/mikrotik_routeros.j2`) sync-t in Nautobot; Generate Intended Config für `crs326-core` erfolgreich, intended config in GC-Tabelle vorhanden.
|
||||
- ✅ **Lokale Cutover-Config materialisiert:** `routeros/tp15-core-cutover-intended.rsc` enthält die aus Nautobot gerenderte Config plus die 54 ap1-Leases und den WG-Hub-Privkey (lokales Fenster-Artefakt, **nicht** im Golden-Config-Repo).
|
||||
- **Offen:** ap1/ap2/crs326-Adoption + Compliance-Push (RouterOS-API); RouterOS-Nornir-Dispatcher falls nötig; Branch-Renumber `.13→.12` und AP-Mgmt-IP-Fix in Datenmodell beim Cutover; Secret-Handling für WG-Privkey in Nautobot/Nornir klären (aktuell lokale Injektion).
|
||||
- Abh.: **TP20** (Postgres muss stehen), Gitea ✅, RouterOS-Router (ap1/ap2, dauerhaft).
|
||||
|
||||
### TP-R — Router-Capabilities-Sweep ▸ FERTIG (`docs/research/routeros-capabilities.md`)
|
||||
|
||||
@@ -31,17 +31,17 @@ routers:
|
||||
|
||||
# --- TP15 CRS326-Bring-up (2026-07-23) ---
|
||||
# Mgmt auf VLAN99. www=plain HTTP:80 (wie ap1/ap2) -> tls.enabled:false.
|
||||
# ENV in ~/.claude.json (mikromcp-Block): ROUTER_CRS326_CORE_USER/PASS, ROUTER_CRS326_BRANCH_USER/PASS.
|
||||
# Wird erst nach MCP-Neustart (neue Session) live; diese Session Verify via direktem REST-curl + ap1-ping.
|
||||
# ENV via ~/.secrets/exports.zsh: CRS326_CORE_USER/PASS, CRS326_BRANCH_USER/PASS.
|
||||
# Wird erst nach MCP-Neustart (neue Session) live; diese Session Verify via direktem REST-curl.
|
||||
crs326-core:
|
||||
host: "10.40.99.11"
|
||||
host: "10.40.41.211" # TEMP cutover mgmt IP until VLAN99 trunk through sw1 is live
|
||||
port: 80
|
||||
tls:
|
||||
enabled: false
|
||||
rejectUnauthorized: true
|
||||
credentials:
|
||||
source: "env"
|
||||
envPrefix: "ROUTER_CRS326_CORE"
|
||||
envPrefix: "CRS326_CORE"
|
||||
tags: ["bf", "switch", "core", "future-l3-router"]
|
||||
rosVersion: "7.19.5"
|
||||
|
||||
@@ -53,6 +53,6 @@ routers:
|
||||
rejectUnauthorized: true
|
||||
credentials:
|
||||
source: "env"
|
||||
envPrefix: "ROUTER_CRS326_BRANCH"
|
||||
envPrefix: "CRS326_BRANCH"
|
||||
tags: ["bf", "switch", "branch"]
|
||||
rosVersion: "7.19.5"
|
||||
|
||||
153
nautobot/ingest-crs326-core-l3.py
Normal file
153
nautobot/ingest-crs326-core-l3.py
Normal file
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/env python3
|
||||
"""BF-Netzwerk -> Nautobot: crs326-core L3-Datenmodell ergaenzen (TP15 Cutover-Prep).
|
||||
|
||||
Erstellt fuer crs326-core:
|
||||
- vlan10..vlan90, vlan100 als virtuelle Bridge-Subinterfaces (tagged)
|
||||
- GW-IPs 10.40.<vlan>.1/24 (v10..v90)
|
||||
- Primaer-IP bleibt 10.40.99.11/24 (Bring-up-Mgmt)
|
||||
- Rolle Router, Status bleibt Planned bis Cutover
|
||||
|
||||
Idempotent; verwendet GraphQL fuer tagged_vlans (REST liefert null).
|
||||
"""
|
||||
import json, os, sys, urllib.request, urllib.error, urllib.parse
|
||||
|
||||
BASE = "http://10.40.20.30:8080/api"
|
||||
TOKEN = os.environ.get("NAUTOBOT_TOKEN", "")
|
||||
DRY = "--apply" not in sys.argv
|
||||
log = []
|
||||
|
||||
|
||||
def req(method, path, data=None):
|
||||
url = path if path.startswith("http") else f"{BASE}{path}"
|
||||
body = json.dumps(data).encode() if data is not None else None
|
||||
r = urllib.request.Request(url, data=body, method=method)
|
||||
r.add_header("Authorization", f"Token {TOKEN}")
|
||||
r.add_header("Content-Type", "application/json")
|
||||
r.add_header("Accept", "application/json")
|
||||
try:
|
||||
with urllib.request.urlopen(r, timeout=30) as resp:
|
||||
raw = resp.read()
|
||||
return json.loads(raw) if raw else {}
|
||||
except urllib.error.HTTPError as e:
|
||||
print(f"!! {method} {url}\n payload={json.dumps(data)}\n -> {e.code} {e.read().decode()[:500]}")
|
||||
raise
|
||||
|
||||
|
||||
def gql(query):
|
||||
r = urllib.request.Request(f"{BASE}/graphql/", data=json.dumps({"query": query}).encode(), method="POST")
|
||||
r.add_header("Authorization", f"Token {TOKEN}")
|
||||
r.add_header("Content-Type", "application/json")
|
||||
with urllib.request.urlopen(r, timeout=30) as resp:
|
||||
data = json.loads(resp.read())
|
||||
if data.get("errors"):
|
||||
print("GraphQL errors:", data["errors"])
|
||||
raise SystemExit(1)
|
||||
return data["data"]
|
||||
|
||||
|
||||
def find(path, **params):
|
||||
q = "&".join(f"{k}={urllib.parse.quote(str(v))}" for k, v in params.items())
|
||||
res = req("GET", f"{path}?{q}&limit=2")
|
||||
return res["results"][0] if res.get("count") else None
|
||||
|
||||
|
||||
def goc(path, match, payload, label=None):
|
||||
name = label or payload.get("name") or str(match)
|
||||
obj = find(path, **match)
|
||||
if obj:
|
||||
log.append(f" = {name}")
|
||||
return obj
|
||||
if DRY:
|
||||
log.append(f" + {name} (dry-run)")
|
||||
return {"id": f"DRY-{name}"}
|
||||
obj = req("POST", path + "/", payload)
|
||||
log.append(f" + {name}")
|
||||
return obj
|
||||
|
||||
|
||||
def patch(path, obj, payload, label):
|
||||
delta = {}
|
||||
for k, v in payload.items():
|
||||
cur = obj.get(k)
|
||||
cur_id = cur.get("id") if isinstance(cur, dict) else cur
|
||||
if cur_id != v:
|
||||
delta[k] = v
|
||||
if not delta:
|
||||
log.append(f" = {label} (unveraendert)")
|
||||
return obj
|
||||
if DRY:
|
||||
log.append(f" ~ {label}: {list(delta)} (dry-run)")
|
||||
return obj
|
||||
out = req("PATCH", f"{path}/{obj['id']}/", delta)
|
||||
log.append(f" ~ {label}: {list(delta)}")
|
||||
return out
|
||||
|
||||
|
||||
def sid(name):
|
||||
return find("/extras/statuses", name=name)["id"]
|
||||
|
||||
|
||||
S_ACTIVE = sid("Active")
|
||||
S_PLANNED = sid("Planned")
|
||||
role_router = find("/extras/roles", name="Router")
|
||||
ns_global = find("/ipam/namespaces", name="Global")["id"]
|
||||
vg = find("/ipam/vlan-groups", name="BF")
|
||||
|
||||
V = {}
|
||||
for vid in (1, 10, 20, 30, 40, 50, 90, 99, 100):
|
||||
V[vid] = find("/ipam/vlans", vid=vid, vlan_group=vg["id"])
|
||||
|
||||
core = find("/dcim/devices", name="crs326-core")
|
||||
print("== crs326-core: Rolle + Status")
|
||||
patch("/dcim/devices", core, {"role": role_router["id"]}, "crs326-core role=Router")
|
||||
|
||||
print("== crs326-core: VLAN-Subinterfaces (L3 SVIs)")
|
||||
br = find("/dcim/interfaces", device="crs326-core", name="bridge")
|
||||
for vid in (10, 20, 30, 40, 50, 90, 99, 100):
|
||||
ifname = f"vlan{vid}"
|
||||
desc = f"L3 SVI VLAN{vid}" if vid != 99 else "L3 SVI VLAN99 (Mgmt + Router-GW)"
|
||||
obj = goc("/dcim/interfaces", {"device": core["id"], "name": ifname},
|
||||
{"device": core["id"], "name": ifname, "type": "virtual",
|
||||
"status": S_ACTIVE, "description": desc,
|
||||
"mode": "tagged", "parent_interface": br["id"],
|
||||
"tagged_vlans": [V[vid]["id"]]}, label=f"core:{ifname}")
|
||||
if not DRY and not str(obj["id"]).startswith("DRY"):
|
||||
# Nachträglich Parent/Mode/VLAN sicherstellen (goc legt nur an, patch bei Änderung)
|
||||
req("PATCH", f"/dcim/interfaces/{obj['id']}/",
|
||||
{"parent_interface": br["id"], "mode": "tagged",
|
||||
"tagged_vlans": [V[vid]["id"]]})
|
||||
|
||||
print("== crs326-core: GW-IPs je VLAN (v10..v99)")
|
||||
IF = {}
|
||||
for vid in (10, 20, 30, 40, 50, 90, 99):
|
||||
IF[vid] = find("/dcim/interfaces", device="crs326-core", name=f"vlan{vid}")
|
||||
for vid in (10, 20, 30, 40, 50, 90, 99):
|
||||
addr = f"10.40.{vid}.1/24"
|
||||
desc = f"VLAN{vid} GW (core, staged)"
|
||||
ip = find("/ipam/ip-addresses", address=addr)
|
||||
if not ip:
|
||||
ip = goc("/ipam/ip-addresses", {"address": addr},
|
||||
{"address": addr, "status": S_ACTIVE, "description": desc,
|
||||
"namespace": ns_global}, label=addr)
|
||||
if DRY or str(ip["id"]).startswith("DRY"):
|
||||
continue
|
||||
ex = find("/dcim/interfaces", device="crs326-core", name=f"vlan{vid}", ip_addresses=ip["id"])
|
||||
if not ex:
|
||||
try:
|
||||
req("POST", "/ipam/ip-address-to-interface/",
|
||||
{"ip_address": ip["id"], "interface": IF[vid]["id"]})
|
||||
log.append(f" + {addr} -> core:vlan{vid}")
|
||||
except urllib.error.HTTPError:
|
||||
log.append(f" = {addr} -> core:vlan{vid} (bereits)")
|
||||
|
||||
print("== crs326-core: Kommentar (L3-Router-Ziel)")
|
||||
if not DRY:
|
||||
req("PATCH", f"/dcim/devices/{core['id']}/",
|
||||
{"comments": "TP15 2026-07-23: grundkonfiguriert via REST (Bring-up-Level). "
|
||||
"MAC 04:F4:1C:B4:17:76, software-id 4W04-URHT, Serial HKA0AREXJFM. "
|
||||
"Wird neuer L3-Router (Routing/DHCP/DNS/NAT von ap1 -> core). "
|
||||
"Mgmt 10.40.99.11 (VLAN99) + GW-IPs .1 je Client-VLAN staged. "
|
||||
"VLAN1-Temp 10.40.41.211. Status Planned bis Cutover."})
|
||||
|
||||
print("\n".join(log))
|
||||
print(f"\n{'DRY-RUN - nichts geschrieben. Mit --apply ausfuehren.' if DRY else 'ANGEWENDET.'}")
|
||||
126
nautobot/mikrotik_routeros.j2
Normal file
126
nautobot/mikrotik_routeros.j2
Normal file
@@ -0,0 +1,126 @@
|
||||
# Nautobot Golden Config -- intended RouterOS config for {{ obj.name }}
|
||||
# Generated from Nautobot device data + hardcoded TP15 L3 staged values.
|
||||
# Scope: identity for all MikroTik devices; full staged L3 cutover config for crs326-core.
|
||||
|
||||
/system identity set name={{ obj.name }}
|
||||
|
||||
{% if obj.name == "crs326-core" %}
|
||||
# =====================================================================================
|
||||
# TP15 — crs326-core L3 staged config (ap1 -> core). NICHT automatisch aktivieren.
|
||||
# Alles Betriebsumlenkende wird disabled=yes angelegt; Cutover aktiviert in einem Rutsch.
|
||||
# =====================================================================================
|
||||
|
||||
# [1] INTERFACE-LISTS
|
||||
/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
|
||||
|
||||
# [2] GW-IPs je VLAN — STAGED (disabled=yes)
|
||||
/ip/address
|
||||
{% for iface in obj.interfaces.all() %}
|
||||
{% if iface.name.startswith("vlan") %}
|
||||
{% for ip in iface.ip_addresses.all() %}
|
||||
{% if ip.host == "10.40." + iface.name|replace("vlan", "") + ".1" %}
|
||||
add address={{ ip.address }} interface={{ iface.name }} comment="{{ iface.description }}" disabled=yes
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
# [3] WAN DHCP-Client (Liwest/Arris) — STAGED
|
||||
/ip/dhcp-client add interface=vlan100 use-peer-dns=no add-default-route=yes \
|
||||
comment="TP15 WAN Liwest (Arris)" disabled=yes
|
||||
|
||||
# [4] DHCP-Server je VLAN
|
||||
/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
|
||||
|
||||
/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
|
||||
|
||||
# [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
|
||||
|
||||
/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"
|
||||
/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
|
||||
|
||||
# [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
|
||||
/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"
|
||||
|
||||
/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"
|
||||
|
||||
# [8] WG-HUB (TP10 Multi-Site) — private-key wird im Cutover-Fenster gesetzt
|
||||
/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)" disabled=yes
|
||||
/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"
|
||||
{% endif %}
|
||||
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.
|
||||
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"]
|
||||
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
|
||||
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()
|
||||
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
|
||||
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)
|
||||
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}")
|
||||
59
routeros/push-gc-template.py
Normal file
59
routeros/push-gc-template.py
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Push nautobot/mikrotik_routeros.j2 to the bf-golden-config Gitea repo.
|
||||
|
||||
Reads Gitea token from ~/.secrets/credentials.env (GITEA_ACCESS_TOKEN).
|
||||
"""
|
||||
import base64
|
||||
import json
|
||||
import pathlib
|
||||
import re
|
||||
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"
|
||||
|
||||
|
||||
def get_token():
|
||||
text = TOKEN_PATH.read_text()
|
||||
m = re.search(r"^GITEA_ACCESS_TOKEN=(.+)$", text, re.MULTILINE)
|
||||
if not m:
|
||||
raise SystemExit("GITEA_ACCESS_TOKEN not found")
|
||||
return m.group(1).strip()
|
||||
|
||||
|
||||
def main():
|
||||
token = get_token()
|
||||
src = pathlib.Path(__file__).parent.parent / "nautobot" / "mikrotik_routeros.j2"
|
||||
content = src.read_text()
|
||||
|
||||
# fetch current SHA
|
||||
req = urllib.request.Request(
|
||||
f"{REPO}/contents/{FILE}?ref=main",
|
||||
headers={"Authorization": f"token {token}"},
|
||||
)
|
||||
with urllib.request.urlopen(req) as resp:
|
||||
meta = json.loads(resp.read().decode())
|
||||
sha = meta["sha"]
|
||||
|
||||
payload = {
|
||||
"content": base64.b64encode(content.encode()).decode(),
|
||||
"sha": sha,
|
||||
"message": "TP15: WG-HUB private key + ap1 cutover lease prep",
|
||||
"branch": "main",
|
||||
}
|
||||
req2 = urllib.request.Request(
|
||||
f"{REPO}/contents/{FILE}",
|
||||
data=json.dumps(payload).encode(),
|
||||
headers={
|
||||
"Authorization": f"token {token}",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
method="PUT",
|
||||
)
|
||||
with urllib.request.urlopen(req2) as resp:
|
||||
print(resp.status, json.loads(resp.read().decode()).get("commit", {}).get("id", "?"))
|
||||
|
||||
|
||||
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()
|
||||
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"
|
||||
Reference in New Issue
Block a user