From 498fa06472d2c3e56b917210b2c92931a5620368 Mon Sep 17 00:00:00 2001 From: Christoph Emsenhuber Date: Tue, 9 Jun 2026 18:08:45 +0200 Subject: [PATCH] =?UTF-8?q?Initial=20commit:=20BF=20Core-Switch-Prep=20+?= =?UTF-8?q?=20VLAN-Architektur=20+=20Delegations-=C3=9Cbergabe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ALL-SG8316M auf FW 2.2.1.2956 geflasht; VLAN-DB 10/20/30/40/100 via Telnet-CLI (non-disruptiv) - CLI-Tooling: run-cli.exp + .cli-Files + CLI-REFERENCE (FW 2.2.1, IOS-artig) - Kanonisches Inventar: bf.csv/md + build.py (Doku-Motor), Core-Port-Map - Finaler VLAN-/Adressplan (10.40..0/24), Firmware-Runbooks, Recovery-Assets - Secrets/Firmware/State/DS_Store via .gitignore ausgeschlossen Co-Authored-By: Claude Opus 4.8 --- .gitignore | 2 + README.md | 4 + docs/core-switch-prep.md | 104 +++++++ docs/firmware-flash-runbook.md | 84 +++++ docs/manual-flash-howto.md | 35 +++ docs/vlan-plan.md | 44 +++ inventory/IPs.xlsx | Bin 0 -> 41482 bytes inventory/README.md | 19 ++ inventory/bf-core-ports.csv | 5 + inventory/bf-core-ports.md | 11 + inventory/bf.csv | 254 +++++++++++++++ inventory/bf.md | 293 ++++++++++++++++++ inventory/build.py | 144 +++++++++ omada/docker-compose.yml | 37 +++ switch/.gitignore | 5 + switch/.secrets.example | 4 + switch/cli/01-vlan-db.cli | 8 + switch/cli/CLI-REFERENCE.md | 47 +++ switch/cli/run-cli.exp | 33 ++ switch/recovery/README.md | 41 +++ switch/recovery/com.bf.switchrecoveryip.plist | 16 + switch/recovery/flash-and-recover.sh | 136 ++++++++ switch/recovery/switch-recovery-ip.sh | 15 + switch/sg8316m-cgi-map.md | 61 ++++ switch/sg8316m.sh | 72 +++++ 25 files changed, 1474 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 docs/core-switch-prep.md create mode 100644 docs/firmware-flash-runbook.md create mode 100644 docs/manual-flash-howto.md create mode 100644 docs/vlan-plan.md create mode 100644 inventory/IPs.xlsx create mode 100644 inventory/README.md create mode 100644 inventory/bf-core-ports.csv create mode 100644 inventory/bf-core-ports.md create mode 100644 inventory/bf.csv create mode 100644 inventory/bf.md create mode 100644 inventory/build.py create mode 100644 omada/docker-compose.yml create mode 100644 switch/.gitignore create mode 100644 switch/.secrets.example create mode 100644 switch/cli/01-vlan-db.cli create mode 100644 switch/cli/CLI-REFERENCE.md create mode 100644 switch/cli/run-cli.exp create mode 100644 switch/recovery/README.md create mode 100644 switch/recovery/com.bf.switchrecoveryip.plist create mode 100644 switch/recovery/flash-and-recover.sh create mode 100644 switch/recovery/switch-recovery-ip.sh create mode 100644 switch/sg8316m-cgi-map.md create mode 100755 switch/sg8316m.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1b27532 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +.secrets diff --git a/README.md b/README.md new file mode 100644 index 0000000..03940e7 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# bf-network-r6 + +BF-Netzwerk-Migration (Variante R6+C2). 2× MikroTik hAP ax² + Core ALL-SG8316M. +Plan-SSOT: ~/.claude/plans/welche-kosteng-nstigen-alternativen-zu-memoized-sparkle.md diff --git a/docs/core-switch-prep.md b/docs/core-switch-prep.md new file mode 100644 index 0000000..a8015bd --- /dev/null +++ b/docs/core-switch-prep.md @@ -0,0 +1,104 @@ +# Core-Switch ALL-SG8316M — Vorbereitung (heute) + Cutover (morgen) + +> Status: **DRAFT** — Port-Map + Subnetze müssen vom User bestätigt werden (markierte `??`). +> Switch: ALLNET ALL-SG8316M, 16× Gigabit, Smart-Managed (Web + SNMP), lüfterlos. + +## 0. Capability-Check (verifiziert) + +Laut Hersteller-Handbuch erfüllt der ALL-SG8316M alle R6-Anforderungen: + +| Anforderung | ALL-SG8316M | Quelle | +|---|---|---| +| IEEE 802.1Q VLAN tagged | ✅ | UM, VLAN-Kapitel | +| Port-Modus **Trunk** (1 untagged + n tagged) | ✅ | UM: "Trunk = untagged member of one VLAN at most, tagged member of zero or more" | +| Port-Modus **Access** (nur untagged) | ✅ | UM | +| Port-Modus **Hybrid** | ✅ | UM | +| PVID je Port (1–4094) | ✅ | UM | +| STP/RSTP, LACP, Port-Mirroring, 802.3x | ✅ | UM | + +→ **Kein Switch-Tausch nötig.** Core bleibt als VLAN-Trunk-Verteiler. + +## 1. VLAN-Schema (User-bestätigt 2026-06-05) + +| VLAN | Zweck | Subnetz | Gateway (hAP #1) | DHCP-Pool | +|---|---|---|---|---| +| **10** | **Server/Main (bestehend, unangetastet)** | **10.40.41.0/24** | .1 (neu, war FB) | #1: .50–.150 / #2: .151–.250 | +| 20 | Docker/Container (`default_internal`-Ziel) | 172.20.0.0/24 | .1 | später (Container-Migration) | +| 30 | IoT | 172.30.0.0/24 | .1 | später (Phase 2) | +| 40 | Guest (*mit Vorbehalt*) | 172.40.0.0/24 | .1 | später (Phase 2) | +| 100 | WAN (→ FB) | FB-Subnetz (z.B. 192.168.178.0/24) | — (DHCP-Client der hAP#1 zur FB) | von FB | +| 1 | **Lifeboat/Default** | nur Switch-Mgmt-Zugang während Transition | — | — | + +**Schlüssel-Vereinfachung:** vlan10 = **das bestehende 10.40.41.0/24**. Geräte behalten ihre IPs; +Cutover = reiner **Gateway-Wechsel** FB→hAP#1, **kein Re-IP**. Switch-Mgmt-IP kann auf 10.40.41.x +bleiben → Lockout-Risiko stark reduziert (Mgmt-VLAN wechselt 1→10, IP-Subnetz bleibt gleich). + +**Gateway-Konvention (User-Entscheid):** **.1 wird Standard** für alle Netze → hAP#1 = **10.40.41.1**. +Heute ist die **FB Gateway/DHCP auf 10.40.41.254** (suboptimal, aber heute unangetastet). Beim Cutover +verlässt die FB das LAN-Subnetz (→ WAN/vlan100), .254 wird frei. Switch-Mgmt = **10.40.41.2** (statisch). + +Phase 1 (morgen) nutzt **nur vlan10 aktiv**; 20/30/40 werden definiert, aber ohne Clients. + +### vlan20 / Docker — eigener Workstream (NICHT Switch-Prep heute) +Die Container (`default_internal` u.a. auf pve/fm) sollen perspektivisch auf 172.20.0.0/24 (vlan20). +Übergangs-**Brücke** nötig, damit Container vorerst unter alten IPs erreichbar bleiben; Migration +schrittweise. → Eigenes Doc/Phase, hier nur vermerkt. Switch muss vlan20 nur **definiert** haben. + +## 2. Port-Map (16 Ports) — DRAFT, vom User zu bestätigen + +| Port | Heute (flach VLAN1) | Ziel (nach Cutover) | Modus Ziel | +|---|---|---|---| +| 1 | FB-Uplink (Gateway) `??` | WAN ↔ FB | **Access untagged vlan100** | +| 2 | — | Trunk ↔ hAP ax² #1 | **Trunk: tagged 10,20,30,40,100** `??` | +| 3 | — | Trunk ↔ hAP ax² #2 | **Trunk: tagged 10,20,30,40** | +| 4–15 | lokale Geräte `??` | lokale Geräte | **Access untagged vlan10** | +| 16 | **Mgmt-Lifeboat** (PC für Switch-Zugang) | Mgmt-Lifeboat | **Access vlan1** bis Mgmt sicher auf vlan10 | + +> ⚠️ **FÜLLE DIESE TABELLE MIT DER ECHTEN BELEGUNG.** Welcher Port = FB? Welche Ports haben kritische Dauer-Geräte (NAS, Drucker, AV)? Das entscheidet, welche Ports beim Cutover umgehängt werden. + +> **Trunk-native-VLAN-Frage:** Auf hAP#1-Trunk liegt zusätzlich das WAN. Sauberste Variante: WAN als **eigenes Tag (vlan100)** auch über den Trunk zu hAP#1 führen statt als native — dann ist auf dem Switch _kein_ Port untagged-WAN nötig und Port 1 (FB) wird Access-untagged-vlan100, der Trunk trägt vlan100 **tagged**. RouterOS macht tagged-WAN problemlos. → Bevorzugt: **Port1 Access-untagged-vlan100 (zur FB), Trunk zu #1 tagged 10,20,30,40,100.** + +## 3. HEUTE — non-disruptive Vorbereitung (Reihenfolge!) + +Alles hier ändert **nichts** am laufenden Flach-Netz (FB bleibt Gateway, alle Live-Ports bleiben VLAN1 untagged). + +1. **Config-Backup ZUERST** — aktuelle Konfig exportieren/sichern (Web-UI → Maintenance/Backup). Datei nach `bf-network-r6/switch/all-sg8316m-backup-PRE.cfg`. +2. **Mgmt-IP dokumentieren** — aktuelle Switch-IP + Login notieren (heute auf FB-Subnetz, z.B. 192.168.178.x). **Nicht ändern** — sonst Zugang weg. +3. **Firmware-Update HEUTE** (User-Entscheid: voll inkl. FW). Aktuelle FW von ALLNET ziehen (Produktseite ALL-SG8316M → Downloads), Version notieren, in ruhigem Zeitfenster flashen. ⚠️ **Reboot = ~1–2 Min Gesamtausfall** fürs BF-Netz → ankündigen. Backup (Schritt 1) MUSS davor liegen. Nach Reboot Config-Integrität prüfen (VLAN-DB ggf. neu anlegen, falls FW Settings resettet). +4. **VLAN-DB anlegen**: VLANs 10, 20, 30, 100 erstellen — **ohne** Port-Membership-Änderungen an Live-Ports. Reines Anlegen im VLAN-Table ist forwarding-neutral, solange alle aktiven Ports untagged member von VLAN1 bleiben. +5. **Leere Trunk-Ports vorkonfigurieren**: Die _für die hAPs vorgesehenen, aktuell unbelegten_ Ports (z.B. 2 & 3) schon auf **Trunk** stellen (tagged 10,20,30,100). Kein Link dran → keine Disruption. Morgen nur noch hAP einstecken. +6. **Physisch vorbereiten**: 2× Cat6e-Trunk-Kabel zu den hAP-Standorten ziehen + Ports labeln (FB / Trunk#1 / Trunk#2 / Lifeboat). +7. **Lifeboat-Port festlegen** (z.B. Port 16, VLAN1) — bleibt während der ganzen Transition als Notzugang zum Switch-Mgmt. + +**Heute NICHT anfassen:** PVID/Membership der Live-Geräte-Ports, FB-Port, Mgmt-IP/Mgmt-VLAN, Global-VLAN-Filtering-Enable falls es Live-Traffic bricht (Verhalten gerätespezifisch → im Backup-Zustand testen). + +## 4. ⚠️ Mgmt-VLAN-Lockout — Gotcha (Cutover-kritisch) + +Entschärft durch vlan10=10.40.41.0/24 (= bestehendes Subnetz): die Mgmt-**IP** muss **nicht** wechseln, +nur die Mgmt-**VLAN-Zuordnung** 1→10. Trotzdem Reihenfolge-kritisch. +**Regel:** Switch-Mgmt **am Cutover** auf **vlan10**, IP bleibt z.B. 10.40.41.2 (statisch, außerhalb DHCP-Pool .50–.250) `??` — und **erst nachdem** Zugang über vlan10 bestätigt ist, den Lifeboat-Port (VLAN1) ziehen. Reset-Button ist die einzige Fallback-Option (kein serieller Konsolen-Port) → langsam & sorgfältig. + +## 5. MORGEN — Cutover-Klickliste (Phase 1, Ziel < 30 Min Ausfall) + +Voraussetzung: hAP #1 & #2 geflasht + Basis-Config (siehe `routeros/`), Technitium läuft (pve+fm). + +1. hAP #1 per Trunk an Switch-Port 2 (schon Trunk-konfiguriert) → Link prüfen. +2. hAP #2 per Trunk an Switch-Port 3 → Link prüfen. +3. **hAP#1 als Gateway**: vlan10-IP = **10.40.41.1**, DHCP-Server an (.50–.150), Option-6 = Technitium (pve+fm). + ⚠️ **Gateway-Migration-Gotcha (.254→.1):** Bestehende Clients haben per alter FB-Lease noch **Gateway .254** — + die FB ist nach Schritt 4 aber weg → Clients tot bis Lease-Renew. **Mitigation:** hAP#1 temporär **2. Adresse + 10.40.41.254/24** geben (Secondary-IP), damit Alt-Lease-Clients weiterrouten; nach Renew aller Leases auf .1 wieder entfernen. + (Alternativ: DHCP-Lease-Time vorher kurz stellen / Clients renewen/rebooten — passt ins 30-Min-Fenster.) +4. **FB umstellen**: FB-DHCP aus, "Exposed Host" → hAP#1-WAN-IP. FB-Port am Switch (Port 1) → **Access untagged vlan100**. FB verlässt damit 10.40.41.0/24 (.254 frei). +5. **Lokale Geräte-Ports** (4–15) → **Access untagged vlan10** (PVID 10). _Disruptiver Moment_ → zügig durchziehen. +6. **Switch-Mgmt** → vlan10, IP **10.40.41.2** statisch. Zugang vom neuen LAN testen, **dann** Lifeboat ziehen. +7. Verifikation: DHCP von hAP#1 (.50–.150), Gateway .1, DNS via Technitium, Internet, CAKE/Bufferbloat-Test, WLAN-Roaming #1↔#2. + +## 6. Offene Punkte (vom User) + +- [x] Subnetz-Schema: vlan10=10.40.41.0/24 (bestehend), 20=172.20/24 (Docker), 30=172.30/24 (IoT), 40=172.40/24 (Guest, Vorbehalt) +- [x] Firmware: heute updaten (User-Entscheid, Reboot akzeptiert) +- [ ] **Echte Port-Belegung** (Tabelle §2 füllen) — v.a. FB-Port + kritische Dauer-Geräte +- [ ] **Switch-Mgmt-Zugang**: aktuelle IP + Login (für Backup/FW/VLAN-Anlage heute) +- [ ] **Zugriffsweg**: Web-UI Klick-für-Klick mit meiner Anleitung (Default für Smart-Switch) — ok? +- [x] **Aktuelles BF-Gateway**: FB = 10.40.41.254 (heute). Künftig Standard **.1** → hAP#1=10.40.41.1. Gateway-Migration-Gotcha in §5 erfasst. diff --git a/docs/firmware-flash-runbook.md b/docs/firmware-flash-runbook.md new file mode 100644 index 0000000..68b43e0 --- /dev/null +++ b/docs/firmware-flash-runbook.md @@ -0,0 +1,84 @@ +# Firmware-Flash ALL-SG8316M (1.0 → 2.2.1) + Plan-B-Recovery + +> ⚠️ Erst ausführen, wenn ALLE Pre-Flight-Punkte erfüllt sind. Flash = Werks-Reset der Config. +> Quelle Defaults: ALLNET QIG. Annahme: Flash setzt Switch auf Werk → **192.168.1.1 / admin / admin**. + +## Werks-Defaults (Recovery-Anker) +| | | +|---|---| +| Default-IP nach Flash | **192.168.1.1** /24 | +| Default-Login | **admin / admin** | +| FW-Image | `switch/firmware/2.2.1/all-sg8316m-version_2.2.1_vmlinux.bix` (5,1 MB) | +| Aktuell (PRE) | IP 10.40.41.239, FW 1.0, nur VLAN1, Ports Hybrid/PVID1 | + +## Warum „du bist dann auch offline" +Claude erreicht den Switch über **10.40.41.239**. Nach dem Flash lebt er auf **192.168.1.1** in einem +anderen Subnetz → für Claude nicht mehr erreichbar, **bis** jemand physisch eine Verbindung ins +192.168.1.x-Netz herstellt. **Recovery ist daher bewusst menschen-ausführbar** (GUI), Skript optional danach. + +## Pre-Flight-Checkliste (HARTE Voraussetzungen) +- [ ] **Physisch am Switch** (Reset-Knopf erreichbar, Konsole-Zugang am Standort). +- [ ] **Direkt angestöpselter Laptop** an einem Switch-Port (nicht über WLAN/Remote). +- [ ] Laptop kann **Zweit-IP `192.168.1.2/24`** setzen (macOS: `sudo ifconfig en0 alias 192.168.1.2 255.255.255.0`). +- [ ] **Stabile Stromversorgung** des Switches (idealerweise USV) — Stromausfall **während** des Flashs = Brick-Risiko #1. +- [ ] FW-Image lokal vorhanden ✅ + Hash notiert (s.u.). +- [ ] PRE-Scrape vorhanden ✅ (`switch/state-PRE/`) → Soll-Config bekannt. +- [ ] Recovery-Skript bereit: `sg8316m.sh` kann Mgmt-IP zurücksetzen + VLANs/Ports anlegen (set_ip/add_vlans/…). +- [ ] **Zeitfenster** angekündigt: BF-LAN droppt ~1–2 Min beim Reboot; Re-Config danach wenige Min. +- [ ] Mentaler Worst-Case akzeptiert: €~96-Switch, im äußersten Notfall Ersatz. + +## Flash-Durchführung (GUI empfohlen — sichtbarer Fortschritt) +1. Browser auf `http://10.40.41.239` → **Maintenance → Upgrade Manager** (cmd=4363). +2. Upgrade Method = **HTTP**, Upgrade Type = **Image**, Datei = `…2.2.1_vmlinux.bix` → **Upgrade**. +3. **NICHT** Strom/Netz trennen, bis der Switch von selbst neu startet. Geduld (mehrere Minuten). + - Scripted-Alternative (nur wenn bewusst gewählt): + `curl -F "type=0" -F "http_file=@switch/firmware/2.2.1/all-sg8316m-version_2.2.1_vmlinux.bix" -F "cmd=4364" http://10.40.41.239/cgi-bin/httpupload.cgi` + +## Post-Flash — erwarteter Zustand +- Switch auf **192.168.1.1**, Login **admin/admin**, **leere Config** (nur VLAN1, Ports default). +- 10.40.41.239 weg (erwartet, kein Fehler). + +## Recovery-Szenarien + +### A) Normalfall: Flash OK, Switch auf 192.168.1.1 (= erwartet) — RECOVERY ÜBER MAC MINI +Voraussetzung: Mac mini trägt Zweit-IP **192.168.1.2/24** auf en0 (L2-benachbart, verifiziert). +Siehe `switch/recovery/README.md`. Claude führt **vom Mac mini aus** (per SSH-Tunnel) aus — **kein** +manuelles IP-Suchen, kein Laptop: +``` +ssh 10.40.41.167 "curl -sS -X POST \ + --data mode=0 --data ip=10.40.41.239 --data netmask=255.255.255.0 \ + --data gateway=10.40.41.254 --data cmd=518 \ + http://192.168.1.1/cgi-bin/dispatcher.cgi" +``` +Danach Switch wieder auf .239 → Claude fährt VLANs/Ports/Mgmt-VLAN auf + `save`. +(Repo muss dafür NICHT auf dem Mac mini liegen — der curl-Einzeiler reicht via SSH.) + +### B) Switch reagiert NICHT auf 192.168.1.1 (Loader/Recovery) +1. **30 Sek warten**, erneut pingen (Boot dauert). +2. **Factory-Reset-Knopf** ~10 Sek halten → erneut 192.168.1.1 prüfen. +3. Manche Realtek-Loader haben **TFTP-Recovery**: PC auf feste IP, TFTP-Server mit dem Image bereithalten, + Switch beim Boot ziehen lassen. (Für SG8316M nicht dokumentiert → nur als letzter Versuch; Setup s.u.) +4. Wenn weiterhin tot → Hardware-Defekt, Ersatz. + +### C) Flash bricht mit Fehler ab, Switch noch auf 10.40.41.239 / FW 1.0 +- Kein Reboot passiert → alte FW läuft weiter. Image-Datei/Hash prüfen, ggf. erneut versuchen oder abbrechen. + +## TFTP-Recovery vorbereiten (optional, für Szenario B) +- macOS hat `launchctl`-tftpd, oder `dnsmasq --enable-tftp`. Image in TFTP-Root legen. +- **Nur** relevant, wenn der Loader es unterstützt — vorher recherchieren, nicht blind versuchen. + +## Image-Integrität +- SHA256 (verifiziert 2026-06-05): + `e3f160983e8b17962dc70a52360b7f560c92da8197928d702f5266027a0fc7fc` +- Vor Flash erneut prüfen: `shasum -a 256 switch/firmware/2.2.1/all-sg8316m-version_2.2.1_vmlinux.bix` + +## Recovery-Skript (Felder verifiziert) +- IP setzen (cmd=518): `POST mode=0 ip= netmask= gateway= cmd=518` → in `sg8316m.sh set-ip`. +- Schnell-Recovery nach Flash: + `SW_HOST=192.168.1.1 SW_USER=admin SW_PASS=admin ./sg8316m.sh set-ip 10.40.41.239` + danach `.secrets` zurück auf .239, dann `add-vlans 10,20,30,40,100` + Port-Config + `save`. + +## Abbruch-Kriterien (lieber nicht flashen) +- Kein physischer Zugang ODER kein direkt-gekabelter Laptop → **verschieben**. +- Switch an instabilem Strom (kein USV, Gewitter, Bauarbeiten) → **verschieben**. +- Kein Zeitpuffer für ~15–30 Min Bastel-Risiko → **verschieben**. diff --git a/docs/manual-flash-howto.md b/docs/manual-flash-howto.md new file mode 100644 index 0000000..2ff04dd --- /dev/null +++ b/docs/manual-flash-howto.md @@ -0,0 +1,35 @@ +# Manuelles Firmware-Update ALL-SG8316M (1.0 → 2.2.1) via GUI + +Ausgangslage: Switch sauber auf FW 1.0 @ 10.40.41.239 (scripted Versuch hat nur den Auto-Reboot +verpasst — Image-Write wird in der GUI vom Browser-JS korrekt zu Ende geführt inkl. Reboot). + +## 1. Firmware holen +- Download (ZIP): https://www.allnet.de/ftp-downloads/allnet/switches/all-sg8316m/all-sg8316m-version_2.2.1.zip +- Entpacken → Datei **`all-sg8316m-version_2.2.1_vmlinux.bix`** (5,1 MB) +- SHA256 (optional prüfen): `e3f160983e8b17962dc70a52360b7f560c92da8197928d702f5266027a0fc7fc` +- (Liegt auch schon auf dem Mac mini: `~/bf-switch-flash/all-sg8316m-version_2.2.1_vmlinux.bix`) + +## 2. Flashen +1. Browser → `http://10.40.41.239` (ggf. Login). +2. Menü **Maintenance → Upgrade Manager**. +3. **Upgrade Method = HTTP**, **Upgrade Type = Image**, Datei = die `.bix`. +4. **Upgrade** klicken. +5. Seite zeigt **„Writing image to FLASH… Do not power down…"** → **Strom NICHT trennen, warten**. + Der Browser pollt selbst und reboot­et danach. +6. Falls die Seite „fertig" zeigt **ohne** Reboot → oben **REBOOT** klicken. + +## 3. Nach dem Reboot (~1–2 min) +Switch kommt vermutlich auf **Werks-Default** hoch: +- IP **192.168.1.1**, Login **admin / admin** +1. Falls nicht erreichbar: Notebook-NIC temporär auf `192.168.1.50 /24` setzen (oder Mac mini, hat schon `192.168.1.2`). +2. Browser `http://192.168.1.1`, admin/admin. +3. **Network → IP Address**: Static, IP `10.40.41.239`, Maske `255.255.255.0`, Gateway `10.40.41.254` → Apply. +4. **SAVE → Save Configuration to FLASH → Apply** (damit es den nächsten Reboot übersteht!). + +## 4. Fertig +- Prüfen: System Information zeigt **Firmware Version 2.2.1**. +- Mir „durch" sagen → ich verifiziere + übernehme (Mac-mini-Alias `192.168.1.2` ist noch aktiv). + +## Hinweise +- Kommt der Switch auf `.239` statt `192.168.1.1` zurück (FW bewahrt IP) → Schritt 3 entfällt, nur prüfen + Save. +- Reagiert er gar nicht: 30 s warten, dann Reset-Knopf 10 s → wieder `192.168.1.1`. diff --git a/docs/vlan-plan.md b/docs/vlan-plan.md new file mode 100644 index 0000000..f86dc40 --- /dev/null +++ b/docs/vlan-plan.md @@ -0,0 +1,44 @@ +# BF — VLAN- & Adressplan (final, 2026-06-06) + +## VLAN-Modell +| VLAN | Name | Subnetz (Ziel) | Interim | Zweck | +|---|---|---|---|---| +| 10 | **MAIN** | 10.40.10.0/24 | **vorerst 10.40.41.0/24** | Trusted-Clients + Media (Sonos/AppleTV/TV/SAT/Drucker) | +| 20 | **INFRA** | 10.40.20.0/24 | **vorerst vorhandene 172.x** | Server, VMs, Docker, NAS-Workloads, HA | +| 30 | **IOT** | 10.40.30.0/24 | — | Smart-Home (HA-managed) | +| 40 | **UNTRUSTED** | 10.40.40.0/24 | — | Spielekonsole & Low-Trust-Internet | +| 90 | **GUEST** | 10.40.90.0/24 | — | nur Internet (abgesetzt; 50–89 frei für künftige VLANs) | +| 99 | **MGMT** | 10.40.99.0/24 | Switch vorerst 10.40.41.239 | Switch/AP/Hypervisor-Mgmt-Interfaces | +| 100 | **WAN** | (FB-Transfer) | — | zur Fritzbox | + +**Konventionen:** Gateway je VLAN = `.1` (hAP#1). Switch-Mgmt = `10.40.99.2`. 3. Oktet = VLAN-ID (Mnemonik). Alles RFC1918 (10/8). + +## Firewall — Least-Privilege (nicht „Main→alle") +- Default **deny** inter-VLAN, dann gezielt erlauben. +- **Main → Infra:** nur Whitelist-Dienste (NAS-Shares, HA-UI, Proxmox-UI auf definierten Ports). Kein Vollzugriff. +- **Infra → Main:** grundsätzlich deny (Ausnahmen: Backups/Notifications gezielt). +- **IoT / Guest / Untrusted → intern:** deny — nur Internet. +- **Mgmt (99):** aus Main nicht erreichbar; nur dedizierter Admin-Zugang. + +## Discovery / Usability (Sonos & Co.) +- mDNS/SSDP queren VLANs **nicht** von allein → discovery-abhängige Media-Geräte (Sonos, AppleTV, AirPrint, TV/SAT) + liegen bewusst **auf MAIN** mit den steuernden Handys → funktioniert ohne Reflector. +- Nicht-Discovery-Zugriff (NAS-UI, HA-Web) aus Main: per Firewall-Regel + DNS/Hostname, kein mDNS nötig. +- Most-IoT-Steuerung läuft eh **Handy → HA → IoT** → IoT (30) kann hart dichtgemacht werden. + +## Geräte-Einordnung +| Gerät | VLAN | +|---|---| +| Handy, Laptop (du) | 10 MAIN | +| Sonos, AppleTV, Smart-TV, SAT-Receiver, Drucker | 10 MAIN (Discovery) | +| Sensoren/Plugs/Kameras/Smart-Home | 30 IOT | +| Spielekonsole | 40 UNTRUSTED | +| NAS, Proxmox-VMs, Docker, HA | 20 INFRA | +| Netz-Mgmt (sw1, hAPs, Hypervisor-Mgmt) | 99 MGMT | + +## Migrations-Notizen +- **MAIN-Re-IP** 10.40.41 → 10.40.10: groß (DHCP/Statics/Referenzen) → später, geplant. +- **INFRA**: erst vorhandene 172er weiterfahren, dann behutsam auf 10.40.20.0/24. +- **NAS .10**: bleibt vorerst auf 10.40.41.10/MAIN; Umzug nach INFRA später. +- **VPNchristoph**: muss von `.1` weg (wird Gateway); IP egal. +- **Switch-Mgmt**: heute 10.40.41.239; nach Cutover → vlan99 / 10.40.99.2 (`management-vlan vlan 99` + `ip address`). diff --git a/inventory/IPs.xlsx b/inventory/IPs.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..51c5b4b2d97afdb22fb533164f266a54ed13e8f1 GIT binary patch literal 41482 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 Ist-Belegung. Ports 4/8/15/16 **behalten** (4+8 interim bis neue Switches produktiv). +> Übrige Ports (1–3, 5–7, 9–14): noch nicht erfasst — gemeinsam ergänzen. + +| port | ist | downstream | behalten | soll | notiz | +|---|---|---|---|---|---| +| 4 | Uplink Wohnzimmer-Switch (smart managed) | | bis neue Switches produktiv | neues Gerät | interim — wird ersetzt | +| 8 | Uplink Arbeitszimmer-Switch (smart managed) | 10.40.41.10; 10.40.41.167; 10.40.41.247 | bis neue Switches produktiv | neues Gerät | interim — wird ersetzt | +| 15 | pve | | ja | beibehalten | | +| 16 | Fritzbox (WAN/Gateway) | 10.40.41.246 (FB LAN4) | ja | beibehalten | FB bleibt Modem+Telefon | diff --git a/inventory/bf.csv b/inventory/bf.csv new file mode 100644 index 0000000..2921516 --- /dev/null +++ b/inventory/bf.csv @@ -0,0 +1,254 @@ +section,ip,hostname,mac,pve_ct,server_ip,server_mac,note +VPN,10.40.41.1,VPNchristoph,,,,,Fallback bis CF One überall läuft; IP umziehbar/unwichtig +VPN,10.40.41.3,,,,,, +"srv, infra",10.40.41.4,MFC,30:5:5c:78:86:20,,,, +"srv, infra",10.40.41.5,P750W,4C:EB:BD:E3:25:F2,,,,Brother PT-P750W Printer +"srv, infra",10.40.41.6,iHost,D0:27:03:C8:CB:36,,,, +"srv, infra",10.40.41.7,odroid-m1,00:1E:06:51:31:C9,,,, +"srv, infra",10.40.41.8,DTUBI-414392337823,54:F2:9F:12:51:F0,,,, +"srv, infra",10.40.41.9,,,,,, +"srv, infra",10.40.41.10,nas-bf,90:9:d0:58:20:f9,,,, +"srv, infra",10.40.41.11,tv,70:AF:24:B8:C9:86,,,, +"srv, infra",10.40.41.12,virtualdsm,,,,, +"srv, infra",10.40.41.13,sysrecue,,,,, +"srv, infra",10.40.41.14,AppleTV,,,,, +"srv, infra",10.40.41.15,,,,,,docker:synology +docker,10.40.41.16,pve:docker:adguard_bf1,BC:24:11:10:3A:98,130,,,dzt kein default_internal (wird je site mit 1 vlan konsolidiert; in bf übergreifendpve-ds923) +docker,10.40.41.17,pve:docker:adguard_fm1,,,,,dzt kein default_internal (wird je site mit 1 vlan konsolidiert; in bf übergreifendpve-ds923) +docker,10.40.41.18,pve:docker:adguard_dw1,,,,,dzt kein default_internal (wird je site mit 1 vlan konsolidiert; in bf übergreifendpve-ds923) +docker,10.40.41.19,docker:iob_exposed,BC:24:11:E4:DC:AB,150,172.16.0.150,BC:24:11:3A:62:43, +docker,10.40.41.20,docker-fm:nginx-proxy-manager,,,,, +docker,10.40.41.21,docker:ldapsyno,,,,, +docker,10.40.41.22,docker:ccu,,,,, +docker,10.40.41.23,docker:pihole_dw1,02:42:0A:28:29:17,,,, +docker,10.40.41.24,docker:,,,,, +docker,10.40.41.25,docker:,,,,, +docker,10.40.41.26,docker:,,,,, +docker,10.40.41.27,docker:,,,,, +docker,10.40.41.28,docker:,,,,, +docker,10.40.41.29,docker:,,,,, +docker,10.40.41.30,docker:cloudflared,,,,, +docker,10.40.41.31,docker:,,,,, +docker,10.40.41.32,res docker2bf,,,,, +docker,10.40.41.33,docker_ds923+:iob_slave,,,,, +docker,10.40.41.34,res docker2bf,,,,, +docker,10.40.41.35,res docker2bf,,,,, +docker,10.40.41.36,res docker2bf,,,,, +docker,10.40.41.37,res docker2bf,,,,, +docker,10.40.41.38,res docker2bf,,,,, +docker,10.40.41.39,res docker2bf,,,,, +docker,10.40.41.40,res docker2bf,,,,, +docker,10.40.41.41,res docker2bf,,,,, +docker,10.40.41.42,res docker2bf,,,,, +docker,10.40.41.43,res docker2bf,,,,, +docker,10.40.41.44,res docker2bf,,,,, +docker,10.40.41.45,res docker2bf,,,,, +docker,10.40.41.46,res docker2bf,,,,, +docker,10.40.41.47,res docker2bf,,,,, +DHCP (reservations),10.40.41.48,ds415+,00:11:32:4F:E2:12,,,, +DHCP (reservations),10.40.41.49,ds415play,00:11:32:4C:72:7E,,,, +DHCP (reservations),10.40.41.50,win11enterprise,02:11:32:2f:1f:cc,,,, +DHCP (reservations),10.40.41.51,ds207,00:11:32:04:57:66,,,, +DHCP (reservations),10.40.41.52,,,,,, +DHCP (reservations),10.40.41.53,,,,,, +DHCP (reservations),10.40.41.54,vuplus,,,,, +DHCP (reservations),10.40.41.55,AppleTV,,,,, +DHCP (reservations),10.40.41.56,,,,,, +DHCP (reservations),10.40.41.57,,,,,, +DHCP (reservations),10.40.41.58,,,,,, +DHCP (reservations),10.40.41.59,MobilMarven,,,,, +DHCP (reservations),10.40.41.60,MobilGeli,8c:b8:4a:56:d0:0b,,,,Note10+ +DHCP (reservations),10.40.41.61,MobilChristoph,08:C7:B5:91:BA:61,,,,"S22 / dhcp-host=08:C7:B5:91:BA:61,10.40.41.33,MobilChristoph" +DHCP (reservations),10.40.41.62,MobilChristophAlt,7C:D6:61:B7:93:99,,,,"dhcp-host=7C:D6:61:B7:93:99,10.40.41.31,MobilChristophAlt" +DHCP (reservations),10.40.41.63,MobilSara,4A:11:58:B5:15:E1,,,,"A34 / dhcp-host=4A:11:58:B5:15:E1,10.40.41.26,MobilSara" +DHCP (reservations),10.40.41.64,MobilTanja,44:16:FA:CE:27:D3,,,,"dhcp-host=44:16:FA:CE:27:D3,10.40.41.30,MobilTanja" +DHCP (reservations),10.40.41.65,MobilChristophA35,B0:54:76:46:BC:1C,,,,A35 +DHCP (reservations),10.40.41.66,MobilOma,DE:44:85:63:51:4A,,,,"dhcp-host=DE:44:85:63:51:4A,10.40.41.29,MobilOma" +DHCP (reservations),10.40.41.67,MobilOpa,02:8C:4F:B8:FC:8E,,,,"dhcp-host=02:8C:4F:B8:FC:8E,10.40.41.28,MobilOpa" +DHCP (reservations),10.40.41.68,,,,,, +DHCP (reservations),10.40.41.69,iPadChristoph,34:2B:6E:6F:1F:EF,,,, +DHCP (reservations),10.40.41.70,,,,,, +DHCP (reservations),10.40.41.71,wwan,3C:B2:33:ED:FC:03,,,, +DHCP (reservations),10.40.41.72,,,,,, +DHCP (reservations),10.40.41.73,Forerunner965,38:F9:F5:8F:CC:69,,,, +DHCP (reservations),10.40.41.74,iHostWIFI,,,,, +DHCP (reservations),10.40.41.75,KindleVoyage,00:BB:3A:2C:0E:E6,,,,"dhcp-host=00:BB:3A:2C:0E:E6,10.40.41.39,KindleVoyage" +DHCP (reservations),10.40.41.76,SmartwatchChristoph935,14:8F:21:E7:45:2C,,,,"dhcp-host=14:8F:21:E7:45:2C,10.40.41.40,SmartwatchChristoph935" +DHCP (reservations),10.40.41.77,SmartwatchChristoph945,B4:C2:6A:57:0B:BB,,,,"dhcp-host=B4:C2:6A:57:0B:BB,10.40.41.41,SmartwatchChristoph945" +DHCP (reservations),10.40.41.78,Garmin Edge 820,14:8F:21:CB:BC:EA,,,,"dhcp-host=14:8F:21:CB:BC:EA,10.40.41.217,GarminEdge820" +DHCP (reservations),10.40.41.79,ubuntu-desktop,02:11:32:2c:3c:b1,,,, +DHCP (reservations),10.40.41.80,,,,,, +DHCP (reservations),10.40.41.81,MacBook LAN,B8:B4:09:1A:EC:AB,,,,"dhcp-host=B8:B4:09:1A:EC:AB,10.40.41.23,MacBookLAN" +DHCP (reservations),10.40.41.82,MacBook WLAN,3c:a6:f6:02:3e:83,,,,"dhcp-host=3c:a6:f6:02:3e:83,10.40.41.24,MacBookWLAN" +DHCP (reservations),10.40.41.83,KindleTanja,a0:02:dc:5d:5d:d2,,,, +DHCP (reservations),10.40.41.84,,,,,, +DHCP (reservations),10.40.41.85,iPadTanja,EC:73:79:C0:66:E7,,,,"dhcp-host=EC:73:79:C0:66:E7,10.40.41.35,iPadTanja" +DHCP (reservations),10.40.41.86,TvSara (zauberkatze),CC:4B:73:75:7C:4A,,,,"dhcp-host=CC:4B:73:75:7C:4A,10.40.41.43,TvSara(zauberkatze)" +DHCP (reservations),10.40.41.87,NotebookSara_alt (galadriel),00:E1:8C:9B:27:BA,,,, +DHCP (reservations),10.40.41.88,NotebookSara (celeborn),,,,, +DHCP (reservations),10.40.41.89,NotebookOpa (pluto),08:71:90:EA:0A:56,,,,"dhcp-host=08:71:90:EA:0A:56,10.40.41.44,NotebookOpa(pluto)" +DHCP (reservations),10.40.41.90,,,,,, +DHCP (reservations),10.40.41.91,,,,,, +DHCP (reservations),10.40.41.92,NintendoSwitchLAN,00:23:55:0C:86:59,,,, +DHCP (reservations),10.40.41.93,NintendoSwitchWLAN,94:58:CB:B1:63:BC,,,, +DHCP (reservations),10.40.41.94,EOS6Rm2,A0:CD:F3:93:FF:E4,,,, +DHCP (reservations),10.40.41.95,,,,,, +DHCP (reservations),10.40.41.96,,,,,, +DHCP (reservations),10.40.41.97,,,,,, +DHCP (reservations),10.40.41.98,,,,,, +DHCP (reservations),10.40.41.99,,,,,, +DHCP (reservations),10.40.41.100,pve,00:D0:B4:04:19:24,,,, +DHCP (reservations),10.40.41.101,ubuntu-server,02:11:32:24:3D:EC,,,, +DHCP (reservations),10.40.41.102,ubuntu-desktop,02:11:32:2b:b6:08,,,, +DHCP (reservations),10.40.41.103,airfryer,E4:BC:96:1F:B2:81,,,, +DHCP (reservations),10.40.41.104,,,,,, +DHCP (reservations),10.40.41.105,pve:homeassistant,BC:24:11:11:A9:B3,100,172.16.0.18,BC:24:11:1E:12:19, +DHCP (reservations),10.40.41.106,z2m25,BC:24:11:A2:B5:0F,112,172.16.0.12,BC:24:11:F3:42:01, +DHCP (reservations),10.40.41.107,iob_master,BC:24:11:4D:26:96,101,172.16.0.19,BC:24:11:B4:3E:41,172.24.0.19 / BC:24:11:6F:9A:86 +DHCP (reservations),10.40.41.108,mqtt5,BC:24:11:B0:46:53,102,172.16.0.10,BC:24:11:53:DA:7D, +DHCP (reservations),10.40.41.109,grafana,BC:24:11:8A:4D:F1,104,172.16.0.9,BC:24:11:D9:A4:AC, +DHCP (reservations),10.40.41.110,SONOFF-NSPanelPro,7C:88:99:06:07:EC,,,, +DHCP (reservations),10.40.41.111,redis,BC:24:11:41:CA:A1,107,172.16.0.7,BC:24:11:5F:6B:EE,172.24.0.7 / BC:24:11:C0:35:39 +DHCP (reservations),10.40.41.112,,,,,, +DHCP (reservations),10.40.41.113,pve:influxdb2,BC:24:11:9A:F2:5E,106,172.16.0.8,, +DHCP (reservations),10.40.41.114,minarca,BC:24:11:3C:E2:3E,103,,, +DHCP (reservations),10.40.41.115,,,,,, +DHCP (reservations),10.40.41.116,adguard-bf1,BC:24:11:B3:FC:52,120,,, +DHCP (reservations),10.40.41.117,adguard-bf2,BC:24:11:69:61:69,121,,, +DHCP (reservations),10.40.41.118,caddy,BC:24:11:3D:5A:5A,129,172.16.0.118,BC:24:11:A7:C9:6F, +DHCP (reservations),10.40.41.119,node-red,BC:24:11:0D:0C:FE,109,,, +DHCP (reservations),10.40.41.120,openproject,BC:24:11:94:83:5C,201,,, +DHCP (reservations),10.40.41.121,vaultwarden,BC:24:11:5A:DC:A0,301,172.18.0.127,BC:24:11:17:CA:26, +DHCP (reservations),10.40.41.122,mariadb,BC:24:11:52:78:0D,302,172.16.0.23,BC:24:11:B4:09:E4, +DHCP (reservations),10.40.41.123,nginx,BC:24:11:CC:13:0B,128,,BC:24:11:7D:DD:F1, +DHCP (reservations),10.40.41.124,pve:docker:hms-mqtt,,,,, +DHCP (reservations),10.40.41.125,docker_ds923+:openspeedtest,,,,, +DHCP (reservations),10.40.41.126,pve:docker,BC:24:11:C2:72:A2,400,172.16.0.126,BC:24:11:62:69:D7, +DHCP (reservations),10.40.41.127,docker:vaultwarden,,,172.16.0.127,, +DHCP (reservations),10.40.41.128,pve:docker:portainer,,,172.18.0.2,, +DHCP (reservations),10.40.41.129,pve:ollama,BC:24:11:2C:B8:0F,170,172.16.0.129,BC:24:11:E7:42:55, +DHCP (reservations),10.40.41.130,docker_ds923+:openclaw,,,172.18.0.130,, +DHCP (reservations),10.40.41.131,pihole2,BC:24:11:5B:FF:8A,131,172.16.0.131,BC:24:11:4F:9F:81, +DHCP (reservations),10.40.41.132,docker_ds923+:openclaw_cloudflared,,,,, +DHCP (reservations),10.40.41.133,ds923+:coolify,,,,, +DHCP (reservations),10.40.41.134,,,,,, +DHCP (reservations),10.40.41.135,synodocker:pbs,02:11:32:2e:15:25,,172.16.0.135,02:11:32:21:b6:4a, +DHCP (reservations),10.40.41.136,,,,,, +DHCP (reservations),10.40.41.137,Dongle-M-10E8,94:54:C5:28:10:EB,,,, +DHCP (reservations),10.40.41.138,Dongle-M-10E8_wifi,94:54:C5:28:10:E8,,,, +DHCP (reservations),10.40.41.139,drawio,,,,, +DHCP (reservations),10.40.41.140,,,,,, +DHCP (reservations),10.40.41.141,wmbusmeters,BC:24:11:25:1E:DE,,,, +DHCP (reservations),10.40.41.142,,,,,, +DHCP (reservations),10.40.41.143,openclawnginx2_dummy,,,,, +DHCP (reservations),10.40.41.144,openclaw2,,,,, +DHCP (reservations),10.40.41.145,pve:docker:cloudflared,,,,, +DHCP (reservations),10.40.41.146,ollama,,,,, +DHCP (reservations),10.40.41.147,n8n,,,,,johnny claw +DHCP (reservations),10.40.41.148,docker_ds923+:nginx,,,,,johnny claw +DHCP (reservations),10.40.41.149,gitea,,,,, +DHCP (reservations),10.40.41.150,Ender3V3KE-3226,FC:EE:11:03:32:26,,,, +DHCP (reservations),10.40.41.151,prometheus,,,,, +DHCP (reservations),10.40.41.152,mcp,,,,, +DHCP (reservations),10.40.41.153,alertmanager,,,,, +DHCP (reservations),10.40.41.154,node-exporter,,,,, +DHCP (reservations),10.40.41.155,,,,,, +DHCP (reservations),10.40.41.156,,,,,, +DHCP (reservations),10.40.41.157,,,,,, +DHCP (reservations),10.40.41.158,,,,,, +DHCP (reservations),10.40.41.159,openclaw-oc-qdrant-central,,,,, +DHCP (reservations),10.40.41.160,openclaw,,,,, +DHCP (reservations),10.40.41.161,openclaw-johnny2,,,,, +DHCP (reservations),10.40.41.162,openclaw-tzcharlie,,,,, +DHCP (reservations),10.40.41.163,,,,,, +DHCP (reservations),10.40.41.164,oc-jonny2-redis,,,172.18.0.164,, +DHCP (reservations),10.40.41.165,oc-charlie-redis,,,172.18.0.165,, +DHCP (reservations),10.40.41.166,,,,,, +DHCP (reservations),10.40.41.167,macmini-LAN,d0:11:e5:b9:a7:48,,,, +DHCP (reservations),10.40.41.168,macmini-WLAN,d0:11:e5:c9:08:0a,,,, +DHCP (reservations),10.40.41.169,macmini-cloudflared,,,,, +DHCP (reservations),10.40.41.170,ms365-mcp,,,,, +DHCP (reservations),10.40.41.171,hostinger-mcp,,,,, +DHCP (reservations),10.40.41.172,woocommerce-mcp,,,,, +DHCP (reservations),10.40.41.173,billbee-mcp,,,,, +DHCP (reservations),10.40.41.174,sevdesk-mcp,,,,, +DHCP (reservations),10.40.41.175,wordpress-mcp,,,,, +DHCP (reservations),10.40.41.176,,,,,, +DHCP (reservations),10.40.41.177,,,,,, +DHCP (reservations),10.40.41.178,,,,,, +DHCP (reservations),10.40.41.179,,,,,, +DHCP (reservations),10.40.41.180,,,,,, +DHCP (reservations),10.40.41.181,,,,,, +DHCP (reservations),10.40.41.182,,,,,, +DHCP (reservations),10.40.41.183,,,,,, +DHCP (reservations),10.40.41.184,,,,,, +DHCP (reservations),10.40.41.185,,,,,, +DHCP (reservations),10.40.41.186,,,,,, +DHCP (reservations),10.40.41.187,,,,,, +DHCP (reservations),10.40.41.188,,,,,, +DHCP (reservations),10.40.41.189,,,,,, +DHCP (reservations),10.40.41.190,,,,,, +Sonos,10.40.41.191,SonosArbeitszimmer1,34:7e:5c:32:37:96,,,,"dhcp-host=34:7e:5c:32:37:96,10.40.41.191,SonosArbeitszimmer1" +Sonos,10.40.41.192,SonosArbeitszimmer2,34:7e:5c:32:33:b8,,,,"dhcp-host=34:7e:5c:32:33:b8,10.40.41.192,SonosArbeitszimmer2" +Sonos,10.40.41.193,SonosSchlafzimmer1,78:28:ca:80:2a:f6,,,,"dhcp-host=78:28:ca:80:2a:f6,10.40.41.193,SonosSchlafzimmer1" +Sonos,10.40.41.194,SonosSchlafzimmer2,48:a6:b8:14:fe:d0,,,,"dhcp-host=48:a6:b8:14:fe:d0,10.40.41.194,SonosSchlafzimmer2" +Sonos,10.40.41.195,SonosBad,48:A6:B8:14:FE:D0,,,,"dhcp-host=48:A6:B8:14:FE:D0,10.40.41.195,SonosBad" +Sonos,10.40.41.196,SonosKinderzimmer,48:A6:B8:16:38:AE,,,,"dhcp-host=48:A6:B8:16:38:AE,10.40.41.196,SonosKinderzimmer" +Sonos,10.40.41.197,SonosKueche,48:A6:B8:14:FE:F2,,,,"dhcp-host=48:A6:B8:14:FE:F2,10.40.41.197,SonosKueche" +Sonos,10.40.41.198,SonosTerrasse,48:a6:b8:16:38:ae,,,,"dhcp-host=48:a6:b8:16:38:ae,10.40.41.198,SonosTerrasse" +Sonos,10.40.41.199,SonosWohnzimmer1,48:A6:B8:0B:63:10,,,,"48:A6:B8:01:13:EE / dhcp-host=48:A6:B8:0B:63:10,10.40.41.199,SonosWohnzimmer1" +Sonos,10.40.41.200,SonosWohnzimmer2,48:a6:b8:14:fe:f2,,,,"dhcp-host=48:a6:b8:14:fe:f2,10.40.41.200,SonosWohnzimmer2" +Sonos,10.40.41.201,SonosWohnzimmer3,78:28:ca:d2:0d:ac,,,,"dhcp-host=78:28:ca:d2:0d:ac,10.40.41.201,SonosWohnzimmer3" +Sonos,10.40.41.202,shelly: s22,a0:85:e3:c8:65:34,,,,kueche_steckdose3-2 +Sonos,10.40.41.203,shelly: s23,ac:15:18:7b:62:20,,,,dieleug-wohnzimmer_licht +Sonos,10.40.41.204,shelly: s24,,,,,bad_spielgelschrank +Sonos,10.40.41.205,shelly: s25,98:a3:16:79:38:50,,,,bad_lichtschalter +IOT,10.40.41.206,shelly: s20,98:a3:16:7c:5f:ec,,,,kueche_steckdosen2 +IOT,10.40.41.207,shelly: s21,20:6e:f1:01:f9:f8,,,,kueche_steckdosen4 +IOT,10.40.41.208,shelly: s1,E4:B0:63:D7:C7:A4,,,,weihnachten_kueche +IOT,10.40.41.209,shelly: s2,28:37:2F:36:F4:7C,,,,weihnachten_terrasse +IOT,10.40.41.210,shelly: s3,E4:B0:63:E4:EF:7C,,,,weihnachten_kinderzimmer +IOT,10.40.41.211,shelly: s4,E4:B0:63:E4:0F:30,,,,kueche_mikrowelle +IOT,10.40.41.212,shelly: s5,D8:85:AC:0C:5C:C8,,,,kueche_backofen +IOT,10.40.41.213,shelly: s6,0c:72:74:36:90:9e,,,,kueche_kuehlschrank +IOT,10.40.41.214,shelly: s7,D0:CF:13:D9:94:E8,,,,kueche_tiefkuehlschrank +IOT,10.40.41.215,shelly: s8,E4:B0:63:FA:FD:E0,,,,kueche_geschirrspueler +IOT,10.40.41.216,shelly: s9,E8:F6:0A:61:88:08,,,,wohnzimmer_sideboard +IOT,10.40.41.217,shelly: s10,E4:B0:63:FC:57:E4,,,,bad_sonos +IOT,10.40.41.218,shelly: s11,E4:B0:63:FA:6C:00,,,,kinderzimmer_sonos +IOT,10.40.41.219,shelly: s12,48:f6:ee:c8:e6:ac,,,,dieleug_steckdosen +IOT,10.40.41.220,shelly: s13,48:F6:EE:DD:6A:F4,,,,arbeitszimmer_technik +IOT,10.40.41.221,shelly: s14,E4:B0:63:FC:59:48,,,,schlafzimmer_bett +IOT,10.40.41.222,shelly: s15,E4:B0:63:FA:D5:34,,,,technik_pve +IOT,10.40.41.223,shelly: s16,10:20:ba:fa:f5:40,,,,wohnzimmer_steckdosen +IOT,10.40.41.224,shelly: s17,10:20:ba:fb:6d:64,,,,bad_steckdosen +IOT,10.40.41.225,shelly: s18,48:f6:ee:cc:16:e4,,,,kueche_steckdosen1 +IOT,10.40.41.226,shelly: s19,10:20:ba:fb:70:fc,,,,kueche_steckdosen3 +IOT,10.40.41.227,switchbot-floorlamp,B8:F8:62:09:F2:04,,,, +IOT,10.40.41.228,Twinkly Weihnachtsgirlande,98:F4:AB:2C:A7:88,,,,"dhcp-host=98:F4:AB:2C:A7:88,10.40.41.223,TwinklyWeihnachtsgirlande" +IOT,10.40.41.229,tuya smartlife TK,,,,, +IOT,10.40.41.230,Withings_waage,00:24:e4:40:2a:72,,,, +IOT,10.40.41.231,Withings_blutdruck,A4:7E:FA:18:2C:64,,,, +IOT,10.40.41.232,pve:homematic-raspi (ccu),BC:24:11:8E:0A:57,330,172.16.0.232,BC:24:11:D3:B3:F4, +IOT,10.40.41.233,shelly: s26,98:a3:16:7a:a3:54,,,,bad_luefter +IOT,10.40.41.234,,,,,, +IOT,10.40.41.235,,,,,, +IOT,10.40.41.236,lichterkette,A4:F0:0F:5F:D0:EC,,,, +IOT,10.40.41.237,lichterkette-mini,24:DC:C3:9B:89:64,,,, +IOT,10.40.41.238,,,,,, +IOT,10.40.41.239,sw1,00:08:54:71:98:2D,,,,"allnet core switch / dhcp-host=00:08:54:71:98:2D,10.40.41.239,sw1" +IOT,10.40.41.240,,,,,, +IOT,10.40.41.241,NukiSmartlock,28:DB:A7:09:7B:54,,,, +IOT,10.40.41.242,,,,,, +IOT,10.40.41.243,,,,,, +IOT,10.40.41.244,NukiBridge,24:62:ab:b1:63:f4,,,,"dhcp-host=24:62:ab:b1:63:f4,10.40.41.244,NukiBridge" +IOT,10.40.41.245,,,,,, +Netzwerk,10.40.41.246,fritzrepeater1,12:72:74:9c:66:49,,,,"Arbeitszimmer / dhcp-host=12:72:74:9c:66:49,10.40.41.246,fritzrepeater1" +Netzwerk,10.40.41.247,,,,,, +Netzwerk,10.40.41.248,,,,,, +Netzwerk,10.40.41.249,,,,,, +Netzwerk,10.40.41.250,,,,,, +Netzwerk,10.40.41.251,,,,,, +Netzwerk,10.40.41.252,,,,,, +Netzwerk,10.40.41.253,openwrt,,700,,, +Netzwerk,10.40.41.254,gateway-bf,0c:72:74:36:90:9c,,,, diff --git a/inventory/bf.md b/inventory/bf.md new file mode 100644 index 0000000..65fa90f --- /dev/null +++ b/inventory/bf.md @@ -0,0 +1,293 @@ +# Inventar — Standort BF (kanonisch) + +> Generiert aus `bf.csv` via `build.py`. **Quelle der Wahrheit = bf.csv.** Seed: `IPs.xlsx`. +> ⚠️ Manche `pve_ct`/Einträge können Doku-Leichen sein (z.B. re-dockerisierte Container). + + +## VPN + +| ip | hostname | mac | pve_ct | server_ip | server_mac | note | +|---|---|---|---|---|---|---| +| 10.40.41.1 | VPNchristoph | | | | | Fallback bis CF One überall läuft; IP umziehbar/unwichtig | +| 10.40.41.3 | | | | | | | + +## srv, infra + +| ip | hostname | mac | pve_ct | server_ip | server_mac | note | +|---|---|---|---|---|---|---| +| 10.40.41.4 | MFC | 30:5:5c:78:86:20 | | | | | +| 10.40.41.5 | P750W | 4C:EB:BD:E3:25:F2 | | | | Brother PT-P750W Printer | +| 10.40.41.6 | iHost | D0:27:03:C8:CB:36 | | | | | +| 10.40.41.7 | odroid-m1 | 00:1E:06:51:31:C9 | | | | | +| 10.40.41.8 | DTUBI-414392337823 | 54:F2:9F:12:51:F0 | | | | | +| 10.40.41.9 | | | | | | | +| 10.40.41.10 | nas-bf | 90:9:d0:58:20:f9 | | | | | +| 10.40.41.11 | tv | 70:AF:24:B8:C9:86 | | | | | +| 10.40.41.12 | virtualdsm | | | | | | +| 10.40.41.13 | sysrecue | | | | | | +| 10.40.41.14 | AppleTV | | | | | | +| 10.40.41.15 | | | | | | docker:synology | + +## docker + +| ip | hostname | mac | pve_ct | server_ip | server_mac | note | +|---|---|---|---|---|---|---| +| 10.40.41.16 | pve:docker:adguard_bf1 | BC:24:11:10:3A:98 | 130 | | | dzt kein default_internal (wird je site mit 1 vlan konsolidiert; in bf übergreifendpve-ds923) | +| 10.40.41.17 | pve:docker:adguard_fm1 | | | | | dzt kein default_internal (wird je site mit 1 vlan konsolidiert; in bf übergreifendpve-ds923) | +| 10.40.41.18 | pve:docker:adguard_dw1 | | | | | dzt kein default_internal (wird je site mit 1 vlan konsolidiert; in bf übergreifendpve-ds923) | +| 10.40.41.19 | docker:iob_exposed | BC:24:11:E4:DC:AB | 150 | 172.16.0.150 | BC:24:11:3A:62:43 | | +| 10.40.41.20 | docker-fm:nginx-proxy-manager | | | | | | +| 10.40.41.21 | docker:ldapsyno | | | | | | +| 10.40.41.22 | docker:ccu | | | | | | +| 10.40.41.23 | docker:pihole_dw1 | 02:42:0A:28:29:17 | | | | | +| 10.40.41.24 | docker: | | | | | | +| 10.40.41.25 | docker: | | | | | | +| 10.40.41.26 | docker: | | | | | | +| 10.40.41.27 | docker: | | | | | | +| 10.40.41.28 | docker: | | | | | | +| 10.40.41.29 | docker: | | | | | | +| 10.40.41.30 | docker:cloudflared | | | | | | +| 10.40.41.31 | docker: | | | | | | +| 10.40.41.32 | res docker2bf | | | | | | +| 10.40.41.33 | docker_ds923+:iob_slave | | | | | | +| 10.40.41.34 | res docker2bf | | | | | | +| 10.40.41.35 | res docker2bf | | | | | | +| 10.40.41.36 | res docker2bf | | | | | | +| 10.40.41.37 | res docker2bf | | | | | | +| 10.40.41.38 | res docker2bf | | | | | | +| 10.40.41.39 | res docker2bf | | | | | | +| 10.40.41.40 | res docker2bf | | | | | | +| 10.40.41.41 | res docker2bf | | | | | | +| 10.40.41.42 | res docker2bf | | | | | | +| 10.40.41.43 | res docker2bf | | | | | | +| 10.40.41.44 | res docker2bf | | | | | | +| 10.40.41.45 | res docker2bf | | | | | | +| 10.40.41.46 | res docker2bf | | | | | | +| 10.40.41.47 | res docker2bf | | | | | | + +## DHCP (reservations) + +| ip | hostname | mac | pve_ct | server_ip | server_mac | note | +|---|---|---|---|---|---|---| +| 10.40.41.48 | ds415+ | 00:11:32:4F:E2:12 | | | | | +| 10.40.41.49 | ds415play | 00:11:32:4C:72:7E | | | | | +| 10.40.41.50 | win11enterprise | 02:11:32:2f:1f:cc | | | | | +| 10.40.41.51 | ds207 | 00:11:32:04:57:66 | | | | | +| 10.40.41.52 | | | | | | | +| 10.40.41.53 | | | | | | | +| 10.40.41.54 | vuplus | | | | | | +| 10.40.41.55 | AppleTV | | | | | | +| 10.40.41.56 | | | | | | | +| 10.40.41.57 | | | | | | | +| 10.40.41.58 | | | | | | | +| 10.40.41.59 | MobilMarven | | | | | | +| 10.40.41.60 | MobilGeli | 8c:b8:4a:56:d0:0b | | | | Note10+ | +| 10.40.41.61 | MobilChristoph | 08:C7:B5:91:BA:61 | | | | S22 / dhcp-host=08:C7:B5:91:BA:61,10.40.41.33,MobilChristoph | +| 10.40.41.62 | MobilChristophAlt | 7C:D6:61:B7:93:99 | | | | dhcp-host=7C:D6:61:B7:93:99,10.40.41.31,MobilChristophAlt | +| 10.40.41.63 | MobilSara | 4A:11:58:B5:15:E1 | | | | A34 / dhcp-host=4A:11:58:B5:15:E1,10.40.41.26,MobilSara | +| 10.40.41.64 | MobilTanja | 44:16:FA:CE:27:D3 | | | | dhcp-host=44:16:FA:CE:27:D3,10.40.41.30,MobilTanja | +| 10.40.41.65 | MobilChristophA35 | B0:54:76:46:BC:1C | | | | A35 | +| 10.40.41.66 | MobilOma | DE:44:85:63:51:4A | | | | dhcp-host=DE:44:85:63:51:4A,10.40.41.29,MobilOma | +| 10.40.41.67 | MobilOpa | 02:8C:4F:B8:FC:8E | | | | dhcp-host=02:8C:4F:B8:FC:8E,10.40.41.28,MobilOpa | +| 10.40.41.68 | | | | | | | +| 10.40.41.69 | iPadChristoph | 34:2B:6E:6F:1F:EF | | | | | +| 10.40.41.70 | | | | | | | +| 10.40.41.71 | wwan | 3C:B2:33:ED:FC:03 | | | | | +| 10.40.41.72 | | | | | | | +| 10.40.41.73 | Forerunner965 | 38:F9:F5:8F:CC:69 | | | | | +| 10.40.41.74 | iHostWIFI | | | | | | +| 10.40.41.75 | KindleVoyage | 00:BB:3A:2C:0E:E6 | | | | dhcp-host=00:BB:3A:2C:0E:E6,10.40.41.39,KindleVoyage | +| 10.40.41.76 | SmartwatchChristoph935 | 14:8F:21:E7:45:2C | | | | dhcp-host=14:8F:21:E7:45:2C,10.40.41.40,SmartwatchChristoph935 | +| 10.40.41.77 | SmartwatchChristoph945 | B4:C2:6A:57:0B:BB | | | | dhcp-host=B4:C2:6A:57:0B:BB,10.40.41.41,SmartwatchChristoph945 | +| 10.40.41.78 | Garmin Edge 820 | 14:8F:21:CB:BC:EA | | | | dhcp-host=14:8F:21:CB:BC:EA,10.40.41.217,GarminEdge820 | +| 10.40.41.79 | ubuntu-desktop | 02:11:32:2c:3c:b1 | | | | | +| 10.40.41.80 | | | | | | | +| 10.40.41.81 | MacBook LAN | B8:B4:09:1A:EC:AB | | | | dhcp-host=B8:B4:09:1A:EC:AB,10.40.41.23,MacBookLAN | +| 10.40.41.82 | MacBook WLAN | 3c:a6:f6:02:3e:83 | | | | dhcp-host=3c:a6:f6:02:3e:83,10.40.41.24,MacBookWLAN | +| 10.40.41.83 | KindleTanja | a0:02:dc:5d:5d:d2 | | | | | +| 10.40.41.84 | | | | | | | +| 10.40.41.85 | iPadTanja | EC:73:79:C0:66:E7 | | | | dhcp-host=EC:73:79:C0:66:E7,10.40.41.35,iPadTanja | +| 10.40.41.86 | TvSara (zauberkatze) | CC:4B:73:75:7C:4A | | | | dhcp-host=CC:4B:73:75:7C:4A,10.40.41.43,TvSara(zauberkatze) | +| 10.40.41.87 | NotebookSara_alt (galadriel) | 00:E1:8C:9B:27:BA | | | | | +| 10.40.41.88 | NotebookSara (celeborn) | | | | | | +| 10.40.41.89 | NotebookOpa (pluto) | 08:71:90:EA:0A:56 | | | | dhcp-host=08:71:90:EA:0A:56,10.40.41.44,NotebookOpa(pluto) | +| 10.40.41.90 | | | | | | | +| 10.40.41.91 | | | | | | | +| 10.40.41.92 | NintendoSwitchLAN | 00:23:55:0C:86:59 | | | | | +| 10.40.41.93 | NintendoSwitchWLAN | 94:58:CB:B1:63:BC | | | | | +| 10.40.41.94 | EOS6Rm2 | A0:CD:F3:93:FF:E4 | | | | | +| 10.40.41.95 | | | | | | | +| 10.40.41.96 | | | | | | | +| 10.40.41.97 | | | | | | | +| 10.40.41.98 | | | | | | | +| 10.40.41.99 | | | | | | | +| 10.40.41.100 | pve | 00:D0:B4:04:19:24 | | | | | +| 10.40.41.101 | ubuntu-server | 02:11:32:24:3D:EC | | | | | +| 10.40.41.102 | ubuntu-desktop | 02:11:32:2b:b6:08 | | | | | +| 10.40.41.103 | airfryer | E4:BC:96:1F:B2:81 | | | | | +| 10.40.41.104 | | | | | | | +| 10.40.41.105 | pve:homeassistant | BC:24:11:11:A9:B3 | 100 | 172.16.0.18 | BC:24:11:1E:12:19 | | +| 10.40.41.106 | z2m25 | BC:24:11:A2:B5:0F | 112 | 172.16.0.12 | BC:24:11:F3:42:01 | | +| 10.40.41.107 | iob_master | BC:24:11:4D:26:96 | 101 | 172.16.0.19 | BC:24:11:B4:3E:41 | 172.24.0.19 / BC:24:11:6F:9A:86 | +| 10.40.41.108 | mqtt5 | BC:24:11:B0:46:53 | 102 | 172.16.0.10 | BC:24:11:53:DA:7D | | +| 10.40.41.109 | grafana | BC:24:11:8A:4D:F1 | 104 | 172.16.0.9 | BC:24:11:D9:A4:AC | | +| 10.40.41.110 | SONOFF-NSPanelPro | 7C:88:99:06:07:EC | | | | | +| 10.40.41.111 | redis | BC:24:11:41:CA:A1 | 107 | 172.16.0.7 | BC:24:11:5F:6B:EE | 172.24.0.7 / BC:24:11:C0:35:39 | +| 10.40.41.112 | | | | | | | +| 10.40.41.113 | pve:influxdb2 | BC:24:11:9A:F2:5E | 106 | 172.16.0.8 | | | +| 10.40.41.114 | minarca | BC:24:11:3C:E2:3E | 103 | | | | +| 10.40.41.115 | | | | | | | +| 10.40.41.116 | adguard-bf1 | BC:24:11:B3:FC:52 | 120 | | | | +| 10.40.41.117 | adguard-bf2 | BC:24:11:69:61:69 | 121 | | | | +| 10.40.41.118 | caddy | BC:24:11:3D:5A:5A | 129 | 172.16.0.118 | BC:24:11:A7:C9:6F | | +| 10.40.41.119 | node-red | BC:24:11:0D:0C:FE | 109 | | | | +| 10.40.41.120 | openproject | BC:24:11:94:83:5C | 201 | | | | +| 10.40.41.121 | vaultwarden | BC:24:11:5A:DC:A0 | 301 | 172.18.0.127 | BC:24:11:17:CA:26 | | +| 10.40.41.122 | mariadb | BC:24:11:52:78:0D | 302 | 172.16.0.23 | BC:24:11:B4:09:E4 | | +| 10.40.41.123 | nginx | BC:24:11:CC:13:0B | 128 | | BC:24:11:7D:DD:F1 | | +| 10.40.41.124 | pve:docker:hms-mqtt | | | | | | +| 10.40.41.125 | docker_ds923+:openspeedtest | | | | | | +| 10.40.41.126 | pve:docker | BC:24:11:C2:72:A2 | 400 | 172.16.0.126 | BC:24:11:62:69:D7 | | +| 10.40.41.127 | docker:vaultwarden | | | 172.16.0.127 | | | +| 10.40.41.128 | pve:docker:portainer | | | 172.18.0.2 | | | +| 10.40.41.129 | pve:ollama | BC:24:11:2C:B8:0F | 170 | 172.16.0.129 | BC:24:11:E7:42:55 | | +| 10.40.41.130 | docker_ds923+:openclaw | | | 172.18.0.130 | | | +| 10.40.41.131 | pihole2 | BC:24:11:5B:FF:8A | 131 | 172.16.0.131 | BC:24:11:4F:9F:81 | | +| 10.40.41.132 | docker_ds923+:openclaw_cloudflared | | | | | | +| 10.40.41.133 | ds923+:coolify | | | | | | +| 10.40.41.134 | | | | | | | +| 10.40.41.135 | synodocker:pbs | 02:11:32:2e:15:25 | | 172.16.0.135 | 02:11:32:21:b6:4a | | +| 10.40.41.136 | | | | | | | +| 10.40.41.137 | Dongle-M-10E8 | 94:54:C5:28:10:EB | | | | | +| 10.40.41.138 | Dongle-M-10E8_wifi | 94:54:C5:28:10:E8 | | | | | +| 10.40.41.139 | drawio | | | | | | +| 10.40.41.140 | | | | | | | +| 10.40.41.141 | wmbusmeters | BC:24:11:25:1E:DE | | | | | +| 10.40.41.142 | | | | | | | +| 10.40.41.143 | openclawnginx2_dummy | | | | | | +| 10.40.41.144 | openclaw2 | | | | | | +| 10.40.41.145 | pve:docker:cloudflared | | | | | | +| 10.40.41.146 | ollama | | | | | | +| 10.40.41.147 | n8n | | | | | johnny claw | +| 10.40.41.148 | docker_ds923+:nginx | | | | | johnny claw | +| 10.40.41.149 | gitea | | | | | | +| 10.40.41.150 | Ender3V3KE-3226 | FC:EE:11:03:32:26 | | | | | +| 10.40.41.151 | prometheus | | | | | | +| 10.40.41.152 | mcp | | | | | | +| 10.40.41.153 | alertmanager | | | | | | +| 10.40.41.154 | node-exporter | | | | | | +| 10.40.41.155 | | | | | | | +| 10.40.41.156 | | | | | | | +| 10.40.41.157 | | | | | | | +| 10.40.41.158 | | | | | | | +| 10.40.41.159 | openclaw-oc-qdrant-central | | | | | | +| 10.40.41.160 | openclaw | | | | | | +| 10.40.41.161 | openclaw-johnny2 | | | | | | +| 10.40.41.162 | openclaw-tzcharlie | | | | | | +| 10.40.41.163 | | | | | | | +| 10.40.41.164 | oc-jonny2-redis | | | 172.18.0.164 | | | +| 10.40.41.165 | oc-charlie-redis | | | 172.18.0.165 | | | +| 10.40.41.166 | | | | | | | +| 10.40.41.167 | macmini-LAN | d0:11:e5:b9:a7:48 | | | | | +| 10.40.41.168 | macmini-WLAN | d0:11:e5:c9:08:0a | | | | | +| 10.40.41.169 | macmini-cloudflared | | | | | | +| 10.40.41.170 | ms365-mcp | | | | | | +| 10.40.41.171 | hostinger-mcp | | | | | | +| 10.40.41.172 | woocommerce-mcp | | | | | | +| 10.40.41.173 | billbee-mcp | | | | | | +| 10.40.41.174 | sevdesk-mcp | | | | | | +| 10.40.41.175 | wordpress-mcp | | | | | | +| 10.40.41.176 | | | | | | | +| 10.40.41.177 | | | | | | | +| 10.40.41.178 | | | | | | | +| 10.40.41.179 | | | | | | | +| 10.40.41.180 | | | | | | | +| 10.40.41.181 | | | | | | | +| 10.40.41.182 | | | | | | | +| 10.40.41.183 | | | | | | | +| 10.40.41.184 | | | | | | | +| 10.40.41.185 | | | | | | | +| 10.40.41.186 | | | | | | | +| 10.40.41.187 | | | | | | | +| 10.40.41.188 | | | | | | | +| 10.40.41.189 | | | | | | | +| 10.40.41.190 | | | | | | | + +## Sonos + +| ip | hostname | mac | pve_ct | server_ip | server_mac | note | +|---|---|---|---|---|---|---| +| 10.40.41.191 | SonosArbeitszimmer1 | 34:7e:5c:32:37:96 | | | | dhcp-host=34:7e:5c:32:37:96,10.40.41.191,SonosArbeitszimmer1 | +| 10.40.41.192 | SonosArbeitszimmer2 | 34:7e:5c:32:33:b8 | | | | dhcp-host=34:7e:5c:32:33:b8,10.40.41.192,SonosArbeitszimmer2 | +| 10.40.41.193 | SonosSchlafzimmer1 | 78:28:ca:80:2a:f6 | | | | dhcp-host=78:28:ca:80:2a:f6,10.40.41.193,SonosSchlafzimmer1 | +| 10.40.41.194 | SonosSchlafzimmer2 | 48:a6:b8:14:fe:d0 | | | | dhcp-host=48:a6:b8:14:fe:d0,10.40.41.194,SonosSchlafzimmer2 | +| 10.40.41.195 | SonosBad | 48:A6:B8:14:FE:D0 | | | | dhcp-host=48:A6:B8:14:FE:D0,10.40.41.195,SonosBad | +| 10.40.41.196 | SonosKinderzimmer | 48:A6:B8:16:38:AE | | | | dhcp-host=48:A6:B8:16:38:AE,10.40.41.196,SonosKinderzimmer | +| 10.40.41.197 | SonosKueche | 48:A6:B8:14:FE:F2 | | | | dhcp-host=48:A6:B8:14:FE:F2,10.40.41.197,SonosKueche | +| 10.40.41.198 | SonosTerrasse | 48:a6:b8:16:38:ae | | | | dhcp-host=48:a6:b8:16:38:ae,10.40.41.198,SonosTerrasse | +| 10.40.41.199 | SonosWohnzimmer1 | 48:A6:B8:0B:63:10 | | | | 48:A6:B8:01:13:EE / dhcp-host=48:A6:B8:0B:63:10,10.40.41.199,SonosWohnzimmer1 | +| 10.40.41.200 | SonosWohnzimmer2 | 48:a6:b8:14:fe:f2 | | | | dhcp-host=48:a6:b8:14:fe:f2,10.40.41.200,SonosWohnzimmer2 | +| 10.40.41.201 | SonosWohnzimmer3 | 78:28:ca:d2:0d:ac | | | | dhcp-host=78:28:ca:d2:0d:ac,10.40.41.201,SonosWohnzimmer3 | +| 10.40.41.202 | shelly: s22 | a0:85:e3:c8:65:34 | | | | kueche_steckdose3-2 | +| 10.40.41.203 | shelly: s23 | ac:15:18:7b:62:20 | | | | dieleug-wohnzimmer_licht | +| 10.40.41.204 | shelly: s24 | | | | | bad_spielgelschrank | +| 10.40.41.205 | shelly: s25 | 98:a3:16:79:38:50 | | | | bad_lichtschalter | + +## IOT + +| ip | hostname | mac | pve_ct | server_ip | server_mac | note | +|---|---|---|---|---|---|---| +| 10.40.41.206 | shelly: s20 | 98:a3:16:7c:5f:ec | | | | kueche_steckdosen2 | +| 10.40.41.207 | shelly: s21 | 20:6e:f1:01:f9:f8 | | | | kueche_steckdosen4 | +| 10.40.41.208 | shelly: s1 | E4:B0:63:D7:C7:A4 | | | | weihnachten_kueche | +| 10.40.41.209 | shelly: s2 | 28:37:2F:36:F4:7C | | | | weihnachten_terrasse | +| 10.40.41.210 | shelly: s3 | E4:B0:63:E4:EF:7C | | | | weihnachten_kinderzimmer | +| 10.40.41.211 | shelly: s4 | E4:B0:63:E4:0F:30 | | | | kueche_mikrowelle | +| 10.40.41.212 | shelly: s5 | D8:85:AC:0C:5C:C8 | | | | kueche_backofen | +| 10.40.41.213 | shelly: s6 | 0c:72:74:36:90:9e | | | | kueche_kuehlschrank | +| 10.40.41.214 | shelly: s7 | D0:CF:13:D9:94:E8 | | | | kueche_tiefkuehlschrank | +| 10.40.41.215 | shelly: s8 | E4:B0:63:FA:FD:E0 | | | | kueche_geschirrspueler | +| 10.40.41.216 | shelly: s9 | E8:F6:0A:61:88:08 | | | | wohnzimmer_sideboard | +| 10.40.41.217 | shelly: s10 | E4:B0:63:FC:57:E4 | | | | bad_sonos | +| 10.40.41.218 | shelly: s11 | E4:B0:63:FA:6C:00 | | | | kinderzimmer_sonos | +| 10.40.41.219 | shelly: s12 | 48:f6:ee:c8:e6:ac | | | | dieleug_steckdosen | +| 10.40.41.220 | shelly: s13 | 48:F6:EE:DD:6A:F4 | | | | arbeitszimmer_technik | +| 10.40.41.221 | shelly: s14 | E4:B0:63:FC:59:48 | | | | schlafzimmer_bett | +| 10.40.41.222 | shelly: s15 | E4:B0:63:FA:D5:34 | | | | technik_pve | +| 10.40.41.223 | shelly: s16 | 10:20:ba:fa:f5:40 | | | | wohnzimmer_steckdosen | +| 10.40.41.224 | shelly: s17 | 10:20:ba:fb:6d:64 | | | | bad_steckdosen | +| 10.40.41.225 | shelly: s18 | 48:f6:ee:cc:16:e4 | | | | kueche_steckdosen1 | +| 10.40.41.226 | shelly: s19 | 10:20:ba:fb:70:fc | | | | kueche_steckdosen3 | +| 10.40.41.227 | switchbot-floorlamp | B8:F8:62:09:F2:04 | | | | | +| 10.40.41.228 | Twinkly Weihnachtsgirlande | 98:F4:AB:2C:A7:88 | | | | dhcp-host=98:F4:AB:2C:A7:88,10.40.41.223,TwinklyWeihnachtsgirlande | +| 10.40.41.229 | tuya smartlife TK | | | | | | +| 10.40.41.230 | Withings_waage | 00:24:e4:40:2a:72 | | | | | +| 10.40.41.231 | Withings_blutdruck | A4:7E:FA:18:2C:64 | | | | | +| 10.40.41.232 | pve:homematic-raspi (ccu) | BC:24:11:8E:0A:57 | 330 | 172.16.0.232 | BC:24:11:D3:B3:F4 | | +| 10.40.41.233 | shelly: s26 | 98:a3:16:7a:a3:54 | | | | bad_luefter | +| 10.40.41.234 | | | | | | | +| 10.40.41.235 | | | | | | | +| 10.40.41.236 | lichterkette | A4:F0:0F:5F:D0:EC | | | | | +| 10.40.41.237 | lichterkette-mini | 24:DC:C3:9B:89:64 | | | | | +| 10.40.41.238 | | | | | | | +| 10.40.41.239 | sw1 | 00:08:54:71:98:2D | | | | allnet core switch / dhcp-host=00:08:54:71:98:2D,10.40.41.239,sw1 | +| 10.40.41.240 | | | | | | | +| 10.40.41.241 | NukiSmartlock | 28:DB:A7:09:7B:54 | | | | | +| 10.40.41.242 | | | | | | | +| 10.40.41.243 | | | | | | | +| 10.40.41.244 | NukiBridge | 24:62:ab:b1:63:f4 | | | | dhcp-host=24:62:ab:b1:63:f4,10.40.41.244,NukiBridge | +| 10.40.41.245 | | | | | | | + +## Netzwerk + +| ip | hostname | mac | pve_ct | server_ip | server_mac | note | +|---|---|---|---|---|---|---| +| 10.40.41.246 | fritzrepeater1 | 12:72:74:9c:66:49 | | | | Arbeitszimmer / dhcp-host=12:72:74:9c:66:49,10.40.41.246,fritzrepeater1 | +| 10.40.41.247 | | | | | | | +| 10.40.41.248 | | | | | | | +| 10.40.41.249 | | | | | | | +| 10.40.41.250 | | | | | | | +| 10.40.41.251 | | | | | | | +| 10.40.41.252 | | | | | | | +| 10.40.41.253 | openwrt | | 700 | | | | +| 10.40.41.254 | gateway-bf | 0c:72:74:36:90:9c | | | | | diff --git a/inventory/build.py b/inventory/build.py new file mode 100644 index 0000000..1316788 --- /dev/null +++ b/inventory/build.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +"""Kanonischer Doku-Generator für das BF-Inventar. + +Wahrheit = CSV. Markdown wird daraus generiert. +- `build.py --seed` : (einmalig) bf.csv aus IPs.xlsx erzeugen (mit Transform/Deltas) +- `build.py` : bf.md aus bf.csv + bf-core-ports.md aus bf-core-ports.csv rendern + +Künftige Änderungen: bf.csv editieren -> `python3 build.py` -> bf.md aktuell. +""" +import sys, os, re, csv, zipfile +import xml.etree.ElementTree as ET + +HERE = os.path.dirname(os.path.abspath(__file__)) +XLSX = os.path.join(HERE, 'IPs.xlsx') +BF_CSV = os.path.join(HERE, 'bf.csv') +BF_MD = os.path.join(HERE, 'bf.md') +PORTS_CSV = os.path.join(HERE, 'bf-core-ports.csv') +PORTS_MD = os.path.join(HERE, 'bf-core-ports.md') + +IPRE = re.compile(r'^\d{1,3}(\.\d{1,3}){3}$') +MACRE = re.compile(r'^[0-9A-Fa-f]{1,2}(:[0-9A-Fa-f]{1,2}){5}$') +COLS = ['section', 'ip', 'hostname', 'mac', 'pve_ct', 'server_ip', 'server_mac', 'note'] + + +def _strip(t): return re.sub(r'\{[^}]*\}', '', t) + + +def read_xlsx_sheet(path, sheet): + z = zipfile.ZipFile(path) + shared = [] + if 'xl/sharedStrings.xml' in z.namelist(): + for si in ET.fromstring(z.read('xl/sharedStrings.xml')): + shared.append(''.join(t.text or '' for t in si.iter() if _strip(t.tag) == 't')) + wb = ET.fromstring(z.read('xl/workbook.xml')) + rels = {r.get('Id'): r.get('Target') for r in ET.fromstring(z.read('xl/_rels/workbook.xml.rels'))} + tgt = None + for s in wb.iter(): + if _strip(s.tag) == 'sheet' and s.get('name') == sheet: + rid = [v for k, v in s.attrib.items() if k.endswith('}id') or k == 'id'][0] + t = rels[rid]; tgt = t if t.startswith('xl/') else 'xl/' + t + ws = ET.fromstring(z.read(tgt)) + + def colnum(ref): + m = re.match(r'([A-Z]+)(\d+)', ref) + if not m: return 0, 0 + c = 0 + for ch in m.group(1): c = c * 26 + (ord(ch) - 64) + return c, int(m.group(2)) + cells = {}; maxc = 0; maxr = 0 + for c in ws.iter(): + if _strip(c.tag) != 'c': continue + ref = c.get('r') or ''; t = c.get('t'); col, row = colnum(ref) + if not col: continue + vs = [x for x in c if _strip(x.tag) == 'v']; iss = [x for x in c if _strip(x.tag) == 'is'] + val = '' + if t == 's' and vs: + try: val = shared[int(vs[0].text)] + except Exception: val = vs[0].text or '' + elif iss: val = ''.join(x.text or '' for x in iss[0].iter() if _strip(x.tag) == 't') + elif vs: val = vs[0].text or '' + if val != '': + cells.setdefault(row, {})[col] = val; maxc = max(maxc, col); maxr = max(maxr, row) + grid = [[cells.get(r, {}).get(c, '') for c in range(1, maxc + 1)] for r in range(1, maxr + 1)] + return grid + + +def seed_bf_csv(): + grid = read_xlsx_sheet(XLSX, 'bf') + out = [] + section = '' + for r in grid[1:]: # skip header row + nz = [x for x in r if x.strip()] + if not nz: + continue + # cols: A(0) empty | B(1) ip/section | C(2) host | D(3) mac | E(4) ct | F(5) sip | G(6) smac | H(7) note | I(8) note2 + def g(i): return r[i].strip() if i < len(r) else '' + ipcell = g(1) + # section header row = single non-empty cell, not an IP + if len(nz) == 1 and not IPRE.match(nz[0].strip()): + section = nz[0].strip(); continue + ip = ipcell if IPRE.match(ipcell) else '' + host = g(2); mac = g(3) if MACRE.match(g(3)) else '' + ct = g(4); sip = g(5); smac = g(6) + notes = [g(7), g(8)] + # defensive: misplaced data -> note + if g(3) and not MACRE.match(g(3)): notes.append('mac?=' + g(3)) + if ct and not ct.isdigit(): notes.append(ct); ct = '' + if sip and not IPRE.match(sip): notes.append(sip); sip = '' + if smac and not MACRE.match(smac): notes.append(smac); smac = '' + note = ' / '.join(n for n in notes if n.strip()) + # --- deltas (User 2026-06-05) --- + if host == 'VPNjoernfuenfstueck': + continue # gekickt + if host == 'VPNchristoph': + note = 'Fallback bis CF One überall läuft; IP umziehbar/unwichtig' + out.append([section, ip, host, mac, ct, sip, smac, note]) + with open(BF_CSV, 'w', newline='') as f: + w = csv.writer(f); w.writerow(COLS); w.writerows(out) + print(f'seed: wrote {BF_CSV} ({len(out)} rows)') + + +def render_bf_md(): + with open(BF_CSV) as f: + rows = list(csv.DictReader(f)) + lines = ['# Inventar — Standort BF (kanonisch)', '', + '> Generiert aus `bf.csv` via `build.py`. **Quelle der Wahrheit = bf.csv.** Seed: `IPs.xlsx`.', + '> ⚠️ Manche `pve_ct`/Einträge können Doku-Leichen sein (z.B. re-dockerisierte Container).', ''] + cur = None + cols = ['ip', 'hostname', 'mac', 'pve_ct', 'server_ip', 'server_mac', 'note'] + for row in rows: + if row['section'] != cur: + cur = row['section'] + lines += ['', f'## {cur or "(ohne Sektion)"}', '', + '| ' + ' | '.join(cols) + ' |', '|' + '|'.join(['---'] * len(cols)) + '|'] + if not any(row[c].strip() for c in cols): + continue + lines.append('| ' + ' | '.join(row[c].replace('|', '\\|') for c in cols) + ' |') + with open(BF_MD, 'w') as f: + f.write('\n'.join(lines) + '\n') + print(f'wrote {BF_MD} ({len(rows)} rows)') + + +def render_ports_md(): + if not os.path.exists(PORTS_CSV): + return + with open(PORTS_CSV) as f: + rows = list(csv.DictReader(f)) + cols = list(rows[0].keys()) if rows else [] + lines = ['# Core-Switch ALL-SG8316M (sw1, 10.40.41.239) — Port-Map', '', + '> Ist-Belegung. Ports 4/8/15/16 **behalten** (4+8 interim bis neue Switches produktiv).', + '> Übrige Ports (1–3, 5–7, 9–14): noch nicht erfasst — gemeinsam ergänzen.', '', + '| ' + ' | '.join(cols) + ' |', '|' + '|'.join(['---'] * len(cols)) + '|'] + for r in rows: + lines.append('| ' + ' | '.join((r[c] or '').replace('|', '\\|') for c in cols) + ' |') + with open(PORTS_MD, 'w') as f: + f.write('\n'.join(lines) + '\n') + print(f'wrote {PORTS_MD} ({len(rows)} ports)') + + +if __name__ == '__main__': + if '--seed' in sys.argv or not os.path.exists(BF_CSV): + seed_bf_csv() + render_bf_md() + render_ports_md() diff --git a/omada/docker-compose.yml b/omada/docker-compose.yml new file mode 100644 index 0000000..f838cfa --- /dev/null +++ b/omada/docker-compose.yml @@ -0,0 +1,37 @@ +# Omada Software Controller — BF +# Ziel-Host: pve docker-LXC (10.40.41.126), Engine 28.x +# Image: mbentley/omada-controller (De-facto-Standard; TP-Link liefert kein offizielles Image) +# +# ES208G/ES216G = Omada "Easy Managed" → SDN-adoptierbar (verifiziert 2026-06). +# ABER: ES-Serie braucht Controller >= 6.1.x (SDN-Support kam erst mit 6.1.x-FW) +# + aktuelle Switch-Firmware. Tier "Easy Managed" = nur Basis-VLAN/QoS im Controller. +# +# network_mode: host = nötig für L2-Auto-Discovery der Switches (29810/udp Broadcast). +# Controller nutzt dann direkt die LXC-IP 10.40.41.126. +# +# Deploy: +# mkdir -p /opt/docker/omada/{data,logs} +# docker compose up -d +# UI: https://10.40.41.126:8043 (Erst-Setup-Wizard) + +services: + omada-controller: + image: mbentley/omada-controller:6.1 + # ^ >=6.1.x ist Pflicht für ES-Serie (5.x adoptiert sie NICHT). + # Tag-Existenz kurz prüfen: docker pull mbentley/omada-controller:6.1 + # (sonst exakten 6.1.x-Tag von hub.docker.com/r/mbentley/omada-controller nehmen) + container_name: omada-controller + restart: unless-stopped + network_mode: host + environment: + - TZ=Europe/Vienna + - MANAGE_HTTP_PORT=8088 + - MANAGE_HTTPS_PORT=8043 + - PORTAL_HTTP_PORT=8088 + - PORTAL_HTTPS_PORT=8843 + - SHOW_SERVER_LOGS=true + - SHOW_MONGODB_LOGS=false + # - SMALL_FILES=true # nur falls MongoDB beim Start auf dem FS zickt + volumes: + - /opt/docker/omada/data:/opt/tplink/EAPController/data + - /opt/docker/omada/logs:/opt/tplink/EAPController/logs diff --git a/switch/.gitignore b/switch/.gitignore new file mode 100644 index 0000000..f704bfd --- /dev/null +++ b/switch/.gitignore @@ -0,0 +1,5 @@ +.secrets +cookies.txt +state-*/ +firmware/ +cli/running-*.txt diff --git a/switch/.secrets.example b/switch/.secrets.example new file mode 100644 index 0000000..bc2c0c8 --- /dev/null +++ b/switch/.secrets.example @@ -0,0 +1,4 @@ +# copy to .secrets (gitignored). Account = Web/Telnet login on the switch. +export SW_HOST=10.40.41.239 +export SW_USER=claudecode +export SW_PASS=changeme diff --git a/switch/cli/01-vlan-db.cli b/switch/cli/01-vlan-db.cli new file mode 100644 index 0000000..15e0a8a --- /dev/null +++ b/switch/cli/01-vlan-db.cli @@ -0,0 +1,8 @@ +# === BF Core-Switch sw1 (ALL-SG8316M, FW 2.2.1) — VLAN-Datenbank === +# Reproduzierbar: . switch/.secrets && expect switch/cli/run-cli.exp switch/cli/01-vlan-db.cli +# NON-DISRUPTIV: legt nur VLANs an; ändert KEINE Port-Zugehörigkeit (alle Ports bleiben default VLAN1). +# VID-Plan: 10=Server/Main 20=Docker 30=IoT 40=Guest 100=WAN +configure +vlan 10,20,30,40,100 +end +save diff --git a/switch/cli/CLI-REFERENCE.md b/switch/cli/CLI-REFERENCE.md new file mode 100644 index 0000000..45bad4b --- /dev/null +++ b/switch/cli/CLI-REFERENCE.md @@ -0,0 +1,47 @@ +# ALL-SG8316M FW 2.2.1.2956 — CLI-Referenz (Telnet) + +Switch `sw1` @ 10.40.41.239. **Kein SSH** → Telnet (Port 23). IOS-artige CLI. Login: `claudecode` (Creds in `switch/.secrets`). +Prompt-Ebenen: `sw1>` (user) → `sw1#` (enable) → `sw1(config)#` (config). `configure` rein, `end`/`exit` raus. + +> ⚠️ **Nur EINE VTY-Line!** Der Switch reapt halb-offene Sessions schlecht (stale Session sperrt ~15 min). +> → Immer **serialisiert** arbeiten und **sauber ausloggen** (`exit` bis zur Verbindungstrennung). Bei „busy" **nicht hämmern**, paar Minuten warten. + +Tooling (macOS): `telnet` (/opt/homebrew/bin) + `expect`. Python 3.14 hat KEIN telnetlib. Runner: `switch/cli/run-cli.exp `. + +## Management-IP +- **Ansehen** (enable): `show ip` → IP / Subnet Netmask / Default Gateway. + - `show ip ?`: `dhcp dns http https igmp` (+ `` = Summary). +- **Statisch setzen** (config): + ``` + ip address + ip default-gateway + ``` + - ⚠️ **Netzmasken-Syntax noch zu bestätigen**: `ip address ?` zeigte nur `A.B.C.D`. Vor dem Commit + `ip address ?` prüfen ODER `show running-config` ansehen (wie die bestehende Zeile geschrieben ist) und spiegeln. +- DHCP statt statisch: `ip dhcp`. +- **NICHT vorhanden:** `interface vlan`, `show ip interface`, `show management`, `terminal datadump`. + +## Management-VLAN +- **Setzen** (config): `management-vlan vlan <1-4094>` (`management` = Abk.) +- **Ansehen** (enable): `show management-vlan` → aktuell `default(1)`. +- Reihenfolge-Warnung: Ziel-VLAN muss existieren UND der Mgmt-Port muss es tragen, sonst Reachability weg. + +## VLANs +- **Anlegen** (config): `vlan ` z.B. `vlan 10,20,30,40,100` (Range 1–4094, `3,6-8` möglich). +- **Ansehen** (enable): `show vlan`. +- **Namen:** Syntax noch zu erkunden (config-vlan `name`? `vlan ` einzeln?) — beim nächsten Lauf via `?` prüfen. + +## Ports (gi1-16, lag1-8) — Trunk/Access (für Cutover) +``` +interface gi (oder: interface range ...) + switchport mode {access|hybrid|trunk} + switchport access vlan + switchport trunk native vlan + switchport trunk allowed vlan ... (genaue add/remove-Syntax via `switchport trunk allowed ?` prüfen) +``` + +## Speichern / Diverses +- **Persistieren:** `save` (enable) → „Success". (Sonst nach Reboot weg!) +- **Config-Dump:** `show running-config` / `show startup-config` (Paging `--More--` → Space). +- **Version:** `show version` → `Firmware Version : 2.2.1.2956`. +- Andere: `reboot`, `restore-defaults`, `copy`, `clock`, `ping`, `ssl`, `clear`, `disable`, `terminal`. diff --git a/switch/cli/run-cli.exp b/switch/cli/run-cli.exp new file mode 100644 index 0000000..20864ab --- /dev/null +++ b/switch/cli/run-cli.exp @@ -0,0 +1,33 @@ +#!/usr/bin/expect -f +# Generischer Telnet-CLI-Runner für sw1 (ALL-SG8316M, FW 2.2.1, IOS-artige CLI). +# Nutzung: . switch/.secrets && expect switch/cli/run-cli.exp switch/cli/.cli +# Liest die .cli-Datei zeilenweise, loggt ein, sendet jeden Befehl, flaggt Fehler. +# Zeilen mit führendem '#' = Kommentar (übersprungen). Am Ende: show vlan zur Kontrolle. +set timeout 20 +set user $env(SW_USER) +set pass $env(SW_PASS) +set host $env(SW_HOST) +if {[llength $argv] < 1} { puts "usage: run-cli.exp "; exit 1 } +set fh [open [lindex $argv 0] r] +log_user 1 +spawn telnet $host +expect "Username:"; send "$user\r" +expect "Password:"; send "$pass\r" +expect -re {sw1[#>]} +while {[gets $fh line] >= 0} { + set line [string trim $line] + if {$line eq "" || [string match "#*" $line]} { continue } + send "$line\r" + expect { + "Incomplete command" { puts "\n>>> FEHLER (incomplete): $line" } + "Unknown command" { puts "\n>>> FEHLER (unknown): $line" } + -re {sw1\([^)]*\)[#>] ?$} {} + -re {sw1[#>] ?$} {} + timeout { puts "\n>>> TIMEOUT bei: $line" } + } +} +close $fh +send "show vlan\r" +expect -re {sw1[#>]} +send "exit\r" +expect eof diff --git a/switch/recovery/README.md b/switch/recovery/README.md new file mode 100644 index 0000000..e27422d --- /dev/null +++ b/switch/recovery/README.md @@ -0,0 +1,41 @@ +# Mac-mini Recovery-Anker für den Switch-Flash + +**Zweck:** Der Mac mini (10.40.41.167, en0, L2-benachbart zum Switch) trägt dauerhaft eine +**Zweit-IP 192.168.1.2/24**. Nach einem Firmware-Flash kommt der Switch auf `192.168.1.1` hoch +(Werks-Default) — über die Zweit-IP erreicht Claude ihn **vom Mac mini aus** und setzt ihn +automatisch auf `10.40.41.239` zurück. Kein manuelles IP-Suchen, kein Laptop nötig. + +## Variante A — nur für heute (transient, kein Reboot dazwischen) +Auf dem Mac mini (deine SSH-Session): +``` +sudo ifconfig en0 alias 192.168.1.2 255.255.255.0 +ifconfig en0 | grep 192.168.1 # prüfen +``` +Entfernen: `sudo ifconfig en0 -alias 192.168.1.2` + +## Variante B — persistent (übersteht Reboots, empfohlen wenn Dauer-Anker) +Auf dem Mac mini, aus diesem Repo-Ordner (`switch/recovery/`): +``` +sudo cp switch-recovery-ip.sh /usr/local/sbin/switch-recovery-ip.sh +sudo chmod 755 /usr/local/sbin/switch-recovery-ip.sh +sudo cp com.bf.switchrecoveryip.plist /Library/LaunchDaemons/ +sudo chown root:wheel /Library/LaunchDaemons/com.bf.switchrecoveryip.plist +sudo launchctl load -w /Library/LaunchDaemons/com.bf.switchrecoveryip.plist +ifconfig en0 | grep 192.168.1 # prüfen +``` +Deinstallieren: +``` +sudo launchctl unload -w /Library/LaunchDaemons/com.bf.switchrecoveryip.plist +sudo rm /Library/LaunchDaemons/com.bf.switchrecoveryip.plist /usr/local/sbin/switch-recovery-ip.sh +sudo ifconfig en0 -alias 192.168.1.2 +``` + +## Recovery-Ablauf nach Flash (Claude führt aus, vom Mac mini) +``` +ssh 10.40.41.167 +cd ~/.../bf-network-r6/switch # Repo muss auf dem Mac mini liegen ODER Claude tunnelt +SW_HOST=192.168.1.1 SW_USER=admin SW_PASS=admin ./sg8316m.sh set-ip 10.40.41.239 +# Switch nun wieder auf .239 → .secrets zurück, dann VLANs/Ports/save +``` +> Hinweis: Claude erreicht den Switch nach Flash **nur** über den Mac mini (.1.1 ist L2-lokal am Mac mini). +> Der Treiber `sg8316m.sh` muss daher vom Mac mini aus laufen (Repo dorthin klonen/kopieren oder via SSH ausführen). diff --git a/switch/recovery/com.bf.switchrecoveryip.plist b/switch/recovery/com.bf.switchrecoveryip.plist new file mode 100644 index 0000000..6bddf81 --- /dev/null +++ b/switch/recovery/com.bf.switchrecoveryip.plist @@ -0,0 +1,16 @@ + + + + + Label + com.bf.switchrecoveryip + ProgramArguments + + /usr/local/sbin/switch-recovery-ip.sh + + RunAtLoad + + StandardErrorPath + /var/log/switch-recovery-ip.log + + diff --git a/switch/recovery/flash-and-recover.sh b/switch/recovery/flash-and-recover.sh new file mode 100644 index 0000000..3d8b207 --- /dev/null +++ b/switch/recovery/flash-and-recover.sh @@ -0,0 +1,136 @@ +#!/bin/sh +# Autonome Flash- + Recovery-Orchestrierung für ALL-SG8316M. +# LÄUFT AUF DEM MAC MINI (10.40.41.167, en0, L2-lokal zum Switch). +# Zweck: Claude stößt es detached an und ist während des Switch-Reboots OFFLINE. +# Das Script zieht die ganze Kette autonom durch und loggt alles. +# +# Kette: pre-flight -> flash -> warte down -> warte up(.1.1|.239) +# -> (falls .1.1) IP zurück auf .239 [cmd dynamisch entdeckt] +# -> VLANs (best-effort) -> save-to-flash -> verify +# +# Aufruf: ./flash-and-recover.sh preflight # nur Checks, kein Flash +# ./flash-and-recover.sh run # echter Flash + Recovery +set -u + +SW_PROD=10.40.41.239 +SW_DEFAULT=192.168.1.1 +PROD_MASK=255.255.255.0 +PROD_GW=10.40.41.254 +ALIAS_IP=192.168.1.2 +VLANS=10,20,30,40,100 +IMG="${IMG:-$HOME/bf-switch-flash/all-sg8316m-version_2.2.1_vmlinux.bix}" +IMG_SHA=e3f160983e8b17962dc70a52360b7f560c92da8197928d702f5266027a0fc7fc +LOG="${LOG:-$HOME/bf-switch-flash/flash-$(date +%Y%m%d-%H%M%S).log}" +MODE="${1:-preflight}" + +mkdir -p "$(dirname "$LOG")" +log(){ printf '%s %s\n' "$(date '+%H:%M:%S')" "$*" | tee -a "$LOG"; } + +# Liveness: Webserver-Root antwortet (firmware-stabiler als ein bestimmter cmd) +http_code(){ curl -s -o /dev/null -w '%{http_code}' --max-time 5 "http://$1/" 2>/dev/null; } +up(){ [ "$(http_code "$1")" = "200" ]; } +fw_version(){ curl -s --max-time 6 "http://$1/cgi-bin/dispatcher.cgi?cmd=512" \ + | sed -e 's/<[^>]*>/ /g' | grep -oiE 'Firmware Version[^0-9]*[0-9.]+' | head -1; } + +wait_up(){ _e=$(( $(date +%s) + $2 )); while [ "$(date +%s)" -lt "$_e" ]; do up "$1" && return 0; sleep 4; done; return 1; } +wait_down(){ _e=$(( $(date +%s) + $2 )); while [ "$(date +%s)" -lt "$_e" ]; do up "$1" || return 0; sleep 4; done; return 1; } + +# IP zurücksetzen — cmd + Seite dynamisch aus der Live-UI entdecken (firmware-drift-sicher) +restore_ip(){ + _host=$1 + _menu=$(curl -s --max-time 8 "http://$_host/cgi-bin/dispatcher.cgi?cmd=2") + _ipcmd=$(printf '%s' "$_menu" | grep -i 'IP Address' | grep -oE 'cmd=[0-9]+' | head -1 | cut -d= -f2) + [ -z "$_ipcmd" ] && _ipcmd=517 + _form=$(curl -s --max-time 8 "http://$_host/cgi-bin/dispatcher.cgi?cmd=$_ipcmd") + _post=$(printf '%s' "$_form" | grep -i 'name="cmd"' | grep -oE 'value="[0-9]+"' | head -1 | grep -oE '[0-9]+') + [ -z "$_post" ] && _post=518 + log "restore_ip: ip-page=$_ipcmd post-cmd=$_post -> set $SW_PROD" + curl -s --max-time 10 -X POST "http://$_host/cgi-bin/dispatcher.cgi" \ + --data "mode=0" --data "ip=$SW_PROD" --data "netmask=$PROD_MASK" \ + --data "gateway=$PROD_GW" --data "cmd=$_post" >/dev/null 2>&1 +} +add_vlans(){ curl -s --max-time 10 -X POST "http://$1/cgi-bin/dispatcher.cgi" \ + --data "vlanlist=$VLANS" --data "vlanAction=0" --data "name=" --data "cmd=1284" >/dev/null 2>&1; } +save_flash(){ curl -s --max-time 15 "http://$1/cgi-bin/dispatcher.cgi?cmd=4358" >/dev/null 2>&1; } + +# ---------- PRE-FLIGHT ---------- +log "=== PRE-FLIGHT (mode=$MODE) ===" +fail=0 +if [ -f "$IMG" ]; then + h=$(shasum -a 256 "$IMG" 2>/dev/null | awk '{print $1}') + if [ "$h" = "$IMG_SHA" ]; then log "OK image sha256"; else log "FAIL image sha256: $h"; fail=1; fi +else log "FAIL image missing: $IMG"; fail=1; fi +if ifconfig en0 2>/dev/null | grep -q "$ALIAS_IP"; then log "OK recovery-alias $ALIAS_IP on en0"; +else log "FAIL alias $ALIAS_IP missing -> sudo ifconfig en0 alias $ALIAS_IP 255.255.255.0"; fail=1; fi +if up "$SW_PROD"; then log "OK switch up at $SW_PROD (FW: $(fw_version "$SW_PROD"))"; +else log "FAIL switch not reachable at $SW_PROD"; fail=1; fi +if [ "$fail" -ne 0 ]; then log "PRE-FLIGHT FAILED -> abort"; exit 2; fi +log "PRE-FLIGHT OK" +[ "$MODE" = "preflight" ] && { log "preflight-only -> done (kein Flash)"; exit 0; } + +# ---------- FLASH ---------- +MARKER="$HOME/bf-switch-flash/.flashed-2.2.1" +if [ -f "$MARKER" ] && up "$SW_PROD"; then + log "Marker vorhanden + Switch up @ $SW_PROD -> Flash übersprungen (nur reconfig)"; skip=1 +else skip=0; fi +if [ "$skip" -eq 0 ]; then + log "=== FLASH: lade Image hoch ($IMG) ===" + curl -s --max-time 200 -F "type=0" -F "http_file=@$IMG" -F "cmd=4364" \ + "http://$SW_PROD/cgi-bin/httpupload.cgi" >>"$LOG" 2>&1 + log "Upload abgeschlossen, warte auf Reboot (down)..." + # Der Reboot selbst ist das verlässliche Flash-Signal (Flash erzwingt Neustart). + if wait_down "$SW_PROD" 180; then + log "Switch down (Reboot) — Flash hat gegriffen" + else + log "FAIL kein Reboot binnen 180s — Flash vermutlich nicht angenommen (Upload/Format/Auth?)." + log " Switch unverändert @ $SW_PROD, Netz intakt, KEIN Reset. Abbruch." + exit 3 + fi +fi + +# ---------- WARTEN AUF WIEDERKEHR ---------- +log "=== RECOVERY: warte auf Switch (max 6 min, .1.1 ODER .239) ===" +target=""; _e=$(( $(date +%s) + 360 )) +while [ "$(date +%s)" -lt "$_e" ]; do + if up "$SW_DEFAULT"; then target=$SW_DEFAULT; break; fi + if up "$SW_PROD"; then target=$SW_PROD; break; fi + sleep 4 +done +if [ -z "$target" ]; then + log "FAIL Switch kam binnen 6min nicht auf $SW_DEFAULT noch $SW_PROD zurück." + log " -> MANUELLE Recovery nötig (Reset-Knopf 10s, dann erneut)." + exit 4 +fi +log "Switch zurück an $target" + +# ---------- IP WIEDERHERSTELLEN ---------- +if [ "$target" = "$SW_DEFAULT" ]; then + log "Switch auf Default $SW_DEFAULT -> stelle $SW_PROD wieder her" + restore_ip "$SW_DEFAULT" + if wait_up "$SW_PROD" 60; then + log "OK Switch wieder auf $SW_PROD" + else + log "FAIL set-ip griff nicht — FW 2.2.1 erzwingt vermutlich Login (FW1.0 war offen)." + log " LAN/Internet laufen TROTZDEM (L2-Forwarding). Nur die Mgmt-IP hängt auf $SW_DEFAULT." + log " MANUELL: Browser http://$SW_DEFAULT Login admin/admin -> Network/IP Address" + log " -> $SW_PROD Maske $PROD_MASK GW $PROD_GW -> Save to Flash." + exit 5 + fi +else + log "Switch hat $SW_PROD behalten (Firmware bewahrte IP)" +fi + +# ---------- RECONFIG (best-effort, unkritisch — online nachholbar) ---------- +log "=== reconfig (best-effort) ===" +if add_vlans "$SW_PROD"; then log "VLANs $VLANS abgeschickt"; else log "WARN VLAN-Add fehlgeschlagen (online nachholen)"; fi +if save_flash "$SW_PROD"; then log "save-to-flash abgeschickt"; else log "WARN save fehlgeschlagen (online nachholen!)"; fi + +# ---------- VERIFY ---------- +if up "$SW_PROD"; then + touch "$HOME/bf-switch-flash/.flashed-2.2.1" + log "=== SUCCESS: Switch up @ $SW_PROD (Marker gesetzt) ===" + exit 0 +else + log "=== WARN: Switch am Ende nicht bestätigt up ===" + exit 6 +fi diff --git a/switch/recovery/switch-recovery-ip.sh b/switch/recovery/switch-recovery-ip.sh new file mode 100644 index 0000000..186d312 --- /dev/null +++ b/switch/recovery/switch-recovery-ip.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# Recovery-Anker: Zweit-IP 192.168.1.2/24 auf en0, damit der Mac mini den +# ALL-SG8316M nach einem Firmware-Flash (Reset auf 192.168.1.1) erreichen kann. +# Wird per LaunchDaemon bei jedem Boot ausgeführt (retry bis en0 da ist). +IFACE=en0 +IP=192.168.1.2 +MASK=255.255.255.0 +i=0 +while [ "$i" -lt 10 ]; do + if ifconfig "$IFACE" >/dev/null 2>&1; then + ifconfig "$IFACE" alias "$IP" "$MASK" 2>/dev/null && exit 0 + fi + i=$((i+1)); sleep 3 +done +exit 1 diff --git a/switch/sg8316m-cgi-map.md b/switch/sg8316m-cgi-map.md new file mode 100644 index 0000000..7327d6c --- /dev/null +++ b/switch/sg8316m-cgi-map.md @@ -0,0 +1,61 @@ +# ALL-SG8316M — dispatcher.cgi API-Map (Recon 2026-06-05) + +> ⚠️ **VERALTET — nur FW 1.0.** Switch ist auf **FW 2.2.1** geflasht; die Web-UI/cmd-Codes hier gelten +> NICHT mehr (cmd=2 → 404). Konfiguration jetzt via **Telnet-CLI** → `switch/cli/` (run-cli.exp + .cli). +> Dieses Dokument bleibt nur als Historie. + +Switch: **10.40.41.239** · Web-UI: Realtek **`/cgi-bin/dispatcher.cgi?cmd=`** · `Server: Hydra/0.1.8` (FW-Basis 2014). +Reine **CGI/Form-POST**-UI (kein JS-SPA) → **vollständig per `curl` skriptbar**. Von diesem Mac direkt erreichbar (~7 ms), +ebenso vom Mac mini (10.40.41.167). **Kein SSH** am Switch; **Telnet** existiert als Option (cmd=534), aber curl ist sauberer. + +> ⚠️ Auth-Hinweis: Unauthentifizierte GETs liefern bereits Config-Seiten (bekannte Schwäche dieser Realtek-dispatcher.cgi-Boxen). +> Login-Mechanik vor Schreibzugriff verifizieren. **Konsequenz fürs Design:** Mgmt strikt auf vlan10/restricted halten, +> EOL-Gerät (2014) nie Richtung WAN exponieren. + +## Befehlscodes (aus Menü cmd=2 extrahiert) + +### 🎯 Für R6-Config gebraucht +| cmd | Seite | Zweck | +|---|---|---| +| **1282** | Create VLAN | VLANs 10/20/30/40/100 anlegen | +| **1289** | Interface Settings | Port-Modus (Access/Trunk/Hybrid) + PVID | +| **1291** | Port to VLAN | VLAN↔Port-Matrix | +| **1293** | Port VLAN Membership | tagged/untagged je Port | +| **1297** | Management VLAN | Mgmt-VLAN 1→10 (Cutover) | +| **517** | IP Address | Switch-Mgmt-IP (Ziel 10.40.41.2) | +| **524** | Account Manager | eigenen User anlegen | +| **534/537/539** | Telnet/HTTP/HTTPS | Zugangsdienste | + +### 🔧 Maintenance +| cmd | Seite | +|---|---| +| 4361 | Backup Manager (User: Export defekt → wir scrapen stattdessen, s.u.) | +| 4363 | Upgrade Manager (**Firmware**) | +| 4358 | Configuration Manager / Save-to-Flash | +| 524 | Account Manager | + +### ⛔ NICHT aufrufen (destruktiv/disruptiv) +| cmd | Wirkung | +|---|---| +| 4352 | **Reboot** | +| 4354 | **Factory Default / Restore Defaults** | +| 4358 | Save to FLASH — nur bewusst am Ende eines Config-Laufs | + +### Weitere (Referenz) +Status 512(SysInfo) 3848(Log) · Port 779/774/1031/4619/1814 · Net 517/519/1297 · Time 541/543 · +Switching 768(Port) 2048(Mirror) · LAG 1024/1026/1032/1034/1036 · VoiceVLAN 1536/1538/1543 3328(EEE) · +Multicast 1792 · IGMP 1802/1806/1797/1796/1808 3072(Jumbo) · STP 4096/4098/4100/4102/4108 · +MAC 2311/2309/2304 · Security: Storm 3586/3584 772(Protected) DoS 4864/4866 · Access 534/537/539 · +QoS 2560/2562/2564/2566/2568/2570 Basic 2572/2574 RateLimit 3588/3590/3592 · +LLDP 4608/4610/4617/4614/4621 · SNMP 2816/2818/2821 · Diag 5120/527/530 · Logging 3840/3842/3844 · +Maint 4361/4363/4358/524 4354/4352. + +## „Backup" trotz defektem Export +User: Config-Import/Export der FW ist kaputt. **Kein Blocker:** Wir GETten jede Config-Seite per curl in Textdateien +(`switch/state-PRE/*.html`) → **git-versionierter, menschenlesbarer Ist-Zustand** statt opaker Binär-Blob. Restore = +gezielte CGI-POSTs (nicht Blob-Reupload). Damit ist der Vorgang reproduzierbar + diff-bar. + +## Skript-Plan (statt MCP) +`switch/sg8316m.sh` (bash+curl) oder `.py` (requests): login→Session-Cookie → State-Scrape (PRE) → +VLANs anlegen (1282) → Interface/Membership (1289/1293) → optional Mgmt-VLAN/IP (1297/517) → Save (4358). +Idempotent, dry-run-fähig, im Repo versioniert. Läuft von hier oder vom Mac mini. diff --git a/switch/sg8316m.sh b/switch/sg8316m.sh new file mode 100755 index 0000000..afc0e53 --- /dev/null +++ b/switch/sg8316m.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# ⚠️ VERALTET — nur FW 1.0. Switch ist auf FW 2.2.1 geflasht; die dispatcher.cgi-cmd-Codes +# unten gelten dort NICHT mehr. Konfig jetzt via Telnet-CLI: switch/cli/ (run-cli.exp + .cli). +# Bleibt nur als Historie / für den (unwahrscheinlichen) FW-1.0-Rollback. +# ALL-SG8316M (Realtek dispatcher.cgi) driver — curl-based, no MCP needed. +# Read ops are safe. WRITE ops change config; SAVE persists to flash. +# Creds via ./.secrets (gitignored): SW_HOST, SW_USER, SW_PASS. +set -euo pipefail + +HERE="$(cd "$(dirname "$0")" && pwd)" +[ -f "$HERE/.secrets" ] && . "$HERE/.secrets" +HOST="${SW_HOST:-10.40.41.239}" +BASE="http://$HOST/cgi-bin/dispatcher.cgi" +CURL=(curl -sS --max-time 12) + +# --- read --- +get() { "${CURL[@]}" "$BASE?cmd=$1"; } + +# Curated config-view + AJAX-data cmd codes (see sg8316m-cgi-map.md) +SCRAPE_CMDS="512 517 519 1297 541 543 768 779 1024 1026 1031 \ +1282 1283 1289 1291 1293 534 537 539 524 \ +4096 4098 4100 2560 2562 2564 2572 2574 2816 2818 2821 3840 3842 3844" + +scrape() { + local out="$HERE/${1:-state-PRE}"; mkdir -p "$out" + echo "Scraping $HOST -> $out" + for c in $SCRAPE_CMDS; do + if "${CURL[@]}" "$BASE?cmd=$c" >"$out/cmd-$c.html" 2>/dev/null; then + printf ' cmd=%-5s %6s bytes\n' "$c" "$(wc -c <"$out/cmd-$c.html" | tr -d ' ')" + else + printf ' cmd=%-5s FAILED\n' "$c" + fi + done +} + +# Pretty-print one page as text +view() { get "$1" | sed -e 's/<[^>]*>/ /g' | tr -s ' \t\r\n' ' ' | sed 's/ / /g'; echo; } + +# --- write (use deliberately, then `save`) --- +post() { "${CURL[@]}" -X POST "$BASE" "$@"; } + +add_vlans() { post --data-urlencode "vlanlist=$1" --data "vlanAction=0" --data-urlencode "name=${2:-}" --data "cmd=1284"; } +del_vlans() { post --data-urlencode "vlanlist=$1" --data "vlanAction=1" --data "cmd=1284"; } +# set_ip [netmask] [gateway] — RECOVERY: re-point mgmt IP (e.g. after flash reset to 192.168.1.1) +set_ip() { post --data "mode=0" --data "ip=$1" --data "netmask=${2:-255.255.255.0}" --data "gateway=${3:-10.40.41.254}" --data "cmd=518"; } +save_flash() { echo ">> SAVE to FLASH (cmd=4358)"; get 4358 >/dev/null; } + +usage() { cat < + scrape [dir] dump config pages to switch/ (default state-PRE) [READ] + get raw HTML of cmd=N [READ] + view cmd=N as plain text [READ] + add-vlans [prefix] e.g. add-vlans 10,20,30,40,100 [WRITE] + del-vlans [WRITE] + set-ip [mask] [gw] RECOVERY: re-point mgmt IP [WRITE] + save persist running config to flash [WRITE] + +Recovery after flash (switch reset to 192.168.1.1): + SW_HOST=192.168.1.1 SW_USER=admin SW_PASS=admin $0 set-ip 10.40.41.239 +USAGE +} + +case "${1:-}" in + scrape) scrape "${2:-state-PRE}" ;; + get) get "$2" ;; + view) view "$2" ;; + add-vlans) add_vlans "$2" "${3:-}" ;; + del-vlans) del_vlans "$2" ;; + set-ip) set_ip "$2" "${3:-255.255.255.0}" "${4:-10.40.41.254}" ;; + save) save_flash ;; + *) usage ;; +esac