Files
KayandClaude Sonnet 5 adb3a661ab Doku: README/Manual an Bug-37-Fix angepasst
M7-Status in README aktualisiert (REST-Schreibpfad + Hostkey-Trust
jetzt live verifiziert). Manual.md korrigiert: seit Bug 37 kann bei
REST-Verbindungen zusätzlich zum Zertifikat auch der SSH-Host-Schlüssel
zur Bestätigung erscheinen, nicht mehr nur eines von beiden.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 16:28:10 +02:00

251 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RouterOS Assistant
Native macOS-App (SwiftUI), die Laien und Fortgeschrittene per geführtem
Interview-Wizard durch die häufigsten Mikrotik-RouterOS-Konfigurationen
führt — und für alles darüber hinaus generischen, aber sicheren Zugriff
auf praktisch jedes RouterOS-Menü bietet.
## Worum geht's
Mikrotik-Router sind mächtig, aber die Konfiguration über Winbox oder die
CLI ist für Einsteiger:innen nicht immer zugänglich. RouterOS Assistant
übersetzt die häufigsten Schritte (Internet-Anschluss, Heimnetz/DHCP,
zusätzliche VLAN-Netzwerke, WLAN, Firewall-Grundschutz) in einen
geführten Wizard — und bleibt für alles, was darüber hinausgeht, über
einen generischen "Experte"-Zugriff auf über 300 RouterOS-Menüs
erweiterbar, ohne für jedes einzelne ein eigenes Formular bauen zu
müssen.
Verbindet sich per REST-API (RouterOS ≥ 7.1) mit SSH-CLI-Fallback für
ältere Geräte/Firmware. Alle Schreibvorgänge zeigen vorher den exakten
Befehl, der ausgeführt wird — nichts passiert unangekündigt.
## Features
- **Verbinden** — REST-zuerst/SSH-Fallback-Verbindung, Zertifikats-/
SSH-Hostkey-TOFU, Geräte- und Routerboard-Infos (Modell, Seriennummer,
Firmware), RouterOS-Software-Update-Check inkl. Installation,
Routerboard-Firmware-Update, Neustart-Button. **Bekannte Router**:
merkt sich Host/Benutzername nach jeder erfolgreichen Verbindung mit
editierbarem Namen (Standard: Hardware-Bezeichnung wie "hEX") und
freiem Standort-Feld (Etage/Raum/Zweck), Liste scrollt ab ca. 4
Einträgen in sich selbst. Interface-Liste zeigt **Live-Traffic**: Punkt
grau/grün/pulsierend-grün je nachdem, ob der Port Verkehr führt.
- **Einrichten** — geführter Wizard (WAN → LAN → VLAN → WLAN → Firewall
→ Review/Apply) mit Einfach- und Experte-Modus. Mehrere LAN-Interfaces
mit eigenem DHCP-Server und optionaler Netzwerk-Isolation
(Firewall-Drop-Regeln zwischen Netzen).
- **Übersicht** — grafisches Diagramm des kompletten IST-Zustands
(Interfaces → IP-Adressen → DHCP/Pools → Routen → Firewall/NAT), mit
echten, aus RouterOS' eigenen Referenzfeldern abgeleiteten
Verbindungslinien, nach Verbindungsart eingefärbt, Hover/Klick hebt
Zusammenhänge hervor, Klick auf eine Verbindungslinie zeigt eine
verständliche Erklärung samt Sprung zu den verbundenen Elementen.
Ein Knoten (IP-Adresse, Pool, DHCP-Server/-Netzwerk/-Client, Route,
Firewall-Filter/-NAT-Regel, WireGuard-Peer) lässt sich direkt über
denselben Dialog wie im Experte-Tab bearbeiten und ans Gerät
zurückschreiben. Verbindungslinien laufen animiert in Flussrichtung
("von → nach"); Kästchen lassen sich frei verschieben (Linien folgen
live mit), ein Button setzt die Anordnung zurück.
- **LAN-Scanner** (vormals "Geräte") — DHCP-Leases + ARP + Bridge-Host-
Tabelle, eine Tabelle pro physischem Port, mit Live-Traffic (↓/↑ +
10-Sekunden-Sparkline) je Port-Überschrift. Der "Aktionen"-Button
hinter jedem Gerät (ersetzt den vorherigen, nicht eindeutig
erkennbaren Rechtsklick) weist eine feste IP-Adresse zu (RouterOS'
"Make Static") oder entfernt sie wieder — der Warnhinweis dazu
erklärt auch den Rückweg ("Aktionen" → "Feste Zuweisung entfernen",
danach Gerät kurz trennen/neu verbinden). **Netzwerk-Tools** (auch im
"Aktionen"-Menü): Ping/Traceroute/DNS-Auflösung vom Router aus, sowie
ein **Port-Scan** direkt von diesem Mac (TCP-Verbindungsversuch auf
~19 gängige Ports, farbig: rot=offen, grün=geschlossen, grau=keine
Antwort).
- **Experte** — kuratierte Formulare (mit Tooltips/Warnhinweisen) für
die wichtigsten RouterOS-Bereiche (Firewall/NAT/Mangle/Raw komplett,
plus Interfaces/IP/VPN/WLAN/Queues/System/Werkzeuge), plus ein
generischer "eigener Menüpfad"-Zugriff für alles, was nicht kuratiert
ist — kein RouterOS-Menü bleibt unerreichbar.
- **Sicherungen** — Konfiguration exportieren und wieder einspielen
(SFTP-Upload + RouterOS' dokumentierter Restore-Weg), mit
Modell-Abgleich als Brick-Schutz, wählbarer Speicherort, "Werks­ein­
stellungen wiederherstellen"-Notfallschalter.
- **Deutsch/Englisch** — Umschalt-Button in der Toolbar (persistiert über
Neustarts). Vollständig übersetzt: kompletter Experte-Tab (alle 9
Menü-Familien) und der Verbinden-Tab; weitere Tabs folgen
schrittweise.
## Architektur
```mermaid
flowchart TD
subgraph UI["SwiftUI-Tabs"]
Connect["Verbinden"]
Setup["Einrichten-Wizard"]
Overview["Übersicht"]
Devices["LAN-Scanner"]
Expert["Experte"]
Backup["Sicherungen"]
end
Connect --> CS["ConnectionService<br/>(geteilter State)"]
Setup --> CS
Overview --> CS
Devices --> CS
Expert --> CS
CS --> Decision{"REST-API<br/>verfügbar?"}
Decision -->|ja| REST["RestTransport"]
Decision -->|nein, Fallback| SSH["SSHTransport"]
Backup -. "eigene SSH-Verbindung<br/>(Backup/Restore/Werksreset/Update)" .-> SSH2["SSHTransport"]
Connect -. "eigene SSH-Verbindung<br/>(InterfaceTrafficMonitor, 3s-Polling)" .-> SSH3["SSHTransport"]
Devices -. "eigene SSH-Verbindung<br/>(NetworkToolsService: Ping/Traceroute/DNS)" .-> SSH4["SSHTransport"]
Devices -. "direkte TCP-Verbindung<br/>(PortScanner, nicht über den Router)" .-> LANDevice[("Gerät im LAN")]
Connect --> Saved["SavedRoutersStore<br/>(Bekannte Router)"]
Saved --> Defaults[("UserDefaults<br/>(lokal, kein Router-Zugriff)")]
REST --> Router[("Mikrotik<br/>RouterOS-Router")]
SSH --> Router
SSH2 --> Router
SSH3 --> Router
SSH4 --> Router
```
`ConnectionService` ist der einzige zwischen den Tabs geteilte State
(REST-zuerst, SSH-Fallback). Einmalige System-Aktionen (Backup,
Wiederherstellung, Werksreset, Updates) laufen bewusst über eine jeweils
eigene, dedizierte SSH-Verbindung statt über den aktiven Live-Transport —
`InterfaceTrafficMonitor` (3-Sekunden-Polling der Live-Interface-
Durchsätze) und `NetworkToolsService` (Ping/Traceroute/DNS-Auflösung im
LAN-Scanner-Tab) folgen demselben Muster, da die zugrundeliegenden
RouterOS-Befehle (`/interface monitor-traffic`, `/ping`,
`/tool traceroute`, `/resolve`) reine CLI-Befehle ohne REST-Äquivalent
sind. `PortScanner` (ebenfalls LAN-Scanner-Tab) geht dagegen gar nicht
über den Router — ein reiner TCP-Verbindungsversuch direkt von diesem Mac
zum jeweiligen LAN-Gerät, da RouterOS selbst keinen Portscanner anbietet.
Ein generischer Menü-Engine (`fetchMenuItems`/`fetchFieldValues`) macht
praktisch jedes RouterOS-Menü lesbar, auch ohne kuratiertes Schema —
darauf bauen Übersicht-, LAN-Scanner- und Experte-Tab gemeinsam auf,
ebenso `ConnectionService.
checkPortConflict(interfaceName:)` für die LAN-Port-Konflikt-Prüfung im
Einrichten-Assistenten. `SavedRoutersStore` (Bekannte Router) ist bewusst
komplett lokal — ein JSON-Array in `UserDefaults`, kein Router-Zugriff;
nur die zugehörigen Passwörter liegen weiterhin im macOS-Schlüsselbund.
## Meilensteine
| # | Feature | Status |
|---|---|---|
| M1M4 | Projektgerüst, Connect, Backup, WAN/LAN/DHCP, VLAN | ✅ live verifiziert |
| M5 | WLAN-Schritt | 🔶 nur "kein WLAN"-Zweig getestet |
| M6 | Firewall-Grundschutz | ✅ live verifiziert |
| M7 | Härtung (SSH-Hostkey-TOFU) | 🔶 TOFU + REST-Schreibpfad live verifiziert, Verbindungsabbruch-mitten-im-Apply noch offen |
| M8 | Mehrere LAN-Interfaces + Netzwerk-Isolation | ✅ live verifiziert |
| M9 | Einfach/Experte-Modusschalter im Wizard | 🔶 gebaut, UI-Test offen |
| M10 | Experte-Tab (generischer RouterOS-Zugriff) | ✅ live verifiziert |
| M11 | Übersicht-Tab (IST-Zustand-Diagramm) | ✅ live verifiziert |
| M12 | Geräte-Tab (LAN-Scanner + Static-IP) | ✅ live verifiziert |
| M13 | Backup-Wiederherstellung | ✅ live verifiziert |
| M14 | Update-Check (Software + Firmware) | ✅ live verifiziert |
| M15 | Übersicht-Tab: Diagramm-Fixes + Direktes Bearbeiten | ✅ live verifiziert |
| M16 | Zweisprachigkeit (DE/EN), begonnen im Experte-Tab | ✅ live verifiziert |
| M17 | Bekannte Router (Verbinden-Tab), Standort-Feld, Scroll-Cap | ✅ live verifiziert |
| M18 | Live-Traffic-Anzeige an Interfaces (Verbinden-Tab) | ✅ live verifiziert |
| M19 | Übersicht-Tab: Flussanimation + verschiebbare Knoten | ✅ live verifiziert |
| M20 | LAN-Scanner: Umbenennung, Netzwerk-Tools (Ping/Traceroute/DNS/Port-Scan) | ✅ live verifiziert |
| M21 | Zweisprachigkeit (DE/EN) auf alle fünf Tabs ausgerollt (Einrichten/Übersicht/LAN-Scanner/Sicherungen) | ✅ live verifiziert |
| M22 | REST-Transport (M7) erstmals live gegen Hardware verifiziert, 4 Bugs gefunden+gefixt | ✅ live verifiziert |
| M23 | Experte-Tab: Sektionsüberschriften prominenter+eingefärbt, einklappbar (Standard: zugeklappt) | ✅ live verifiziert |
| M24 | LAN-Scanner: "Aktionen"-Button statt Rechtsklick, Traffic-Monitor+Sparkline pro Port, ARP-Bug gefixt | ✅ live verifiziert |
| M25 | Einrichten-Wizard-Politur: WAN-Zurück-Button, prominente Aktionsbuttons, leere Platzhalter-Felder (LAN/VLAN) | ✅ live verifiziert |
| M26 | Bekannte Router: Seriennummer hinterlegt, trennt zwei Geräte mit identischem Host+Benutzername | ✅ live verifiziert |
| M27 | Passwort-Anzeige-Button, Schlüsselbund nach Seriennummer getrennt, `terse`-Fallback verallgemeinert | ✅ live verifiziert |
| — | LAN-Port-Konflikt-Prüfung + "Fertig"-Button (Einrichten) | 🔶 gebaut, Live-Test offen |
Ausführlicher Stand inkl. aller gefundenen Bugs, offener Punkte und
Session-Verlauf: [`HANDOFF.md`](HANDOFF.md) / [`CHATLOG.md`](CHATLOG.md).
## Projektstruktur
```
RouterOS/
├── RouterOSAssistant/ — App-Quellcode (SwiftUI, macOS 14+)
│ ├── App/
│ │ └── RouterOSAssistantApp.swift — Einstiegspunkt, TabView, geteilter ConnectionService
│ ├── Core/
│ │ ├── Models/
│ │ │ ├── RouterOSCommand.swift — eine Änderung, vier Operationen (add/set/remove/action)
│ │ │ ├── WanConfig.swift, LanDhcpConfig.swift, VlanEntry.swift,
│ │ │ │ WifiNetworkConfig.swift, FirewallConfig.swift — bauen je RouterOSCommand-Listen
│ │ │ ├── RouterOSMenuItem.swift — generisches Item für jeden RouterOS-Menüpfad
│ │ │ ├── RouterOSSchema.swift / RouterOSSchemaCatalog.swift — kuratierte Formular-Schemas (Experte-Tab)
│ │ │ ├── OverviewGraph.swift — Knoten/Kanten-Modell fürs Übersicht-Diagramm
│ │ │ ├── LanDevice.swift — ein Gerät im LAN-Scanner-Tab (Lease+ARP+Bridge-Host verschmolzen)
│ │ │ ├── SavedRouter.swift — ein Eintrag in "Bekannte Router" (Host/Name/Standort)
│ │ │ ├── PortConflict.swift — LAN-Port-Konflikt-Prüfung (Bridge/Adresse/DHCP-Client/PPPoE)
│ │ │ ├── InterfaceTraffic.swift — ein Live-Durchsatz-Sample + TrafficSample (10s-Sparkline-Historie, LAN-Scanner)
│ │ │ ├── NetworkToolResult.swift — Rohausgabe von Ping/Traceroute/DNS-Auflösung
│ │ │ ├── PortScanResult.swift — Ergebnis eines Port-Scans, ein Eintrag pro Port
│ │ │ └── RouterOSModels.swift — Credentials, DeviceInfo, RouterBoardInfo, PackageUpdateInfo, Fehler
│ │ ├── Networking/
│ │ │ ├── RouterOSTransport.swift — Protocol: connect/fetch.../apply/disconnect
│ │ │ ├── RestTransport.swift — REST-API (RouterOS ≥7.1)
│ │ │ ├── SSHTransport.swift — SSH-Fallback via Citadel, generischer CLI-Zugriff, SFTP-Upload
│ │ │ ├── RouterOSCliParser.swift — parst CLI-Ausgaben generisch
│ │ │ └── CertificateTrustStore.swift / SSHHostKeyTrustStore.swift — TOFU
│ │ └── Services/
│ │ ├── ConnectionService.swift — zentraler App-State
│ │ ├── BackupService.swift — Sicherung erstellen/auflisten/wiederherstellen
│ │ ├── FactoryResetService.swift — Werksreset ("Gefahrenzone")
│ │ ├── UpdateService.swift — Software-/Firmware-Update, Neustart
│ │ ├── KeychainService.swift — Passwort-Speicherung
│ │ ├── SavedRoutersStore.swift — "Bekannte Router"-Liste (JSON in UserDefaults)
│ │ ├── InterfaceTrafficMonitor.swift — pollt Live-Durchsatz über eigene SSH-Verbindung
│ │ ├── NetworkToolsService.swift — Ping/Traceroute/DNS-Auflösung über eigene SSH-Verbindung
│ │ └── PortScanner.swift — TCP-Port-Scan direkt von diesem Mac (Network.framework)
│ ├── Core/Localization/
│ │ └── L10n.swift — DE/EN-Übersetzungshelfer (Dictionary-Lookup, kein String Catalog)
│ ├── Features/
│ │ ├── Wizard/Steps/Connect/ — Verbinden-Tab
│ │ ├── Wizard/Steps/Setup/ — Einrichten-Tab (Mode→Wan→Lan→Vlan→Wifi→Firewall→Review)
│ │ ├── Overview/ — Übersicht-Tab
│ │ ├── Devices/ — LAN-Scanner-Tab
│ │ ├── Expert/ — Experte-Tab
│ │ └── Backup/ — Sicherungen-Tab
│ └── Resources/Assets.xcassets/ — App-Icon
├── RouterOSAssistantTests/ — Unit-Tests (Command-Builder, CLI-Parser, ViewModels, Mock-Transport)
├── project.yml — xcodegen-Projektdefinition (Quelle der Wahrheit, nicht das generierte .xcodeproj editieren)
├── HANDOFF.md — detaillierter technischer Stand, alle gefundenen Bugs, offene Punkte
└── CHATLOG.md — chronologischer Session-Verlauf
```
## Setup / Bauen
```bash
xcodegen generate # erzeugt RouterOSAssistant.xcodeproj (nicht in git)
open RouterOSAssistant.xcodeproj # oder direkt per xcodebuild
# Debug
xcodebuild -project RouterOSAssistant.xcodeproj -scheme RouterOSAssistant \
-destination 'platform=macOS' build
# Tests
xcodebuild -project RouterOSAssistant.xcodeproj -scheme RouterOSAssistant \
-destination 'platform=macOS' test
# Release + Deploy nach /Applications
xcodebuild -project RouterOSAssistant.xcodeproj -scheme RouterOSAssistant \
-configuration Release build
```
`xcodegen` ist via Homebrew installiert. `.xcodeproj`, `DerivedData` und
Router-Backups sind gitignored.
## Sicherheit
Jede Schreibaktion zeigt vor der Ausführung den exakten RouterOS-Befehl
in einem Bestätigungsdialog. Destruktive Aktionen (Werksreset, Backup-
Wiederherstellung) liegen in einer eigenen "Gefahrenzone" mit
zusätzlichen Warnhinweisen. Zertifikate und SSH-Hostkeys werden per
Trust-on-First-Use (TOFU) behandelt, nicht blind akzeptiert.