§1
RoamSwitch für Linux ist eine residente Netzwerksicherheits- und Systemdiagnoseanwendung, die das Zero-Trust-Netzwerkverteidigungsmodell von macOS RoamSwitch auf Linux (systemd + nftables-Umgebungen) bringt.
Diese Edition zielt auf Client-Maschinen (Workstations, Laptops, Einplatinencomputer) ab und setzt autonomes Verhalten voraus, das der Maschine folgt, wenn sie sich zwischen Netzwerken bewegt. Eine gehärtete Server-/Headless-Infrastruktur-Edition (RoamSwitch Server Edition – Always-on-Default-Deny, Critical-Path-FIM-Integrität, Remote-Webhooks und statische Richtliniendurchsetzung) wird als dedizierter Server-Build bereitgestellt.
Es identifiziert das verbundene WLAN/kabelgebundene Netzwerk anhand seiner Gateway-MAC-Adresse und schaltet selbstständig das aktive nftables-Firewallprofil um. Darüber hinaus bietet es drei Ebenen der Man-in-the-Middle-Verteidigung (MITM) in nicht vertrauenswürdigen Netzwerken: einen VPN-Tunnel + Kill-Switch (WireGuard oder Tailscale, die primäre Verteidigung), eine präventive ARP/NDP-Sperre und ARP-Spoof-Erkennung. Hinzu kommen verhaltensbasierte Ransomware-Erkennung (Fanotify + Shannon-Entropie + Kanarienvögel), ein passiver Link Guard, der Phishing-Verbindungen kennzeichnet oder blockiert (NFQUEUE + SNI), ein Port Anomaly Guard, BadUSB-Abwehr, Gegenmaßnahmen gegen Kernel Local Privilege Escalation (LPE) (als Abschwächung von Frag Gap CVE-2026-53362 lässt sich die Ablehnung nicht privilegierter Benutzer-Namensräume in nicht vertrauenswürdigen Netzwerken optional aktivieren; standardmäßig deaktiviert), eBPF-Laufzeit-Bedrohungssensor-Integration (Falco/Tetragon) mit Einfrieren des angreifenden Prozesses im Millisekundenbereich (SIGSTOP) und automatischer Air-Gap-Isolation, eine 27-Punkte-Bewertung des Sicherheitszustands und ein integrierter Model Context Protocol (MCP)-Server.
Dieses Whitepaper beschreibt die Architektur, das Bedrohungsmodell und das Design jedes Abwehrmechanismus – und insbesondere, wie das Prinzip „vollständig lokale Verarbeitung; standardmäßig verlässt nur eine Anfrage nach signierten Erkennungsdaten die Maschine, und sie enthält nichts über Sie“ auf Codeebene sichergestellt wird. Opt-in-Funktionen, die ein Betreiber ausdrücklich aktivieren muss (etwa die Ereignisweiterleitung), sind Ausnahmen von diesem Standard; sie sind alle in der folgenden Tabelle und in §9.4 aufgeführt. Es vermeidet Marketingsprache; die Aussagen lassen sich am tatsächlichen Verhalten des verteilten Pakets (Binärdatei) und an der Selbstprüfung im Anhang überprüfen. RoamSwitch für Linux ist proprietäre Freeware, der Quellcode wird nicht veröffentlicht (§11).
| Prinzip | Detailliert |
|---|---|
| Null-Telemetrie | Das Produkt sendet standardmäßig keinerlei Informationen über Sie oder Ihr Gerät nach außen. Es gibt weder Telemetrie, Analysen, Absturzberichte, Nutzungsstatistiken, Fernkonfiguration noch einen Lizenzaktivierungsserver. Kommunizieren können nur die Opt-in-Funktionen, die ein Betreiber ausdrücklich aktiviert; sie stehen in der nächsten Zeile („Ausnahmen vom Standard“) und in 9.4. |
| Ausnahmen vom Standard (alle Opt-in) | Die folgenden Funktionen kommunizieren nur dann nach außen, wenn ein Betreiber sie ausdrücklich aktiviert. Ziele sind ausschließlich die vom Betreiber konfigurierten; es gibt keine eingebauten Ziele. (1) Ereignisweiterleitung (forward_enabled, Standard AUS) – sendet Erkennungsereignisse an ein vom Betreiber angegebenes Syslog / eine JSON-Lines-Datei / einen signierten Webhook. (2) Fleet (Business-Stufe, nur geräteseitiger Code) – ein nicht registriertes Gerät sendet nichts und löst nicht einmal den Fleet-Hostnamen auf; der Verwaltungsdienst ist weder bereitgestellt noch veröffentlicht. Alles Weitere, einschließlich vom Benutzer ausgelöster Update-Prüfungen, steht in 9.4. |
| Nur Updates empfangen | Die einzige ausgehende Anfrage, die das Produkt standardmäßig stellt, ist ein täglicher GET auf ein festes, signiertes Manifest unter lafine.net/updates/v1. Ist ClamAV installiert, startet jeder Lauf zusätzlich ClamAVs eigenes Aktualisierungswerkzeug freshclam; dieser Datenverkehr gehört zu ClamAV und ist gesondert in §9.4 aufgeführt. Aus dem Manifest bezieht das Produkt die Betrugsseitenliste für den Link Guard, die neueste App-Version, die CVE-Karten für Kernel, OS-Pakete (Debian / Ubuntu / Arch / RHEL-Familie / SUSE) und Sprachpakete (npm / PyPI / crates.io / RubyGems / Packagist / Go / Maven), die CVE-Karte für den aktiven Schwachstellenscan und die Liste beliebter npm-Paketnamen für die Typosquatting-Erkennung. Täglich geholt werden nur das Manifest und seine Signatur (zwei GETs); die Link-Guard-Liste, die CVE-Karte für den aktiven Scan und die npm-Liste nur, wenn das Manifest eine neuere Version zeigt, die Kernel- und Paket-CVE-Karten nur, wenn seit der letzten Aktualisierung etwa 30 Tage vergangen sind. Die Ubuntu-CVE-Karte wird nur von Geräten mit einer unterstützten Ubuntu-Version geholt; ein Gerät, das sie noch nicht hat, holt sie beim nächsten täglichen Lauf, ohne die 30 Tage abzuwarten. Die Anfrage enthält keinen Query-String und keine Cookies, der einzige Header, der die Software nennt, ist ein fester User-Agent: RoamSwitch-Updater, und es sind keine Informationen über Sie enthalten. updates.enabled = false schaltet sie vollständig ab; das Produkt läuft dann mit mitgelieferten Daten und hat, solange keine Opt-in-Funktion aktiviert ist, keinen externen Kontakt. |
| Vollständig lokale Verarbeitung | Jede Bewertung, Erkennung und Prüfung wird vollständig auf dem lokalen Computer ausgeführt. URL-Sicherheitsanalysen und geheime Scans werten ihre Eingaben heuristisch aus, ohne sie irgendwohin zu übertragen. |
| Geringeste Berechtigung | Privilegierte Operationen sind auf einen Root-Daemon beschränkt; UI, CLI und MCP-Server fordern sie über eine IPC per Unix-Domain-Socket an. Der Daemon öffnet standardmäßig keinen TCP/UDP-Socket (Ausnahme sind die Opt-in-Funktionen, die ein Betreiber aktiviert, §9.4); der Link-Guard nutzt ausschließlich den AF_NETLINK-NFQUEUE-Verdict-Kanal (Kernel ↔ Userspace, kein Paketaustritt). Zustandsändernde IPC-Aufrufe werden nur von root oder von einer UID mit lokaler Anmeldesitzung angenommen (ab 1.10.4; lesende Aufrufe bleiben unverändert). |
| Fehler geschlossen | Air-Gap (Notfallisolierung) überlebt einen Daemon-Neustart und wird innerhalb von Sekunden wieder aktiviert, wenn seine Regeln extern gelöscht werden. |
| Offline-Lizenzierung | Pro-/Business-Lizenzen werden ausschließlich durch die Ed25519-Signaturprüfung überprüft. Es erfolgt kein Aufruf an einen Aktivierungsserver. |
§2
RoamSwitch für Linux zielt hauptsächlich auf Laptops/mobile Workstations ab, die zwischen nicht vertrauenswürdigen Netzwerken wechseln.
Angreifer im Visier
- ___
- Bösartige USB-Geräte (BadUSB) – Vortäuschen einer Tastatur und Einschleusen von Tastenanschlägen, bevor der Bildschirm gesperrt wird; unregistrierter USB-Massenspeicher zur Datenexfiltration oder zum Einschleusen von Schadsoftware.
- Ransomware/dateilose Malware – Eindringen über eine heruntergeladene Datei und Massenverschlüsselung der Dokumente des Benutzers.
- DNS-basiertes C2 und Phishing – Malware, die Namensauflösung nutzt, um einen C2-Server oder eine Phishing-Site zu erreichen.
Außerhalb des Gültigkeitsbereichs
- Ein Angreifer, der bereits Wurzeln schlägt; Rootkits auf Kernel- oder Firmware-Ebene.
- Angriffe, die die Festplatte physisch entfernen (die Domäne der vollständigen Festplattenverschlüsselung; RoamSwitch diagnostiziert, ob eine Verschlüsselung vorhanden ist, führt jedoch keine Verschlüsselung durch).
- Proximity Wireless Sharing-Steuerung im AirDrop-Stil (kein Betriebssystem-nativer Mechanismus unter Linux; nicht unterstützt).
§3
RoamSwitch für Linux ist in Rust implementiert, und das Paket enthält acht ausführbare Dateien (roamswitch-daemon, roamswitch-app, roamswitch (CLI), roamswitch-mcp, roamswitch-updater, roamswitch-honeytokens, roamswitch-incident-capture und das experimentelle, standardmäßig deaktivierte roamswitch-xdp-gate). Die gemeinsame Logik liegt in der Bibliothek roamswitch-core, und roamswitchkit ist das Client-SDK. Die gesamte Kommunikation mit dem Daemon erfolgt über /run/roamswitch/roamswitch.sock (einen Unix-Domänen-Socket). Es gibt keinen lauschenden TCP/UDP-Socket im Daemon, in der App oder im MCP-Server. Das Einzige, was die App per bind öffnet, ist ein einzelner Unix-Socket, um eine zweite Instanz zu verhindern.
# Userspace (unprivilegiert) roamswitch-app GTK3 + AppIndicator-Tray roamswitch (CLI) Schlankes Shell-Frontend roamswitch-mcp stdio JSON-RPC (von AI-Clients gestartet) │ │ AF_UNIX /run/roamswitch/roamswitch.sock (nur lokales IPC) ▼ roamswitch-daemon root / systemd Type=notify + WatchdogSec=30 ・nftables-Profilsteuerung (inet roamswitch-Tabelle) ・Sentinel-Schleife (Netzwerkerkennung & Profildurchsetzung) ・VPN-Tunnel + Kill-Switch (WireGuard: wg-quick / roamswitch_vpn, Tailscale: roamswitch_ts) ・Präventive ARP/NDP-Sperre (Neigh-Tabellen-Pin) / Erkennung ・Port-Anomalie-Wächter (roamswitch_dev_guard) ・fanotify-Wächter (Ransomware / Malware) ・Link Guard (NFQUEUE — inet roamswitch_linkguard) ・Canary-Engine / Quarantäne-Vault ・Kernel-LPE-Gegenmaßnahmen (Ablehnung nicht privilegierter userns optional, standardmäßig aus) ・eBPF-Laufzeitintegration (/var/run/roamswitch/events.sock) ・SIGSTOP-Einfrieren angreifender Prozesse im Millisekundenbereich & Air-Gap-Kopplung ・USB-Überwachung (evdev EVIOCGRAB — BadUSB) / Freigabe-Warteschlange ・Ed25519-Lizenzprüfung roamswitch-updater Ein eigenständiger systemd-Timer-Helfer. Das einzige Crate mit HTTP/TLS-Stack (täglicher signierter Manifest-GET) roamswitch-honeytokens Vom Daemon gestarteter Hilfsprozess (legt Köder-Zugangsdaten an und überwacht sie) roamswitch-incident-capture Vom Daemon gestarteter Hilfsprozess (sammelt bei der Eindämmung ein Beweispaket) roamswitch-core Reine Logikbibliothek (von allen Crates geteilt) roamswitchkit MCP-Client-SDK
| Komponente | Privileg | Rolle |
|---|---|---|
| roamswitch-daemon | root (systemd, Type=notify + WatchdogSec=30) | Alle privilegierten Operationen. Steuert als einzelner Autor nftables, DNS und systemd-Einheiten. |
| Roamswitch-App | Login-Benutzer | GTK3 GUI + AppIndicator-Fach. Nur Konfigurationsbearbeitung und -visualisierung; Jede privilegierte Aktion durchläuft IPC. |
| Roamswitch (CLI) | Login-Benutzer | Dünnes Shell-Frontend mit demselben IPC-Sockel. |
| roamswitch-mcp | Vom KI-Client erzeugter Prozess | stdio JSON-RPC. Stellt schreibgeschützte Diagnoseinformationen bereit. |
Die gesamte Kommunikation mit dem Daemon erfolgt über /run/roamswitch/roamswitch.sock (das Verzeichnis hat 0755, der Socket 0666). Die Zugriffskontrolle beruht nicht auf Dateiberechtigungen, sondern auf der Prüfung des Aufrufers: Der Daemon liest die UID der Gegenstelle über SO_PEERCRED, weist Systemkonten ab (UIDs 1 bis 999 und nobody) und nimmt zustandsändernde Aufrufe nur von root oder von einer UID an, die eine lokale Login-Sitzung besitzt (§1). Die Benutzerkonfiguration wird als Klartext-JSON unter ~/.config/roamswitch/config.json gespeichert. Der Daemon durchsucht und liest /home/*/.config/roamswitch/config.json mit Root-Rechten (er läuft mit HOME=/root). Akzeptiert wird nur eine Datei, die dem Konto selbst gehört, kein symbolischer Link ist und für andere Benutzer nicht beschreibbar ist. Die Konfiguration verlässt nie die Maschine; es gibt keine Kontoregistrierung und keine Cloud-Synchronisierung.
§4
Die Sentinel-Schleife (3-Sekunden-Zyklus) liest den MAC des Standard-Gateways von /proc/net/arp und ip neigh und gleicht ihn mit den registrierten MACs in config.json ab. MAC wird anstelle von SSID verwendet, da eine SSID auf einfache Weise gefälscht werden kann. Die beim Profilwechsel angezeigte Desktop-Benachrichtigung nennt den Grund für den Wechsel („ein nicht registriertes Netzwerk“ / „Ihre Einstellung für das registrierte Netzwerk X“ / „keine Netzwerkverbindung“).
| Profil | Situation | nftables-Verhalten |
|---|---|---|
| offen (vertrauenswürdig) | Ein registriertes Heim- oder Firmennetzwerk | policy accept. Lokaler Verkehr erlaubt. |
| ausgeglichen | Nicht registriert, aber als relativ sicher konfiguriert | Eingehender Verkehr standardmäßig verweigert. Nur bestehende Verbindungen, lo und ICMP / ICMPv6 erlaubt; offene Ports werden überwacht. |
| lockdown (Auswärtsschutz) | Öffentliches WLAN / nicht registriertes Netzwerk | Alle eingehenden Pakete werden im Stealth-Modus verworfen. Freigabedienste werden automatisch gestoppt und beim Wechsel zurück in ein vertrauenswürdiges Netz wiederhergestellt (standardmäßig an, jederzeit abschaltbar). |
Alle Regeln sind in einer dedizierten nftables-Tabelle mit dem Namen inet roamswitch isoliert und kollidieren nie mit anderen Firewall-Konfigurationen (ufw/firewalld). Der Ablauf der manuellen Überschreibung (1 Stunde / 2 Stunden / 4 Stunden / bis Mitternacht / bis zur Löschung / bis zur nächsten Trennung) wird vom Daemon als einzigem Autor erzwungen. Die GUI schreibt niemals einen Ablauf; Es liest den config.json, den der Daemon beim nächsten Tick neu geschrieben hat, erneut und spiegelt ihn in der Benutzeroberfläche wider (wodurch ein Konflikt vermieden wird).
Air-Gap (Notfall-Netzwerkisolierung)
Ein vollständiger Isolationsmodus, der policy drop (Priorität -100) sowohl für die Eingabe- als auch für die Ausgabe-Hooks der Tabelle inet roamswitch festlegt und nur lo zulässt.
- Fail close – Beim Neustart des Daemons wird durch die Erkennung der Markierungsdatei (
/run/roamswitch/airgap.active) die Isolation erneut sichergestellt. - Selbstheilend – Wenn ein externer Prozess die Regeln mit
nft delete tablelöscht, wird die Sentinel-Schleife innerhalb von Sekunden erneut angewendet. - Auslöser mit geringer Konfidenz enden per kurzem Timer — ein einfaches manuelles Air-Gap ohne Warnkontext (eine GUI-Schaltfläche oder
roamswitch airgap) ist ein Auslöser mit geringer Konfidenz und wird über einen kurzen Timer (airgap_low_confidence_secs, Standard 600 Sekunden) vollständig aufgehoben, damit ein versehentlicher Klick oder ein Fehlalarm die Maschine nicht lange vom Netz trennt. Eine ARP-Anomalie außerhalb von lockdown, eine Port-Anomalie und ein eBPF-Ereignis der Stufe Error oder darunter werden in der gemeinsamen Zustandsmaschine ebenfalls als gering konfident eingestuft, doch der Client löst dafür nie automatisch ein Air-Gap aus; sie führen nur zu einer Benachrichtigung oder einem Protokolleintrag oder sperren den einzelnen Port. - Auslöser mit hoher Konfidenz stellen nie stillschweigend wieder her — Kanarien-Manipulation, ein eBPF-Ereignis Emergency/Alert (ein Ereignis der Stufe Critical nur, wenn sich der einzelne Prozess nicht eindämmen ließ), ARP-Spoofing unter lockdown, an dem das Gateway beteiligt ist, und ein als Reaktion auf eine ARP-Warnung ausgelöstes Air-Gap (sowie, nur bei Opt-in, eine Regel des Ausführungsrekorders mit hohem Schweregrad; §5) werden nicht automatisch aufgehoben, egal wie viel Zeit vergeht. Ab dem kurzen Timer wird in jedem Zyklus geprüft, ob die Ursache fortbesteht (eingefrorene PID noch aktiv, Kanarie erneut überschrieben, ARP-Anomalie hält an usw.); nur wenn die Ursache nachweislich beseitigt ist, wird mit Benachrichtigung aufgehoben. Eine nicht eindeutige Prüfung gilt als „nicht behoben“. Ein Ransomware-Entropie-Burst löst zusätzlich zum Einfrieren des Prozesses mit
SIGSTOPund einer Benachrichtigung auch ein Air-Gap aus und gilt ebenso als Auslöser mit hoher Konfidenz. - DEGRADED-Modus — erreicht eine Isolation mit hoher Konfidenz die Obergrenze (
airgap_hard_cap_secs, Standard 3600 Sekunden;0= keine Obergrenze), ohne dass der Benutzer sie aufhebt und ohne nachgewiesen beseitigte Ursache, wechselt sie in DEGRADED. Beim Client ist DEGRADED so streng wie FULL – alles außer Loopback wird verworfen, auch bestehende Verbindungen; der Unterschied ist, dass es sich niemals per Timer wieder öffnet. Aufgehoben wird durch den lokalen Benutzer (GUI-Schaltfläche oderroamswitch emergency-restore) oder durch eine Neuprüfung, die das Verschwinden der Ursache nachweist. Air-Gap sperrt standardmäßig auch das WLAN-Funkmodul per rfkill (airgapAutoRfkill); DEGRADED lässt es gesperrt, sofernairgap_degraded_lift_rfkillnicht auf true steht. - Übergänge werden protokolliert und gemeldet — der Wechsel von FULL nach DEGRADED, jede Art automatischer Aufhebung und eine Aufhebung durch den Benutzer werden in der Vorfall-Zeitleiste festgehalten und lösen eine Desktop-Benachrichtigung aus. Der Isolationszustand liegt in
/run/roamswitch/airgap_isolation.jsonund übersteht einen Daemon-Neustart (ein Neustart setzt den Zähler aufeinanderfolgender ARP-Prüfungen zurück, was zugunsten der fortbestehenden Isolation ausfällt – fail-closed).
table inet roamswitch {
chain input {
type filter hook input priority -100; policy <accept|drop>;
iif "lo" accept
ct state established,related accept
# open ist policy accept ohne Regeln; balanced / lockdown sind policy drop (ICMP / ICMPv6 sind nur in balanced erlaubt)
}
chain output {
type filter hook output priority -100; policy <accept|drop>;
# Bei Air-Gap (Isolation) wird dieselbe Tabelle neu aufgebaut: input und output mit policy drop, nur lo ist erlaubt (auch bestehende Verbindungen werden nicht durchgelassen)
}
}
Passiver Link Guard (Erkennung von Phishing-Verbindungen)
Der Daemon überwacht, wohin ausgehende Verbindungen gehen, und markiert bzw. blockiert Verbindungen zu gefährlichen Hosts, wenn es sich um die eng gefasste Gruppe „eindeutig Phishing“ handelt. Es ersetzt den älteren Paste-a-URL-Checker, der ein Eingreifen des Benutzers erforderte.
- Interception – eine dedizierte nftables-Tabelle
inet roamswitch_linkguardbindet den Pfadoutputein und stellt DNS-Fragen und neue/frühe Webverbindungen über NFQUEUE in die Warteschlange für einen Userspace-Worker. NFQUEUE ist ein Kernel↔Userspace-Urteilskanal überAF_NETLINK; Der Daemon bindet keinen Socket und generiert kein Paket. Die Warteschlangenregeln tragenbypass, sodass der Datenverkehr ungehindert durchläuft, wenn der Worker nicht ausgeführt wird (Air-Gap bleibt der separate harte Stopp). - Hostname-Quellen – der DNS-Fragename, der TLS-ClientHello SNI (damit ein Browser, der DoH verwendet, immer noch durch den Hostnamen abgedeckt wird) und der Klartext-HTTP-Header
Host. Encrypted ClientHello (ECH), sobald es weit verbreitet ist, ist ein bekannter blinder Fleck. - Verdict (
roamswitch-core, reine Logik) – ein Host wird anhand des lokalen Phishing-/Bedrohungs-Feeds und einer Reihe von Offline-Heuristiken überprüft: IDN/verwechselbares Homograph einer geschützten Marke, Markentoken in einer nicht offiziellen Domäne, Raw-IP-Host, TLD mit hohem Risiko.
Modus (linkGuard.mode) | Feed-Hit oder Markenhomograf | Andere verdächtige Signale |
|---|---|---|
off | nicht geprüft | nicht geprüft |
warn | Verbindung hielt bis zu 8 s + eine Aufforderung zur Genehmigung/Blockierung | Weder Benachrichtigung noch Blockierung |
block (Standard) | Verbindung getrennt + ein Zulassungsdialog (einmal pro Host) | Weder Benachrichtigung noch Blockierung |
Hart blockiert wird nur ein Feed-Treffer oder ein Host mit Markenhomograph; alles, was die Heuristik allein kennzeichnet, bleibt ein Urteil auf Warnstufe, ohne Blockierung und ohne Benachrichtigung. Der warn-Modus hält die Verbindung zu einem gefährlichen Host bis zu 8 Sekunden an, während der Benutzer gefragt wird; läuft die Sperre ohne Antwort ab, ist sie fail-closed (die Pakete werden verworfen und das Urteil wird nicht zwischengespeichert). Eine ausbleibende Antwort auf „Ist diese Site in Ordnung?“ darf nicht als „Ja“ gelten; beim nächsten Versuch wird erneut gefragt. Im block-Modus werden eine Benachrichtigung und ein Zulassungsdialog nur einmal pro Host angezeigt (ein Browser, der viele Verbindungen zum gleichen blockierten Host öffnet, überflutet die Benachrichtigungen nicht mehr). In einem Genehmigungsdialog für ein gefährliches Ziel ist die Standardschaltfläche „Weiter blockieren“, und „Zulassen“ ist die unauffällige, nicht voreingestellte Option. Wählt man im Genehmigungsdialog „Zulassen“, wird der blockierte Host dauerhaft zu linkGuard.allowlist hinzugefügt und passiert, bis er in den Einstellungen wieder entfernt wird.
DNS wird überprüft, nie gefälscht: Eine DNS-Frage auf der Blockliste erzeugt nur eine Benachrichtigung; die Durchsetzung erfolgt auf der nachfolgenden TCP-Verbindung, sodass RoamSwitch niemals eine synthetische DNS-Antwort einfügt. Der Feed ist eine zusammengestellte Liste von Phishing-/Betrugsdomänen, die im Paket geliefert und vom täglichen Updater aktualisiert wird (§11). Auch wenn kein Feed vorhanden ist, werden die Offline-Heuristiken weiterhin ausgeführt. Die Ed25519-Signatur und der SHA-256 des Feeds werden vom täglichen Updater geprüft, bevor er etwas installiert; nicht passende Daten werden nicht übernommen. Der Link Guard lädt den installierten Feed (oder den im Paket mitgelieferten); ist keiner von beiden vorhanden, arbeitet er „nur mit Heuristiken“ und niemals mit „alles zulassen“.
VPN-Tunnel + Kill-Switch (die primäre MITM-Verteidigung)
Anti-MITM-Schutz, der nicht von der Integrität der Schicht 2 abhängt. In einem nicht vertrauenswürdigen Netzwerk macht ein ständig aktiver verschlüsselter Tunnel zu einem vertrauenswürdigen Endpunkt lokales ARP/NDP-Spoofing, Rogue-DHCP und passives Sniffing irrelevant – der Angreifer sieht nur Chiffretext. Die ARP/NDP-Sperre und die folgende Erkennung sind für diese Funktion zweitrangig.
Zwei Backends zur Auswahl – „WireGuard (Konfigurationsdatei)“ oder „Tailscale (Ausgangsknoten)“. RoamSwitch implementiert keine eigene Kryptografie und ist kein VPN-Anbieter. Beide Backends sind optionale Abhängigkeiten; Wenn nicht, zeigt die GUI den Installationsbefehl an.
(A) WireGuard-Backend
- Es wird kein VPN-Server bereitgestellt – verwendet eine WireGuard-Konfiguration, die der Benutzer bereitstellt: eine
.confvon einem Anbieter wie Mullvad, IVPN oder Proton VPN oder den eigenen WireGuard-Server des Benutzers (ein VPS oder ein Heimserver). Es wird keine Standardkonfiguration ausgeliefert. - Config – der Daemon validiert den
.confund speichert ihn unter/etc/wireguard/roamswitch.conf(0600, Schnittstelleroamswitch). Es kann nicht anderswo leben: Das AppArmorwg-quick-Profil unter Ubuntu 24.04+ / Debian 13 verweigertwg-quickdas Lesen eines.confaußerhalb von/etc/wireguard/– selbst als Root. Eine Split-Tunnel-Konfiguration (AllowedIPs, nicht0.0.0.0/0/::/0) wird als „nicht der gesamte Datenverkehr ist geschützt“ gekennzeichnet. - Kill-switch – eine dedizierte nftables-Tabelle
inet roamswitch_vpn(policy drop, beide Hooks) verwirft alles außer Loopback, der Tunnelschnittstelle (roamswitch, passend zuoifname), UDP zur angehefteten Endpunkt-IP, DHCP und ICMP. Es wird vor installiert, bevor der Tunnel eingerichtet wird (der Endpunkt wird zuerst übergetent ahostsin feste IPs aufgelöst), sodass es kein Leckfenster gibt. Wennwg-quick upfehlschlägt, bleibt der Kill-Switch aktiv.
(B) Tailscale-Backend
- Für Benutzer, die Tailscale bereits ausführen. RoamSwitch führt nicht aus, führt
tailscale up/ login / installtailscaledaus – es liesttailscale status --jsonund führttailscale set --exit-node=<node>/--exit-node=aus (klar). - Ein Exit-Knoten ist erforderlich – Anti-MITM-Schutz gilt nur bei einem Exit-Knoten, der den gesamten Datenverkehr weiterleitet. Wenn „Keine“ konfiguriert ist, ist der Schutz nicht aktiviert und die Benutzeroberfläche warnt „nicht geschützt“. Wenn der ausgewählte Knoten offline geht, wird der Schutz automatisch deaktiviert und der Benutzer benachrichtigt (die Weiterleitung aller Daten über einen toten Knoten würde die Verbindung blockieren).
- Kill-switch (
inet roamswitch_ts,policy drop) – Der Transport von Tailscale kann nicht an eine einzelne Endpunkt-IP (DERP-Relays + Roaming-Peers) angeheftet werden, daher ist dieser lockerer als der von WireGuard. Es ermöglicht: Loopback, die Tunnelschnittstelle (tailscale0), die CGNAT-Bereiche100.64.0.0/10undfd7a:115c:a1e0::/48, STUN (udp/3478), DERP (tcp/443),udp/41641, DHCP, ICMP, MagicDNS (100.100.100.100:53), aufgebaute Verbindungen. Alles andere – beliebiges UDP, DNS zu einem lokalen Resolver, SMB, mDNS, Klartext-HTTP, beliebiges TCP – wird gelöscht. - Kill-Switch-Vorbehalte – (1) breitere Zulassungsliste als das WireGuard-Backend (
udp/3478,tcp/443, das gesamte CGNAT/10). (2) Ein On-Path-Angreifer sieht immer noch Metadaten (dass Tailscale verwendet wird, DERP-Region, Timing) und kann sie löschen/verzögern – kann die getunnelte Nutzlast jedoch nicht lesen. (3) Wenn direktes UDP blockiert ist, beruht die Vertraulichkeit auf Tailscales eigenem DERP TLS mit festem Zertifikat. (4) Wenn MagicDNS ausgeschaltet ist und ein lokaler Resolver vorhanden ist, bricht DNS im aktivierten Zustand ab (UI-Warnung). (5) Captive-Portale müssen vor der Aktivierung angemeldet sein.
Gemeinsam – nur aktiviert, wenn vpn_on_untrusted_enabled gesetzt ist und das Profil lockdown ist. Bei open und balanced wird der Tunnel nicht aufgebaut, und bei Tailscale wird der Exit-Knoten gelöscht und der Kill-Switch entfernt (niemals tailscale down). Standardmäßig deaktiviert, Opt-in. Der WireGuard-Tunnel/Tailscale-Transport geht an den eigenen VPN-Endpunkt/das eigene Tailnet des Benutzers und hat nichts mit der Infrastruktur von lafine zu tun (§9).
Präventive ARP/NDP-Sperre
Sobald ein nicht vertrauenswürdiges Netzwerk beitritt, werden die MAC-Adressen der On-Link-Infrastruktur, die ein MITM-Angreifer nachahmen müsste, in der Kernel-Nachbartabelle als PERMANENT (statische) Einträge verankert. Nach dem Fixieren ignoriert der Kernel gefälschte ARP-Antworten/Nachbar-Ankündigungen.
- ___ IPv6-Nachbarn werden mit
ip -6 neigh replace ... nud permanentgepinnt. - Vertrauenswürdige Netzwerke werden nie angeheftet – ein Neustart des Heimrouters kann also nicht dazu führen, dass der Benutzer ins Schwarze getroffen wird. Auf jedem Netzwerk-Switch neu angepinnt (TOFU); Bei der nächsten Wiederherstellung der Verbindung wird ein legitimes Failover erkannt. Angepinnte Einträge werden in
/var/lib/roamswitch/arp_lock.jsonaufgezeichnet. - Standardmäßig aktiviert (Community Edition-Richtlinie; gleiche Aufschlüsselung wie beim macOS Pro-Build). Umschalten:
gateway_arp_lock_enabled.
ARP-Spoof-Erkennung (notify-first)
Überwacht /proc/net/arp auf eine MAC, die für mehrere IPs antwortet (doppelte MAC), und auf eine verdächtige plötzliche Änderung der Gateway-MAC. Im Lockdown: Ist das Gateway beteiligt, wird der gesamte Verkehr unterbrochen (Air-Gap) und benachrichtigt. In balanced-/vertrauenswürdigen Netzwerken: nur benachrichtigen, ohne zu trennen; der Benutzer löst das Notfall-Air-Gap über RoamSwitch aus. Dies (a) verhindert, dass ein Angreifer ein einzelnes gefälschtes ARP-Paket als Waffe für einen selbstverschuldeten Ausfall nutzt, und (b) verhindert, dass ein Router-Neustart oder ein Access-Point-Roaming die Funktion versehentlich auslöst. Umschalten: arp_spoof_guard_enabled.
Prüfung der Ursache vor Aufhebung eines Air-Gap (ARP-Neuprüfung)
Ein durch ARP-Spoofing ausgelöstes Air-Gap (unter lockdown erkannt oder als Reaktion auf eine ARP-Warnung ausgelöst) wird nur dann als „Ursache beseitigt“ aufgehoben, wenn Folgendes gilt. Der Daemon liest die Neighbour-Tabelle des Kernels (ip -j neigh show, ersatzweise /proc/net/arp) und die Standardroute; die MAC des Standard-Gateways muss der bei der Auslösung gespeicherten vertrauenswürdigen MAC entsprechen (Zustand REACHABLE, STALE, DELAY, PROBE oder PERMANENT, und kein anderer IPv4-Host am selben Gerät beansprucht diese MAC), und zwar über arp_recheck_consecutive aufeinanderfolgende Prüfungen (Standard 3), die mindestens arp_recheck_min_secs Sekunden umfassen (Standard 60). Nur wenn der Neighbour-Eintrag fehlt oder fehlgeschlagen ist und die Verbindung steht (Carrier vorhanden, operstate up, WLAN nicht per rfkill gesperrt), sendet er ein einzelnes ARP-who-has an das Gateway (mindestens 20 Sekunden Abstand, über AF_PACKET) zur Prüfung (arp_recheck_active_probe, Standard true). Trägt irgendeine Antwort eine andere MAC als die vertrauenswürdige, ist das eine Abweichung. Abweichung, fehlender Eintrag, doppelte MAC, Lesefehler oder keine gespeicherte vertrauenswürdige MAC gelten alle als „nicht behoben“ (fail-closed) und setzen den Zähler zurück. Bekannte Einschränkung: Ein Angreifer, der die MAC des echten Gateways klont, ist durch keinen MAC-Vergleich erkennbar, weder aus dem Cache noch aktiv.
Ein erkannter ARP-Spoof löst das automatische Air-Gap nur aus, wenn das Gateway beteiligt ist: Die MAC des Gateways hat sich geändert, oder die IP des Gateways teilt sich eine MAC mit einer anderen IP. Ändert sich die MAC eines anderen Hosts oder antwortet ein Rechner mit einer MAC für mehrere IPs (ein PC mit virtuellen Maschinen, ein NAS mit Alias-Adresse), wird nur gemeldet und nicht getrennt. Dieselbe Regel gilt für die Freigabeprüfung: Nur ein Duplikat, an dem das Gateway beteiligt ist, zählt als „Ursache besteht fort“. Bei der Korrektur in 1.10.7 (26.09.2026) löste in einem echten LAN ein von einem anderen Rechner gesendetes gefälschtes Gateway-ARP das Air-Gap nach etwa 1 Sekunde aus; es wurde etwa 11 Minuten nach Ende des Angriffs automatisch aufgehoben (Standard 10 Minuten plus 60 Sekunden Bestätigung), auch während zwei unbeteiligte IPs weiter mit einer MAC antworteten. Vor dieser Regel löste allein dieses harmlose Duplikat eine vollständige Trennung aus und wurde nie aufgehoben.
Port Anomaly Guard
Enthält automatisch einen Überwachungsport, der neu dem externen LAN zugänglich gemacht wird (eine Hintertür, C2 oder ein Entwicklungsserver/eine lokale LLM-API, die versehentlich an 0.0.0.0 gebunden ist). Das Urteil lautet baseline-relative, nicht „gefährliche Portnummer“. Bei der Aktivierung werden die aktuell verfügbar gemachten ausführbaren Dateien als „bekannt“ erlernt; Danach wird nur eine neu erschienene verfügbar gemachte ausführbare Datei markiert (Identität = der ausführbare Pfad, Snapshots normalisiert auf snap:<name>). Systemdämonen liegen außerhalb des Gültigkeitsbereichs. Die Eindämmung erfolgt über die Tabelle inet roamswitch_dev_guard: Legen Sie TCP von einem beliebigen Ort außer lo auf diesen Port ab – die Maschine selbst verwendet ihn weiterhin. Bei der automatischen Eindämmung wird sofort ein Desktop-Benachrichtigungs- und Bestätigungsdialogfeld („Diesen Port zulassen“/„Blockiert halten“) angezeigt, der eine permanente Whitelist mit einem Klick ermöglicht. Über den Port-Diagnosebildschirm kann jeder Port auch einzeln zugelassen und die Baseline neu erfasst werden. Standardmäßig aktiviert. Umschalten: port_anomaly_guard_enabled. Portiert von macOS.
DNS-Tunneling-/Exfiltrationserkennung
Läuft durchgehend als Teil des bestehenden NFQUEUE-DNS-Pfads des passiven Link Guard (es gibt keinen eigenen Schalter dafür). Eine DNS-Abfrage wird als „verdächtig geformt“ gezählt, wenn sie eines der für DNS-Tunneling-Tools wie iodine oder dnscat2 typischen Muster aufweist — ein Abfrage-Label über 40 Byte UND eine Shannon-Entropie über 3,8, oder ein TXT-/NULL-Eintragstyp —, und es wird erst benachrichtigt, wenn innerhalb eines gleitenden 60-Sekunden-Fensters 10 oder mehr solcher Abfragen auftreten (zwischen wiederholten Benachrichtigungen für dieselbe Apex-Domain liegt eine Abklingzeit von 300 Sekunden, die bei fortlaufenden Benachrichtigungen auf 600, 1200 und höchstens 1800 Sekunden anwächst und nach einer ruhigen Phase von mindestens der doppelten Abklingzeit wieder auf 300 Sekunden zurückfällt). Geprüft wird ausschließlich DNS (UDP/TCP-Port 53); anderer Datenverkehr wird nicht untersucht. Die Funktion benachrichtigt nur und blockiert nie automatisch. Eine TXT-Abfrage an clamav.net allein wird nicht gezählt, weil freshclam sie für Aktualitätsprüfungen verwendet. Die zugrunde liegende NFQUEUE-Regel trägt das Flag bypass, sodass DNS-Datenverkehr unverändert durchgelassen wird, falls der Erkennungsprozess selbst ausfällt oder nicht reagiert — die Namensauflösung wird durch einen Ausfall dieser Funktion niemals blockiert (dasselbe Fail-open-Design wie beim passiven Link Guard selbst).
Bekannte Einschränkung — Lange, durch Bindestriche getrennte Hostnamen (etwa prod-us-east-1-web-server-node-0042) sowie die Aggregation von TXT-/NULL-Bursts über einen einzigen globalen Zähler, der nicht nach Zieldomäne unterschied, führten hier nachweislich zu Fehlalarmen. Beides wurde am 23.09.2026 behoben. Die Lösung ist eine konfigurierbare Entropie-Allowlist sowie eine nach Apex-Domain (eine einfache Näherung anhand der letzten beiden Labels des QNAME, keine strikte Public-Suffix-List-Implementierung) aufgeschlüsselte Burst-Zählung. Die Allowlist enthält standardmäßig 16 gängige CDN-/Cloud- und PaaS-Suffixe (cloudfront.net, akamaiedge.net, akamaized.net, edgekey.net, edgesuite.net, fastly.net, azureedge.net, googleusercontent.com, amazonaws.com, r2.dev, workers.dev, vercel.app, netlify.app, supabase.co, firebaseapp.com, web.app), und Administratoren können über LinkGuardCfg.dns_tunnel_entropy_allowlist eigene interne Domains hinzufügen (die Link-Guard-Einstellungen von roamswitch-app haben dafür ein eigenes Feld mit kommagetrennter Eingabe). Die Allowlist setzt nur die Prüfung aus Label-Länge und Entropie außer Kraft; die TXT-/NULL-Qtype-Erkennung greift unabhängig von der Allowlist immer, sodass ein Angreifer einen Tunnel nicht unter einer zugelassenen Domain verstecken kann (die einzige Ausnahme ist TXT unter clamav.net, das freshclam für Aktualitätsprüfungen nutzt und das über eine eigene kleine Ausnahmeliste nicht mitgezählt wird). Der Burst-Zähler ist jetzt pro Apex-Domain aufgeschlüsselt, wodurch die durch einen einzigen, zieldomänenunabhängigen globalen Zähler verursachten Fehlalarme entfallen (die Entscheidungslogik des gleitenden 60-Sekunden-Fensters ist unverändert; die Abklingzeit für wiederholte Benachrichtigungen beginnt bei 300 Sekunden und wächst bei fortlaufenden Benachrichtigungen auf höchstens 1800 Sekunden). Echter bösartiger Datenverkehr von Tools wie iodine oder dnscat2 rotiert Labels und Qtypes stets unter derselben, vom Angreifer kontrollierten Domain, sodass die Beschränkung auf eine Zählung pro Apex-Domain die Erkennungsleistung nicht mindert.
Docker-Risikoerkennung & Firewall-Umgehungsschutz
Von Docker veröffentlichte Ports (-p) sind bekanntermaßen in der Lage, die Standard-Firewall des Hosts zu umgehen. Daher werden dauerhaft Prüfregeln in die DOCKER-USER-Chain eingefügt, die jeglichen nicht ausdrücklich erlaubten externen Datenverkehr blockieren (keine Konfiguration nötig, standardmäßig aktiv). Zusätzlich wird docker events in Echtzeit überwacht, um den Moment zu erkennen, in dem ein --privileged-Container startet oder /var/run/docker.sock eingebunden wird – ein Risiko für einen Container-Ausbruch – und Sie sofort zu benachrichtigen. Da dies eine riskante Konfiguration und keine bestätigte Kompromittierung anzeigt, erfolgt nur eine Benachrichtigung ohne automatische Blockierung.
Abdeckung — Diese Prüfung der DOCKER-USER-Kette deckt das iptables-Backend (IPv4), IPv6 und das native nftables-Backend von Docker ab und prüft und repariert sich alle 60 Sekunden selbst (auch in der Desktop-Edition, ab 1.10.4; frühere Versionen deckten nur das iptables-Backend (IPv4) ab).
Scanner für Geheimnisse & API-Schlüssel-Lecks
Erkennt API-Schlüssel (OpenAI, Anthropic, AWS, GitHub, Slack, Stripe u. a.) und SSH-Private-Keys mittels Shannon-Entropie und Mustererkennung. roamswitch audit-secrets <text|Datei|Verzeichnis> durchsucht Text und Dateien sowie rekursiv ein ganzes Verzeichnis (überspringt .git, node_modules u. Ä.; Dateien über 2 MB oder die binär wirken, werden übersprungen). Dieselbe Erkennung steht auch über das MCP-Tool audit_secrets (mit text oder path) und über den Rust-Client roamswitch-linux-kit des öffentlichen SDK zur Verfügung (audit_secrets() für Text, audit_secrets_path() für eine Datei oder ein Verzeichnis). Inhalte werden niemals irgendwohin übertragen.
Erkennung und Sperrung von SSH-Brute-Force (nur solange sshd läuft)
Der Daemon der Client Edition betreibt dieselbe Engine wie die Server Edition (ssh_guard_enabled, standardmäßig true). Es gibt drei Unterschiede. Erstens arbeitet er nur, solange sshd läuft: Jede Minute prüft er, ob an den SSH-Ports etwas lauscht, und hält nach drei Fehlschlägen in Folge an. Auf einem Rechner ohne sshd liest er das Log nicht mit und berührt keine nftables-Tabelle. Zweitens sind die Einstellungen dieselben 10 Schlüssel (ssh_guard_*) mit denselben Standardwerten, abgelegt in config.json und nach etwa einer Minute wirksam. Drittens sind die Benachrichtigungen Desktop-Benachrichtigungen und ein Eintrag im Vorfallsprotokoll des Clients; ein Air-Gap startet er nie. Eine Quelle, deren Fehlversuche die Schwelle erreichen (Standard: 6 innerhalb von 600 Sekunden), verliert ihre neuen Verbindungen, und die SSH-Verbindungen, die sie bereits offen hatte, werden gleichzeitig getrennt (eine authentifizierte Sitzung und eine ausgenommene Quelle werden nie getrennt). Schützt fail2ban (mit aktivem sshd-Jail) oder CrowdSec sshd bereits, wird nur erkannt und gemeldet. Sperren werden mit sudo roamswitch bans und sudo roamswitch unban <IP> aufgelistet und aufgehoben; dafür gibt es keine GTK-Oberfläche, nur config.json und die Befehle. Bei den Standard-Schutzstufen des Clients ist eingehender Verkehr geschlossen, sodass Verbindungen SSH möglicherweise gar nicht erreichen.
Erstmaliger Setup-Assistent und Bestätigungs-Benutzeroberfläche
Das Paket wird mit /etc/xdg/autostart/roamswitch.desktop geliefert, sodass der Setup-Assistent bei der ersten Anmeldung nach der Installation gestartet wird (danach ist er nur noch in der Taskleiste vorhanden). Beim Aktivieren/Deaktivieren eines Sicherheitswächters wird ein Bestätigungsdialogfeld für dieselben Wächter wie beim macOS-Build angezeigt (Portanomalie, ARP-Auto-Containment, USB-Speicher, BadUSB-Tastatur, Bluetooth). Entscheidungen zum Ereigniszeitpunkt (eine unbekannte USB-Tastatur, ein nicht registriertes USB-Laufwerk, ein unbekannter automatisch blockierter Port, ein Notfall-Air-Gap) werden als modale Dialoge dargestellt.
§5
Shannon-Entropie-Burst-Erkennung · YARA-Scanning
Schreibereignisse werden pro PID verfolgt. Wenn ein einzelner Prozess innerhalb von 5 Sekunden 20 oder mehr verschiedene Dateien mit einer Entropie ≥ 7,92 erstellt, wird dies als Ransomware-Massenverschlüsselung behandelt: Der Prozess wird mit SIGSTOP eingefroren. Darauf folgen eine Desktop-Benachrichtigung, ein Eintrag in der Incident-Zeitleiste und ein Beweispaket. Diese Erkennung löst ebenfalls ein Air-Gap aus (die netzwerkweite Trennung) – als Auslöser mit hoher Konfidenz, wie Kanarien-Manipulation und eBPF-Ereignisse mit hohem Schweregrad.
Gemessen auf einer echten Maschine (Ubuntu 24.04, Kernel 7.0) mit einem Reproduktionsprogramm, das 40 Dateien neu schreibt (Messung vom 26.09.2026 gegen den Daemon der Version 1.10.7, die die Erkennung von Teilverschlüsselung enthält). Eine vollständige Verschlüsselung wurde nach der 20. Datei erkannt und der Prozess bei der 31. eingefroren. Auch wenn sich der Prozess in python3 oder git umbenennt, wird er erkannt: Die Allowlist prüft jetzt, dass Programmdatei und Skriptname zum Namen passen, nicht nur den Namen (früher blieben alle 40 Dateien unbemerkt). cp -r, rsync -a, tar -x und Python-Skripte werden erkannt, wenn der Schreibvorgang gesehen wird, und lösen daher auch dann keinen Fehlalarm mehr aus, wenn sie schnell enden (früher waren sie bei der Auswertung schon beendet und wurden als „unbekannter Prozess“ gemeldet). Eine Teilverschlüsselung (16 von je 32 Bytes, so wie LockBit-artige Ransomware schreibt) blieb unter dem Gesamtdurchschnitt von 7,92 und wurde früher nicht erkannt; seit 1.10.7 wird sie erkannt. Die Regel sucht nach 16-Byte-Blöcken, die zwischen zufallsähnlich und textähnlich wechseln; sie erkannte 94 % der simulierten Dateien und löste bei 19.997 gewöhnlichen Dateien 2 Fehlalarme aus (0,01 %). Ein Reproduktionsprogramm, das mit voller Geschwindigkeit ohne Pause pro Datei schreibt, hat alle 40 Dateien fertig geschrieben, bevor die Schwelle von 20 Dateien ausgewertet wird, sodass der Prozess beim Stoppen schon beendet war; mit 0,2 Sekunden pro Datei wurde er bei der 20. angehalten. Verschlüsselung nur des Dateianfangs, Verschlüsselung mit übersprungenen Bereichen und als Base64 geschriebene verschlüsselte Daten zählen nicht als Erkennung: Sie werden nur protokolliert und nichts wird eingefroren, weil sie gewöhnliche Dateien fälschlich erkennen würden. Ransomware, die in einem echten Allowlist-Programm (etwa python3) geschrieben ist, lässt sich am Namen ebenfalls nicht unterscheiden.
- Trennung von YARA-Scanning und Entropie-Tracking – Die YARA-Malware-Inspektion wird auf geschriebene Dateien ohne Ausschluss nach Dateiendung angewendet, einschließlich
~/.cache/,node_modules/und Archiven (ausgenommen sind die vom Benutzer konfiguriertenscan_exclusions, der Quarantäne-Vault,/dev/shmsowie Dateien im Arbeitsspeicher oder gelöschte Dateien, Orte wie/proc,/sysund/devund Dateien, die von Systemprozessen wie dem Daemon selbst, ClamAV und der Desktop-Basis geschrieben werden; gelesen werden nur die ersten 256 KB einer Datei). Unterdessen schließt die Ransomware-Entropie-Burst-Analyse natürlich komprimierte Formate (.zip,.tgz,.tar.gz,.gz,.png,.jpg,.mp4,.wasmusw.), Dateien, die noch mit einem echten Komprimierungs- oder Medien-Header beginnen (seit 1.10.25), und verifizierte Paketmanager (npm,npx,cargo,rustc,dpkg,apt,tarusw.), die in Build-/Cache-Bäumen arbeiten, aus, um falsch positive SIGSTOP-Einfrierungen zu verhindern. - Wiederholte Überschreibungen derselben Datei (z. B. die drei Durchläufe von
shred) zählen als ein Ereignis. - Schutz kritischer Prozesse – Prozesse werden mit einer fest codierten Liste geschützter Prozesse abgeglichen (
PROTECTED_PROCESS_NAMES:systemd/dockerd/NetworkManager/sshd/gnome-shellusw.); ein Prozess, dessen Name übereinstimmt und dessen ausführbare Datei in einem Systemverzeichnis liegt (etwa/usroder/opt), wird niemals eingefroren (das verhindert ein Hängen der gesamten Maschine). Ein Programm in/tmpoder/home, das nur den Namen nachahmt, ist nicht geschützt.
Regeln der Web-Anwendungsschicht (Web-Shells und eingeschleuster Code)
Eigene Regeln erkennen PHP-, JavaScript-, JSP- und ASP-Web-Shells, eingeschleusten verschleierten Code, in Bildern versteckten PHP-Code und die Übernahme der Ausführung über .htaccess. Sie sind von der eingebauten ELF- und Shell-Erkennung getrennt und in einer kleinen Sprache aus Literalen, Literalfolgen mit begrenztem Abstand und zwei Statistiken (extrem lange Zeile, riesiger Base64-Block) geschrieben. Ohne reguläre Ausdrücke kann die Auswertung weder ausufern noch hängen; selbst eine feindliche Regeldatei kann nur Fehlalarme verursachen. Keine Signatur stammt aus einer echten Probe oder ist an eine benannte Malware-Familie gebunden: Die 18 Regeln beschreiben nur öffentlich dokumentierte Techniken (Ausführung der Ausgabe eines Dekoders, direkt ausgeführte Request-Werte, ausführbares PHP in Upload-Verzeichnissen, PHP in einem Bild, .htaccess-Handler-Zuordnungen, mit unescape gebaute Injektionsskripte, Miner-Bibliotheken im Browser).
Die Regeln gibt es in drei Schichten: eingebaut, vom täglichen Updater (11.3) nach Signaturprüfung installiert und eigene Dateien in /etc/roamswitch/rules.d/*.json (gelesen werden nur Dateien, die root gehören und die Gruppe und andere nicht beschreiben können). Die Schweregrade sind critical, high, medium und low; critical und high laufen über Freigabe oder Quarantäne, medium und darunter werden nur gemeldet. Automatische Quarantäne gilt standardmäßig nur für critical (quarantine in /etc/roamswitch/web_rules.conf); in der Client-Edition entscheidet bei einer Erkennung beim Schreiben oder Ausführen weiterhin der Benutzer im Freigabedialog. Alles unter tests/, fixtures/ und .git/ wird standardmäßig übersprungen, weil Testcode dieselben Konstrukte zitiert.
Nach einer Erkennung erhält eine ausführbare Datei unter /etc/roamswitch/hooks/post-detection die Treffer als JSON auf der Standardeingabe (ausgeführt wird nur eine root gehörende, nicht beschreibbare Datei in einem sicheren Verzeichnis; keine Shell, minimale Umgebung, Abbruch nach 30 Sekunden). Die optionale Kontomaßnahme (standardmäßig aus) sperrt die Login-Shell des Besitzers einer isolierten Datei. Sie tut nichts für root, Konten unter account_min_uid (Standard 1000), angemeldete Benutzer und den Benutzer des Daemons; die frühere Shell wird gespeichert und roamswitch web-rules unlock-account stellt sie wieder her. Gemessene Fehlalarme: 0 in WordPress-Kern (2.409 Dateien), phpMyAdmin (3.356 Dateien) und npm-Abhängigkeiten (14.743 Dateien). Grenzen: Gelesen werden nur die ersten 256 KB (beim Schreiben/Ausführen) bzw. 4 MB (Scan), zerlegte Namen wie 'ev'.'al' werden nicht verfolgt, und mangels echter Proben werden keine Signaturen für einzelne bekannte Malware mitgeliefert.
Kanarienvögel (Köderdateien)
Decoy-Dateien werden in den Ordnern „Dokumente“, „Desktop“, „Downloads“ und „Bilder“ des Benutzers sowie in einem speziellen Verzeichnis abgelegt und in einem 3-Sekunden-Zyklus mit einer SHA-256-Basislinie verglichen. Jede Umbenennung, Löschung, Kürzung oder Inhaltsänderung löst Air-Gap sofort aus. Da der Daemon als Root ausgeführt wird, zählt er /home/* auf und stellt Canaries in den Verzeichnissen jedes echten Benutzers bereit.
Forensische Beweissicherungs-Bundles
Nur wenn die Ransomware-Entropie-Burst-Überwachung auslöst oder ein Ereignis der Schwere Critical des eBPF-Laufzeit-Bedrohungssensors eine prozessgenaue Eindämmung (SIGSTOP plus Netzwerkisolation) zustande bringt, wird roamswitch-incident-capture gestartet und sichert ein Beweis-Bundle unter <Statusverzeichnis>/incident-evidence/<Zeitstempel>-<Kurz-ID>/. Erfasst werden: eine begrenzte, 30 Sekunden lange Paketaufzeichnung per tshark auf der Standard-Routing-Schnittstelle (als übersprungen vermerkt, falls tshark nicht installiert ist) sowie, wenn eine PID übergeben wird, ein /proc/<pid>-Snapshot des betroffenen Prozesses (status, cmdline, maps, ein environ mit als Geheimnisse erkannten Werten, ersetzt durch [REDACTED], eine Liste der Ziel-Links offener Dateideskriptoren — deren Inhalt wird nicht erfasst — sowie die Kette der Vorgängerprozesse). Das Scheitern eines einzelnen Artefakts gilt nicht als fataler Fehler; es wird vermerkt, und die übrige Erfassung läuft weiter. Bei eBPF-Ereignissen wird die PID des betroffenen Prozesses übergeben. Bei der Entropie-Burst-Überwachung wird die PID übergeben, wenn sich der schreibende Prozess identifizieren ließ; war dieser Prozess bei der Auswertung des Bursts schon beendet, startet das Werkzeug ohne PID und erfasst nur die Pakete. Die Beweissicherung läuft nicht, wenn die prozessgenaue Eindämmung nicht möglich ist oder fehlschlägt und auf eine hostweite Air-Gap-Isolation zurückfällt, ebenso wenig bei Ereignissen der Stufe Emergency/Alert, die direkt eine hostweite Isolation auslösen. Die Pakete bis 1.10.4 enthielten das für diese Funktion nötige roamswitch-incident-capture nicht, sodass sie bei Installationen aus den Paketen nicht lief. Seit 1.10.5 ist es enthalten.
Die Ergebnisse werden in manifest.json festgehalten, das zusätzlich den SHA-256-Hash jeder anderen Datei im Bundle einbettet (damit nachträgliche Manipulation erkennbar ist). Bundles werden nie automatisch gelöscht — alte Bundles werden nur entfernt, wenn roamswitch-incident-capture prune (Standardaufbewahrung: 30 Tage) explizit ausgeführt wird.
Erfasste Beweise werden zum Zeitpunkt der Erfassung nicht verifiziert. Um nachträglich auf Manipulation zu prüfen, führen Sie roamswitch-incident-capture verify <Bundle-Verzeichnis> [--json] aus. Der Befehl berechnet die Hashes aller aktuell im Bundle vorhandenen Dateien neu, gleicht sie mit den in manifest.json erfassten Werten ab und meldet jede Abweichung einzeln als geändert, fehlend oder nicht erfasst (eine Datei, die im Manifest nicht verzeichnet ist).
Bekannte Einschränkung — Diese Prüfung vergleicht den SHA-256 von manifest.json mit Aufzeichnungen außerhalb des Bündels, und zwar an zwei Stellen: einer Hash-Kette außerhalb des Bündels (evidence_anchor.log, jede Zeile bindet sich an die vorherige, wo das Dateisystem es erlaubt nur zum Anhängen gesetzt) und dem Systemlog (Tag roamswitch-evidence). Wird manifest.json nach der Erfassung umgeschrieben, schlägt verify fehl; ebenso, wenn eine Zeile der Kette geändert oder entfernt wird, weil die Kette dann reißt. Ein Angreifer mit root, der sowohl die Kette als auch das Ziel der Systemlog-Weiterleitung umschreiben kann, wird dadurch nicht aufgehalten; empfohlen wird, das Systemlog an einen anderen Rechner weiterzuleiten. Signaturen sind nicht umgesetzt. Ein Bündel ohne Eintrag (von einer älteren Version erfasst) wird als „kein Eintrag“ gemeldet, d. h. es gibt keine Bestätigung von außen.
Honeytokens (Anmeldedaten-Köder)
Beim Start des Daemons legt RoamSwitch idempotent Köder-Anmeldedateien an bekannten, tatsächlich von Angreifern und automatisierten Tools zum Diebstahl von Anmeldedaten durchsuchten Pfaden ab — ~/.aws/credentials, ~/.ssh/id_rsa und ~/.docker/config.json, ~/.pypirc, ~/.env.backup (im Home-Verzeichnis des aufrufenden Benutzers) —, jeweils mit dem Marker ROAMSWITCH_HONEYTOKEN. Existiert an einem dieser Pfade bereits eine echte Datei, wird sie niemals überschrieben (vor der Bereitstellung wird stets zuerst geprüft, ob die Datei existiert). Ein tatsächlicher Zugriff auf ein Honeytoken kann zudem eine kaskadierende Bereitstellung weiterer, verwandter Köder auslösen. Die Pakete bis 1.10.4 enthielten das für diese Funktion nötige roamswitch-honeytokens nicht, sodass sie bei Installationen aus den Paketen nicht lief. Seit 1.10.5 ist es enthalten. Seit 1.11.1 wird jeder docker-Befehl, den RoamSwitch selbst ausführt, mit einem leeren, privaten Verzeichnis als DOCKER_CONFIG gestartet und löst daher den Köder ~/.docker/config.json nicht aus. Ein Lesezugriff durch ein anderes Programm wird weiterhin wie bisher erkannt.
Ein Hintergrundwächter überwacht mit benachrichtigendem fanotify (FAN_OPEN/FAN_ACCESS pro Datei auf jedem Köder) das Lesen und Öffnen jedes Köders; wo fanotify nicht verfügbar ist (etwa bei Ausführung ohne Root), wechselt er zu inotify. Da kein legitimer Prozess einen Grund hat, diese Dateien zu lesen, wird jeder Zugriff als starkes Signal für eine Aufklärung durch einen Angreifer nach einer Kompromittierung gewertet (MITRE ATT&CK T1552); RoamSwitch versucht, den zugreifenden Prozess zu identifizieren, und erfasst das Ereignis mit der Schwere Critical in der Incident-Zeitleiste (es erscheint kein Desktop-Popup; bei aktivierter Ereignisweiterleitung wird es weitergeleitet). Zugriffe durch die eigenen ausführbaren Dateien von RoamSwitch sowie durch die OpenSSH-Client-Familie (ssh, scp, sftp, ssh-add, ssh-agent) auf die SSH-Köder werden nicht erfasst, um Fehlalarme zu vermeiden; ein Zugriff, dessen ausführbare Datei sich nicht identifizieren lässt, wird erfasst. Dies dient ausschließlich der Aufzeichnung — der zugreifende Prozess wird dadurch weder eingefroren noch blockiert.
Bekannte Einschränkung — Der Inhalt des ~/.ssh/id_rsa-Köders enthält lesbaren Text und bleibt als Base64-Rumpf eines echten OpenSSH-Privatschlüssels ungültig. Da die meisten Secret-Scanner Dateien jedoch allein anhand eines Regex-Treffers auf den Header -----BEGIN ... PRIVATE KEY----- markieren, schätzen wir die Auswirkung auf die tatsächliche Erkennungsrate als gering ein. Außerdem wird der zugreifende Prozess normalerweise anhand der PID des fanotify-Ereignisses identifiziert; nur wenn fanotify nicht verfügbar ist und auf inotify umgeschaltet wird, kommt ein fuser-Aufruf zum Einsatz, der bei sehr kurzlebigen Prozessen, die sich unmittelbar nach dem Lesen der Datei beenden, PID und Prozessname möglicherweise nicht ermitteln kann. In diesem Fall wird der Prozess lediglich als unbekannt erfasst; die Erkennung des Zugriffs selbst (Ereignisauslösung und Erfassung) ist davon nicht betroffen.
Fanotify-Überwachung · Quarantäne-Tresor · ClamAV
- Der Daemon überwacht
/home,/tmp,/var/tmpund/dev/shmmit Marken auf Dateisystemebene (seit 1.10.18; eine Marke auf Mount-Ebene ist nur der Ersatz, falls eine Dateisystem-Marke abgelehnt wird) und überwacht die Schreibabschlüsse auf/insgesamt ebenfalls auf Dateisystemebene, und zwar überFAN_CLASS_CONTENT(Berechtigungsmodus; FallbackFAN_CLASS_NOTIF). Ab 1.10.4 gelten Berechtigungsereignisse nur für die Ausführung (FAN_OPEN_EXEC_PERM);openwird als Benachrichtigung behandelt (mitfanotify_open_permlässt sich das frühere Verhalten wiederherstellen). Bereits als sauber geprüfte ausführbare Dateien werden 60 Sekunden zwischengespeichert, und die eigenen Kindprozesse des Daemons werden von der Überwachung ausgenommen. - Notify-first, keine Quarantäne vor Bestätigung (fanotify-Wächter). Ein bloßer YARA-/ClamAV-Treffer führt im fanotify-Wächter nie zu einer Quarantäne ohne Bestätigung oder zu
FAN_DENY. Eine echte Signatur löst eine modale Anfrage in/run/roamswitch/approvals.json(Quarantäne/Zulassen/Später) aus; nichts gelangt in den Tresor, bis der Benutzer dies bestätigt. Nur ein tatsächlicherexecveerhältFAN_DENY, und nur, wennpre_exec_blocking_enabledaktiviert ist. Die Genehmigung läuft bei Fail-open ab. Die Download-Überwachung (standardmäßig~/Downloadsund~/Desktop, ergänzt durchwatched_folders) ist ein eigener Pfad: Eine Datei, die YARA oder ClamAV (außer EICAR) meldet, wird ohne Rückfrage sofort in den Quarantäne-Vault verschoben, und eine Benachrichtigung folgt. - Testsignaturen wie EICAR werden nur im Verlauf erfasst – die branchenübliche Testzeichenfolge löst keine Benachrichtigung aus, sondern erzeugt nur einen Eintrag im Benachrichtigungsverlauf, und wird weder im Fanotify-Guard noch im Download-Guard unter Quarantäne gestellt oder blockiert.
- Eine vom Benutzer konfigurierte
scan_exclusions-Pfadliste (absolute Pfade, rekursiv angewendet; sie fasst das alteclamav_exclusionszusammen) wird sowohl von den YARA- als auch den ClamAV-Scannern berücksichtigt. „Zulassen“ in der Eingabeaufforderung und „Wiederherstellen“ in der Registerkarte „Quarantäne“ werden beide daran angehängt, sodass dieselbe Datei nicht erneut markiert wird. - Erkannte echte Malware (im fanotify-Wächter nur, was der Benutzer bestätigt hat) wird in das nur für Root zugängliche Verzeichnis
/var/lib/roamswitch/quarantine/verschoben (früher lag sie im jeweiligen~/.local/share/roamswitch/quarantine/des Benutzers; der alte Speicherort wird beim Start automatisch migriert). Das Vault-Verzeichnis gehört root und hat0700; jede Probe gehört root und hat0400(schreibgeschützt, nicht ausführbar). Benutzer können den Vault nur über das IPC des Daemons bedienen und nur die selbst unter Quarantäne gestellten Einträge auflisten, wiederherstellen und löschen. Eine Wiederherstellung schreibt ein Kindprozess, der auf die Rechte des aufrufenden Benutzers heruntergestuft wurde, als Datei mit0644(eine vorhandene Datei wird nie überschrieben). - Die Berechtigungsereignisschleife liest die Konfigurationsdatei nie – die Konfiguration wird von einem dedizierten Hintergrundthread in einen
Mutex<GuardConfig>-Snapshot gelesen; die Hot-Path-Zugriffe auf die Konfiguration sperren und kopieren nur (das Lesen des Dateianfangs der auszuführenden Datei zur Beurteilung ist davon getrennt). Dies ist eine Designinvariante: Ein Blockieren aufFAN_OPEN_EXEC_PERMwürde die Maschine einfrieren. - Wenn ClamAV vorhanden ist (
clamav_enabled, standardmäßig aktiviert), werden neue Dateien, die in den überwachten Ordnern der Download-Überwachung erscheinen (standardmäßig~/Downloadsund~/Desktop), nach dem eingebauten YARA-Scan anhand der lokalen Datenbank gescannt. Ausführbare Windows-Formate wie.exelösen eine Benachrichtigung aus, Linux-Verteilformate (.sh,.deb,.elfusw.) werden nur im Verlauf vermerkt, und gefährliche KI-Modelle (.pkl,.pt) lösen eine Benachrichtigung mit Angabe der Herkunft aus. ClamAV ist eine optionale Abhängigkeit; die anderen Abwehrmechanismen funktionieren auch ohne. Ist es installiert, ruft der tägliche Updater (§11)freshclamauf, damit die Signaturdatenbank aktuell bleibt.
Prozess-Ausführungsrekorder (nur lokal)
Ein rein lokaler Rekorder, der exec-Ereignisse und uid-Wechsel über den netlink-Prozess-Connector (proc connector) protokolliert. Er erfasst Programmpfad, Kommandozeilenargumente (auf 64 Argumente, je 512 Zeichen und insgesamt 4096 begrenzt, Steuerzeichen maskiert), Elternprozess-Abstammung, uid, Arbeitsverzeichnis, Container-ID, SHA-256 der ausführbaren Datei u. a. Er ist standardmäßig aktiv, standardmäßig aber aus auf Maschinen mit weniger als 1 GiB RAM (eine ausdrückliche Einstellung von exec_recorder_enabled hat Vorrang). Die eigene CPU-Nutzung ist auf 3 % eines Kerns begrenzt (exec_recorder_cpu_budget_pct); er läuft mit nice 10. Lässt sich der Prozess-Connector nicht öffnen, fällt er auf einen seltenen /proc-Scan zurück (kurzlebige Prozesse werden dabei verpasst).
- Speicherung — die Einträge liegen unter
/var/lib/roamswitch/exec_logals in 8-MiB-Segmente aufgeteilte JSON Lines (0600). Standardmäßige Aufbewahrung: 200 MB / 14 Tage (exec_recorder_retention_mb/exec_recorder_retention_days). Eine Hash-Kette macht Manipulation erkennbar, aber nicht verhinderbar (ein Angreifer mit Root kann die gesamte Kette neu schreiben). Suche mitroamswitch events search|tree|export|verify; die schreibgeschützten MCP-Werkzeuge für KI-Clients sindsearch_exec_eventsundget_process_tree. - Nur benachrichtigende Korrelationsregeln (EXR-001 bis EXR-010) — zehn Regeln: eine von einem Webdienst gestartete Shell, Ausführung aus
/tmp, einer Speicherdatei (memfd) oder einer gelöschten Datei, Ausführung unmittelbar nach einem Download, ein base64/eval-Einzeiler, Erlangen von uid 0 ohne setuid-Pfad, Ausführung einer Binärdatei, die direkt nach einer cron/systemd-Änderung abgelegt wurde, Ausführung nach einer Änderung an/etc/ld.so.preload, ein lokaler Dateisystem-Snapshot (btrfs, LVM), der von etwas anderem als einem bekannten Verwaltungswerkzeug wiesnapperodertimeshiftgelöscht wurde (EXR-008, 1.10.11), derselbe Akteur, der innerhalb von 30 Sekunden mitwhichund Ähnlichem nach 8 oder mehr Angriffswerkzeugen sucht (EXR-009, 1.11.0), sowie eine Skript-Laufzeitumgebung wie python oder node, die innerhalb von 2 Minuten 3 oder mehr Angriffswerkzeuge startet (EXR-010, 1.11.0; ausgenommen ist die Eingabe durch einen Menschen unter sshd, login oder einem Terminal). Jede Regel trägt eine MITRE-ATT&CK-Technik-ID. Regeln benachrichtigen nur und isolieren nie allein; nur wenn ein Betreiberexec_rules_isolation_optin(Standard false) ausdrücklich aktiviert, wird eine Regel mit hohem Schweregrad als Air-Gap-Auslöser mit hoher Konfidenz behandelt (§4). - Nichts verlässt die Maschine — das Rohprotokoll wird nie weitergeleitet. Nur wenn die Ereignisweiterleitung (§9.4) aktiviert ist, werden die Regelmeldungen (Schweregrad, Regel-ID, Prozessname, Zusammenfassung) und die Segment-Siegel-Hashes gesendet, und zwar nur an das vom Betreiber konfigurierte Ziel.
Überwachung des Zugriffs auf Zugangsdaten-Dateien (standardmäßig an, nur Benachrichtigung)
Standardmäßig an (credential_access_watch_enabled ist true; mit false wird es abgeschaltet, auch über den Schalter im Malware-Guard-Bildschirm). Es benachrichtigt, wenn ein unerwartetes Programm einen SSH-Privatschlüssel (~/.ssh/id_*), ~/.aws/credentials, die Zugangsdatendateien unter ~/.config/gcloud/ (vier Arten, etwa credentials.db) oder den Zugangsdaten-/Cookie-Speicher eines gängigen Browsers öffnet (nur Benachrichtigung). Es setzt lediglich das fanotify-Benachrichtigungsereignis FAN_OPEN auf wenige einzelne Dateien, blockiert nie etwas, friert nie etwas ein und verweigert nie etwas, und der Kernel wartet nicht auf eine Antwort. Der Name der ausführbaren Datei des öffnenden Programms wird mit nach Art getrennten Zulassungslisten (ssh / git / gpg-agent, Browser, aws / terraform / kubectl usw.) abgeglichen; wiederholte Meldungen für dasselbe (Programm, Datei)-Paar werden 10 Minuten lang unterdrückt. Backup-Werkzeuge (restic, borg usw.) und Indexer (tracker, baloo usw.) sind von Anfang an erlaubt. Weitere Programme, für die Sie keine Meldungen wollen, tragen Sie in credential_access_watch_allow in der config.json ein. Bei AWS-Zugangsdaten sind Werkzeuge erlaubt, die als python, python3 oder ansible laufen, etwa boto3-Skripte und Ansible (bei gcloud python und python3); ein Einzeiler wie python -c löst dennoch eine Meldung aus. Der Preis dieser Erlaubnis ist, dass auch ein Programm zum Diebstahl von Zugangsdaten, das als python-Skriptdatei läuft, keine Meldung auslöst. Andere Interpreter wie node oder ruby sowie allgemeine Such- und Synchronisierungswerkzeuge wie grep oder rclone sind bewusst nicht erlaubt, weil ein Programm, das Zugangsdaten stiehlt, genauso aussieht; sie können daher Meldungen auslösen. Ein sehr kurzer Lesezugriff wie bei cat oder head, bei dem sich das Programm beendet, bevor RoamSwitch seine ausführbare Datei bestimmen kann, wird möglicherweise nicht gemeldet (ein Lesezugriff durch ein Programm, das eine Weile weiterläuft, wird gemeldet). RoamSwitch nutzt zur Umgehung dieser Grenze nicht das fanotify der Berechtigungsklasse, weil es das System anhalten könnte. Änderungen wirken nach etwa 30 Sekunden, ohne Neustart.
Der Einbruchsweg in Benachrichtigungen über Dateimanipulation
Auch die Benachrichtigungen der Überwachung wichtiger Dateien (FIM) des Clients und der Überwachung von Abhängigkeits-Lockfiles nennen den Prozess, der die Änderung vorgenommen hat (Konto, ausführbare Datei, Befehl), und die SSH-Anmeldung, zu der er gehört (Quelle, Zeit, Authentifizierungsmethode). Das ist fim_intrusion_context_enabled in config.json, standardmäßig true; es wird nichts nach außen gesendet. Eine Benachrichtigung über den Zugriff auf eine Zugangsdaten-Datei erhält nur dann eine zusätzliche Zeile, wenn der Prozess zu einer SSH-Anmeldung gehört. Wie es funktioniert, welchen Werten es traut und welche drei Antworten es auseinanderhält (gefunden / keine SSH-Anmeldung gefunden / Anmeldeweg nicht ermittelbar), ist wie in der Server Edition. Was nicht geprüft werden konnte, wird nie als „keine Anmeldung“ gemeldet. Die Aufzeichnung liegt in /var/lib/roamswitch/fim_intrusions.json und im Feld recentIntrusionContext des MCP-Tools verify_fim.
Kernel Local Privilege Escalation (LPE) Preemption & Hardening
Wenn ein Angreifer oder eine Schadsoftware unprivilegierten Benutzern Zugang verschafft, verhindert die Tiefenverteidigung, dass Schwachstellen im Linux-Kernel ausgenutzt werden, um Root-Rechte zu erlangen.
- Umgang mit nicht privilegierten User-Namespaces (Frag Gap CVE-2026-53362 Abschwächung) — Viele moderne Linux-Kernel-LPE-Schwachstellen beruhen darauf, dass nicht privilegierte Benutzer mit
unshare(CLONE_NEWUSER)isolierte User-Namespaces anlegen und darin auf nicht initialisierte Kernel-Strukturen oder ältere Netzwerk-Subsysteme zugreifen. Die Diagnose prüft und zeigt den Zustand vonuser.max_user_namespacesundkernel.unprivileged_userns_clonean; da eine Deaktivierung jedoch Browser, Flatpak, Electron und Rootless-Container beeinträchtigen kann, empfiehlt die Client-Edition sie nicht und nimmt sie nicht in das One-Click-Hardening auf (istuser.max_user_namespaces = 0gesetzt, rät der Bericht, den Standardwert wiederherzustellen). Die Deaktivierung ist eine Übergangslösung, die nur Angriffswege schließt, die einen User-Namespace benötigen; andere Wege stoppt sie nicht. Das Setzen vonkernel.unprivileged_userns_clone = 0nur während eines nicht vertrauenswürdigen Netzwerks wird nur angewendet, wenn Sieadaptive_security.untrusted_network_actions.auto_enable_userns_restrictioninguard.yamlausdrücklich aktivieren (standardmäßig deaktiviert; auf Kerneln ohne diese Einstellung bewirkt es nichts). Die Server Edition wendet es standardmäßig dauerhaft an (harden_userns_enabled). Die eigentliche Lösung ist ein Update auf einen gepatchten Kernel und ein Neustart. - Yama LSM-Speicherschutz – Durch die Durchsetzung von
kernel.yama.ptrace_scope = 1(oder2) wird verhindert, dass nicht autorisierte Prozesse überptraceeine Verbindung herstellen oder über/proc/$pid/memden Speicher lesen, wodurch Browsersitzungen und private GPG/SSH-Schlüssel geschützt werden. - Core Dump Suppression – Die Einstellung
fs.suid_dumpable = 0verhindert, dass abstürzende sensible Prozesse Klartext-Speicherauszüge auf die Festplatte schreiben. - __
eBPF-Laufzeit-Bedrohungssensor und autonomes Einfrieren von Prozessen (Desktop eBPF Guard)
Der RoamSwitch-Client-Daemon umfasst eine native Integration mit modernen eBPF-Sensoren im Kernel (Falco / Tetragon / BTF).
# eBPF-Laufzeit-Bedrohungserkennung & autonomer Abwehrfluss [Bösartiger Prozess (LPE/Malware)] │ Illegale Syscall-Ausführung (Frag-Gap-Ausnutzungsversuch) ▼ [Linux-Kernel (eBPF-Sonde)] │ eBPF-Ringpuffer (kompaktes 2-MB-Design) ▼ [Falco (RoamSwitch Optimized)] │ Direkter UNIX-Socket im Arbeitsspeicher (/var/run/roamswitch/events.sock) ▼ [roamswitch-daemon (root)] ├─► ① Millisekunden-Einfrieren des angreifenden Prozesses: kill(pid, SIGSTOP) [Zustand: Ts] ├─► ② Netzwerksperre: Critical nur für den Benutzer des Prozesses (roamswitch_isolate), Emergency/Alert nftables input/output drop [Air-Gap aktiviert] └─► ③ Desktop-Notfallwarnung: GTK3-Modal & libnotify-Benachrichtigung
- Direct UNIX Domain Socket IPC (
/var/run/roamswitch/events.sock) – Warnungen von Falco oder anderen eBPF-Sensoren werden direkt über einen speicherinternen UNIX-Socket empfangen, ohne in Festplattenprotokolle zu schreiben, wodurch Festplatten-E/A-Latenz vermieden wird und Antwortübergaben in weniger als einer Sekunde möglich sind. - Autonome Reaktion im Millisekundenbereich (Prozess einfrieren und Netzwerk sperren) – Wird ein Ereignis mit der Priorität
Criticalempfangen (etwa Kernel-LPE, Rechteausweitung oder Ransomware-Verschlüsselung), sendet der DaemonSIGSTOPan die betreffende PID, um den Prozess vollständig anzuhalten (Zustand:Ts), sperrt in der Tabelleroamswitch_isolatenur den Datenverkehr des echten Benutzers dieses Prozesses (bei einem Container seiner cgroup) („prozessgenaue Isolation“) und löst eine Desktop-Benachrichtigung aus. Lässt sich keine PID ermitteln, wird das Einfrieren eines geschützten Prozesses abgelehnt, scheitert die Isolation (etwa bei einem Root-Prozess) oder hat das Ereignis die PrioritätEmergencyoderAlert, setzt der Daemon in der Tabelleinet roamswitchpolicy drop(Air-Gap) ein und sendet zusätzlichSIGSTOP, sofern eine PID bekannt ist. Ereignisse unterhalb vonCriticallösen keine Sperre aus und werden nur im Verlauf vermerkt. - Overhead-arme Desktop-Abstimmung & Schutz vor Log-Aufblähung (RoamSwitch Optimized) Um Akkuverbrauch, CPU-Last und Speicherplatzerschöpfung auf Laptops und Workstations einzudämmen, liegen für Umgebungen, in denen Falco installiert wird, ein optimiertes Profil (
99-roamswitch-optimized.yaml) und eine logrotate-Konfiguration bei. Die Client-Pakete und der Desktop-Modus voninstall.shinstallieren Falco nicht und legen dieses Profil nicht ab (die Pakete der Server Edition undinstall.sh --servertun das). Wenn Sie Falco mit dem Client verwenden, installieren Sie Falco selbst und legen das Profil bei Bedarf selbst ab. Die wichtigsten Einstellungen sind die folgenden.- Schweregradfilterung (
priority: warning) – Filtert 95 % der routinemäßigen Hinweis-/Infoereignisse heraus. - Kernel Early Drop (
drop_failed_exit: true) – Verwirft fehlgeschlagene Systemaufruf-Exits direkt im Kernel-Treiber, wodurch Kontextwechsel und CPU-Last halbiert werden. - Kompakter Ringpuffer (
cpus_for_each_buffer: 2) – Reduziert die Größe des Ringpuffers auf 2 MB, wobei der residente RAM bei 30–50 MB und die CPU-Auslastung bei <1 % bleibt. - Obligatorische Protokollrotationsobergrenze (
/etc/logrotate.d/roamswitch-falco) – Erzwingt eine strikte Obergrenze von 50 MB mit komprimierter Rotation der 7. Generation.
- Schweregradfilterung (
- Hybride Resilienz (eigenständige Härtung vs. eBPF-Erweiterung) – Auch ohne Falco schützt RoamSwitch das System autonom über Kernel-sysctl (Yama-ptrace-Beschränkung, Unterdrückung von Core-Dumps und Netzwerkschutz, bei jedem Profilwechsel angewendet), nftables-Profile, fanotify und die Canary-Überwachung. Mit Falco kommen die Abwehr von Zero-Day-Angriffen und das Einfrieren von Prozessen über eBPF-Ereignisse in Echtzeit hinzu, was den stärksten Schutz ermöglicht.
§6
USB-Ereignisse werden überwacht; Tastaturgeräte (HID) und USB-Massenspeicher werden verfolgt. Standardmäßig deaktiviert (Auslieferung isEnabled = false, passend zu macOS USBKeyboardGuard / USBStorageGuard). Melden Sie sich über den Erstausführungsassistenten oder die Registerkarte „USB“ an. Beim Aktivieren wird ein Bestätigungsdialog angezeigt.
Rogue-USB-Tastatur (Tastenanschlag-Injektion)
- Keine Deautorisierung physischer Ports auf Kernel-Ebene (wichtig). Die alte Implementierung (≤1.0.6) schrieb
0bis/sys/bus/usb/devices/*/authorizedfür eine nicht registrierte Tastatur und trennte sie physisch. Bei einem kombinierten Tastatur- und Mausempfänger (üblich bei einem Raspberry Pi oder einem Mini-PC) wird dadurch auch die Maus getrennt, wodurch ein Computer ohne eingebauten Eingang gesperrt wird. RoamSwitch verweigert jetzt strikt das Schreiben vonauthorized=0auf ein Gerät, das eine HID-Schnittstelle (bInterfaceClass 03) bereitstellt, und der Daemon autorisiert jedesauthorized==0HID-Gerät beim Start erneut, um Maschinen selbst zu reparieren, die durch eine frühere Version blockiert wurden. - ___ Der Mausknoten bleibt unberührt. Dies ist das Linux-Äquivalent von macOS
CGEventTap; Das Gerät bleibt mit Strom versorgt. - Sicherheit – Der Zugriff erfolgt nur, wenn eine andere Tastatur zum Tippen vorhanden ist (eine integrierte oder eine zugelassene und angeschlossene USB-Tastatur), sodass ein Computer mit einer einzigen neuen Tastatur niemals gesperrt wird.
- Freigabedialog — zusammen mit dem Grab wird in
/run/roamswitch/approvals.jsoneine Freigabeanfrage abgelegt und die GUI zeigt einen modalen Dialog (Erlauben / Ablehnen). Erlauben trägt das Gerät in die Whitelist ein und hebt den Grab auf. Wird nicht innerhalb von 3 Minuten freigegeben, wird die Tastatur standardmäßig nicht mehr freigegeben (ab 1.10.4; frühere Versionen öffneten nach 3 Minuten im Fail-open, und mitusb_keyboard_timeout_releaselässt sich das frühere Verhalten wiederherstellen).
Schurken-USB-Massenspeicher
Wird ein nicht registriertes USB-Massenspeichergerät (ohne HID-Schnittstelle) eingesteckt und ist der Schutz aktiviert, wird es mit authorized=0 gehalten (sicher für ein Nicht-HID-Gerät) und ein Genehmigungsdialog angezeigt, unabhängig davon, ob das Netzwerk vertrauenswürdig ist. Ein Laufwerk, das eingehängt ist oder als Swap dient (eine in Benutzung befindliche externe Festplatte, ein Live-USB-Stick), wird nicht gehalten, weil das einem abrupten Entfernen gleichkäme und es beschädigen könnte; es wird nur protokolliert. Zulassen autorisiert erneut und trägt es in die Whitelist ein; Ablehnen hält es weiter zurück. Der macOS-Build wurde in 1.7.4 an dieses Modell „Schreibgeschützt halten + Genehmigungsaufforderung“ angepasst.
Identifikation und Bestandsschutz
HID wird aus bInterfaceClass == "03" und der Zeile Handlers= in /proc/bus/input/devices ermittelt. Ein Kombinationsempfänger (ein VID:PID mit sowohl einem kbd- als auch einem Mausabschnitt) wird durch VID:PID zusammengeführt. Das Grandfathering (die Aufnahme bereits vorhandener Tastaturen in die Zulassungsliste) übernimmt die GUI, nicht der Daemon. Die zu diesem Zeitpunkt angeschlossenen Tastaturen werden in die Zulassungsliste eingetragen, wenn Sie den Schutz im Assistenten der Ersteinrichtung aktivieren (sowie bei einer einmaligen Migration für eine bestehende Installation, bei der der Schutz aktiv und die Einrichtung abgeschlossen ist, aber keine angeschlossene Tastatur in der Zulassungsliste steht). Wird der Schutz später im USB-Tab aktiviert, wird nichts eingetragen. Eine Tastatur, die beim Daemon-Start angeschlossen, aber nicht registriert ist, gilt als nicht registriert, weil sie vor einem Neustart ausgetauscht worden sein könnte, und wird abgegriffen (grab), sofern eine andere Tastatur zum Tippen zur Verfügung steht.
§7
Der LinuxHealthChecker in roamswitch-core bewertet 27 Elemente und ergibt eine Punktzahl von 0–100, eine Note S/A/B/C (S für 100, A für 85–99, B für 70–84, C darunter) und Ratschläge pro Element. Im GTK-Dashboard, der CLI (roamswitch status) und dem MCP (get_security_report) werden Titel, Details und Empfehlung aller 27 Elemente in der Sprache des Benutzers (10 Sprachen) angezeigt.
| Kategorie | Beispielartikel |
|---|---|
| Festplatte / Boot | LUKS/dm-crypt-Verschlüsselung, UEFI Secure Boot |
| Zugangskontrolle | LSM (AppArmor / SELinux), SSH / Sudo-Konfigurationsprüfung |
| Kernhärtung | sysctl-Härtung, Prüfung des Zustands nicht privilegierter User-Namespaces (Frag-Gap-Abschwächung; die Client-Edition empfiehlt keine Deaktivierung), Yama-ptrace-Beschränkung, Core-Dump-Kontrolle, Noexec auf /tmp und /dev/shm |
| Aktualisierungen | Automatische Konfiguration von Sicherheitsupdates |
| Netzwerk | ARP-Spoofing-Überwachung, Gateway-ARP/NDP-Sperrstatus, Prüfung exponierter Ports, Stärke der WLAN-Verschlüsselung |
| Schadsoftware | ClamAV (einschließlich eines Live-Erkennungstests mit EICAR) / fanotify (prüft auch, dass der Guard tatsächlich läuft und keine Ereignisse durch Warteschlangenüberlauf verpasst wurden) / Entropieüberwachung / noexec / Installationsprüfung der Hilfsprogramme (Honeytokens und Beweissicherung) |
| Browser | Firefox / Chrome / Chromium Safe Browsing-Einstellungen |
| DNS / USB | Bedrohungsschutz-DNS, Zero-Trust-Status des USB-Busses |
| Container und Schwachstellen | Exposition des Docker-Sockets durch Einbindung, Audit privilegierter Container (--privileged), Isolationsstufe der Container-Runtime (runc / gVisor / Kata), bekannte CVE-Gefährdung des laufenden Kernels |
Jede Prüfung basiert auf dem Lesen lokaler Dateien und der Befehlsausgabe (getenforce, mokutil, resolvectl, ss, …). Es gibt keinerlei externe Abfrage.
Vertrauensbewusste Einstufung. Die Härtung, die RoamSwitch absichtlich nicht in einem vertrauenswürdigen (Heim-)Netzwerk anwendet – Fixierung des Gateway-MAC als PERMANENT (was das LAN bei einem Neustart des Routers blockieren würde), erneutes Mounten von /tmp und /dev/shm noexec (was Paket-Builds und einige Installationsprogramme unterbricht) und Bedrohungsschutz-DNS im Standardbereich – wird grün mit angezeigt eine Erklärung anstelle eines roten „nicht gehärtet“ und weist darauf hin, dass es automatisch auf ein nicht vertrauenswürdiges Netzwerk angewendet wird. Die Laufzeitwahrheit kommt von /run/roamswitch/state.json (active_level / network_trusted / fanotify_ready), die in jedem Zyklus vom Daemon geschrieben wird. Das Fanotify-Element prüft, ob der Guard tatsächlich markiert ist und ausgeführt wird (/run/roamswitch/fanotify.ready), und nicht nur, ob der Kernel ihn unterstützt. Das Element „exponierte Ports“ liest das Live-Profil des Daemons (der MCP-Hardcode ist weg).
___ Der Daemon wird als Root ausgeführt, sodass bis auf den Daemon-Neustart kein pkexec erforderlich ist.
NIST-CSF-2.0-/CIS-Controls-v8-Zuordnung
Jeder der 27 Prüfpunkte wird mit einer NIST-CSF-2.0-Funktions-/Kategorie-Kennung versehen (z. B. PR.DS-01, DE.CM-09), und nur bei Punkten, für die eine verlässliche Zuordnung möglich ist, zusätzlich mit einer CIS-Controls-v8-Kontrollnummer (z. B. 3.11, 4.1). Mehrdeutige Punkte werden nicht erzwungen zugeordnet, sondern bleiben unzugeordnet. Diese Zuordnung (nistCsf / cisControl) ist in der MCP-Ausgabe (get_security_report) und in der JSON-Ausgabe der CLI (roamswitch status --json) enthalten. In der GUI und in der normalen CLI-Anzeige der Client-Edition erscheint sie nicht (in der Anzeige von roamswitch status --server der Server-Edition schon). Sie ermöglicht es Betreibern und Prüfern mit Compliance-Anforderungen, die Prüfpunkte von RoamSwitch mechanisch bestehenden Rahmenwerken zuzuordnen.
§8
roamswitch-mcp spricht JSON-RPC über stdio und wird von KI-Clients wie Claude Desktop, Cursor und Antigravity gestartet. Jedes Tool ist schreibgeschützt, und fast alle arbeiten vollständig lokal. Als einziges Tool kann run_npm_audit_signatures einen externen Host kontaktieren; es ist standardmäßig deaktiviert. Die Auswertung von get_security_report und verify_security_findings sendet nichts ins LAN, und das Gateway wird nur aus dem ARP-Cache und anderen lokalen Informationen gelesen. Ein Ping kann nur in anderen Abläufen ausgehen, die die Gateway-MAC neu auflösen (ARP-Überwachung des Daemons, Notfallwiederherstellung, Sensor-Kopplung, get_guard_status und Ähnliches).
| Werkzeug | Zweck |
|---|---|
| get_security_report | 27-Punkte-Bewertung, Punktzahl, Empfehlungen |
| verify_security_findings | Bewertet Einträge (checkId) aus get_security_report anhand des aktuellen Zustands neu und liefert je Eintrag ein Urteil, nämlich stillPresent (trifft weiterhin zu), resolved (behoben oder konstruktionsbedingt nicht zutreffend) oder inconclusive (nicht feststellbar), dazu einen sprachunabhängigen Begründungscode. Das Tool dient dazu, nach einer Korrektur zu prüfen, ob sie wirklich gewirkt hat. Ein Eintrag, der sich nicht messen ließ, etwa wegen fehlender Berechtigungen, eines nicht verbundenen privilegierten Helpers oder eines nicht erreichbaren Docker, wird nie als sicher gemeldet, sondern als inconclusive. Ohne checkIds werden alle Einträge geprüft (höchstens 50 IDs auf dem Mac und 64 unter Linux; unter Linux ist zusätzlich isServer möglich). Auf dem Mac werden host_firewall, network_stealth_mode, gateway_arp_lock, malware_scanning, dns_threat_guard und usb_zero_trust anhand der App-Einstellungen von RoamSwitch entschieden. Sie geben also diese Einstellungen wieder und messen den tatsächlichen Zustand des Betriebssystems nicht neu. Der Zugriff ist schreibgeschützt, es gibt keine Verbindung zu externen Hosts, keine Reparatur und keine Änderung von Einstellungen. Unter Linux wird auch nichts ins LAN gesendet, das Gateway wird nur aus lokalen Caches gelesen. Auf dem Mac kann zur Ermittlung der Gateway-MAC-Adresse ein ICMP-Ping, normalerweise einer (bei nicht auflösbarer MAC einige), an das Gateway im LAN gehen. |
| audit_mcp_configs | Liest die MCP-Konfigurationsdateien der KI-Clients (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code, Cline, Gemini CLI sowie .mcp.json und ähnliche Dateien in den registrierten Projektordnern) und meldet riskante Einstellungen. Erkannt werden Tools, die ohne Bestätigung je Aufruf automatisch genehmigt werden (auto_approve), Klartext-http://-Server auf einem Nicht-Loopback-Host, ob im Feld url oder als Startargument wie --server http://… angegeben (remote_plain_http), Startbefehle als Shell- oder Interpreter-Einzeiler (shell_wrapper), Starter wie npx / uvx / docker run, die ein nicht festgelegtes Paket oder Image laden (unpinned_package_launcher), docker run mit --privileged oder mit eingebundenem Docker-Socket oder Root-Dateisystem (container_host_access), Umgebungsvariablen, die beim Start zusätzlichen Code laden, etwa LD_PRELOAD oder --require in NODE_OPTIONS (Namen ohne Beachtung der Groß-/Kleinschreibung, Werte werden nie zurückgegeben; code_loading_env), Einträge, die auf HexStrike AI zeigen, ein Angriffstool-Backend ohne Authentifizierung (hexstrike), für Gruppe oder andere beschreibbare Konfigurationsdateien (world_writable_config), der Schalter enableAllProjectMcpServers von Claude Code (auto_trust_project_servers) und eine Konfigurationsdatei, in der ein Server, der von anderen geschriebenen Text liest (Webseiten, Mails, Chats, Issues), neben einem Server steht, der Befehle ausführen oder Dateien ändern kann, also die Kombination, die indirekte Prompt-Injection braucht (anhand bekannter Paketnamen erkannt, die Inhalte der Server-Tools werden nicht gesehen; injection_exposure). Das Tool hat keine Argumente, ist schreibgeschützt und sendet nichts ins Netzwerk. Es gibt keine Env- oder Header-Werte, Argumente oder Geheimnisse zurück, nur Servernamen, den Basisnamen eines Befehls, einen URL-Host und, bei einem einfachen Registry-Namen, den Paket- oder Image-Namen. Nicht lesbare Dateien stehen in unreadableFiles und wurden nicht geprüft. |
| audit_agent_setup | Liest die Anweisungsdateien und Skills, die KI-Agenten bekommen (CLAUDE.md, commands, agents und skills unter ~/.claude, dazu ~/.codex, ~/.cursor/rules, ~/.gemini, ~/.agents, ~/.openclaw sowie CLAUDE.md, AGENTS.md, .cursorrules und Ähnliches in den registrierten Projektordnern) und OpenClaws openclaw.json und weist auf riskante Inhalte und Einstellungen hin. In Anweisungs- und Skill-Dateien meldet es in unsichtbaren Unicode-Tag-Zeichen versteckte Sätze (hidden_tag_characters), Zeichen ohne Breite und Steuerzeichen für die Schreibrichtung (invisible_characters), Formulierungen, die frühere Anweisungen aufheben oder dem Benutzer etwas verschweigen (override_instruction), Herunterladen-und-Ausführen wie curl … | sh (remote_script_exec), Dekodieren-und-Ausführen (encoded_payload_exec), Verweise auf Schlüssel- und Zugangsdatenspeicher (credential_access) neben einem Upload oder einem Ablage-Dienst (credential_exfil_shape, exfil_endpoint), das Einrichten von Dauerhaftem (persistence_instruction), kompilierten Code in einem Skill (skill_precompiled_code) und für andere beschreibbare Dateien (agent_file_writable). Alles innerhalb eines HTML-Kommentars wird höher eingestuft, weil eine gerenderte Seite es verbirgt. Für OpenClaw werden ausgeschaltete Authentifizierung (openclaw_auth_disabled), eine aus dem Netzwerk erreichbare Bindung (openclaw_wide_bind), ein Token unter 24 Zeichen (openclaw_weak_token), ein Wildcard-Origin (openclaw_origin_wildcard), eingeschaltete dangerously…-Schalter (openclaw_dangerous_flag), eine Proxy-Liste, die jedem vertraut (openclaw_broad_trusted_proxy, openclaw_proxy_trust_loosened), für jeden offene DM- oder Gruppenrichtlinien (openclaw_open_dm), mDNS full (openclaw_mdns_full), ausgeblendete Selbstprüfungs-Befunde (openclaw_audit_suppressed) und lockere Berechtigungen (openclaw_loose_permissions) gemeldet. Jede Regel ist deterministisch: Ein Treffer heißt „ein Mensch sollte diese Zeile lesen“, nicht „bösartig“. Es nimmt keine Argumente, ist schreibgeschützt und sendet nichts ins Netzwerk. Es gibt nie Dateiinhalte oder Geheimnisse zurück (ein Token nur als Länge), sondern nur Regelname, Zeilennummer, URL-Host und Konfigurationsschlüsselpfad. Nicht lesbare Dateien stehen in unreadableFiles und wurden nicht geprüft. |
| get_exposed_ports | exponierte Ports und deren Firewall-Blockierungsstatus |
| get_guard_status | aktuelle Schutzstufe und Status des Verteidigungsmoduls |
| audit_url_safety | Heuristische URL-Sicherheitsanalyse (ruft das Ziel nicht ab) |
| audit_secrets | Erkennung von API-Schlüsseln/Geheimnissen im Text (übermittelt den Text nicht) |
| audit_security_logs | Aggregation lokaler Journal-/Authentifizierungsprotokolle |
| get_quarantine_status / get_canary_status | Quarantäne und Kanarienstaat |
| get_app_help | Suche in der integrierten Wissensdatenbank |
| run_active_vuln_scan | Zerstörungsfreie aktive Schwachstellenprüfung, ausschließlich auf 127.0.0.1. Es wird kein anderer Host kontaktiert, aber das Tool sendet Netzwerkanfragen; es ist daher standardmäßig deaktiviert und muss in den Einstellungen per Opt-in aktiviert werden. |
| run_package_cve_scan | Gleicht installierte Pakete (Mac: Homebrew / Linux: dpkg, dnf, zypper, pacman) mit einer lokalen CVE-Zuordnung ab. Es findet überhaupt keine Netzwerkkommunikation statt. Unter Linux wird bei nicht lesbarer oder zeitüberschrittener Paketliste nicht „kein Treffer“ gemeldet, sondern complete ist false und incompleteReason nennt den Grund (ein unvollständiges Ergebnis ist kein sauberes Ergebnis). Unter Ubuntu (20.04, 22.04, 24.04, 26.04) werden die Ubuntu-eigenen Daten verwendet und nach Quellpaketname und Quellversion abgeglichen; geprüft werden nur CVEs mit CVSS 7,0 oder höher, für die Ubuntu bereits eine Korrektur veröffentlicht hat, daher bedeutet „kein Treffer“ nicht, dass es keine bekannten CVEs gibt. Das Ergebnis enthält zusätzlich ecosystem und release, jeder Treffer trägt binary (den installierten Binärpaketnamen); Korrekturen, die nur über Ubuntu Pro verfügbar sind, sind mit proOnly markiert. Ubuntu-Derivate (Linux Mint, Pop!_OS und andere) und nicht unterstützte Versionen liefern complete = false mit dem Grund in incompleteReason und werden nicht auf die Debian-Daten umgestellt. |
| run_package_cve_scan_languages | Gleicht Abhängigkeits-Lockfiles für npm, PyPI, crates.io, RubyGems, Packagist, Go und Maven mit derselben lokalen CVE-Zuordnung ab. Es findet überhaupt keine Netzwerkkommunikation statt. |
| get_vulnerability_scan_history | Liefert für jede von scan-vulns --confirm erfasste Prüfung die Anzahl der Tage seit ihrer letzten tatsächlichen Ausführung und Bestätigung (pass_age_days). |
| verify_fim | Berechnet die Hashes von 23 festen kritischen Systemdateien, jeder Datei direkt in 12 Verzeichnissen (Authentifizierung, cron, systemd, SSH-Konfiguration u. a.), den eigenen Binärdateien von RoamSwitch und der authorized_keys jedes Benutzers neu und vergleicht sie mit der Basislinie, um Manipulation und neue Dateien zu prüfen. Bei Ausführung als root enthält das Ergebnis außerdem ein zusätzliches Feld, recentIntrusionContext: zu jeder jüngsten Änderung den Prozess, der sie vorgenommen hat (Konto, ausführbare Datei, Befehl), und die SSH-Anmeldung, zu der er gehört (Quelle, Anmeldezeit, Authentifizierungsmethode), oder den Grund, warum das nicht ermittelt werden konnte. |
| get_file_scan_guard_status | Liefert die Konfiguration des File Scan Guard (ClamAV) und den Zustand des zugehörigen Quarantäne-Tresors (ein Tool der Server Edition; es meldet nicht die Einstellungen des Malware-Guards der Client-Edition). |
| get_port_anomaly_incidents | Liefert den Baseline-Zustand des Port-Anomalie-Schutzes, aktuell automatisch blockierte Ports und bis zu die 50 jüngsten Vorfälle. Die Antwort weist ausdrücklich darauf hin, dass die aktuell blockierten Ports eine zeitstempellose Momentaufnahme sind, die sich von der zeitgestempelten Vorfallshistorie unterscheidet. |
| get_ebpf_incidents | Liefert den aktuellen Isolationsstatus des eBPF-Runtime-Guards und die Vorfallshistorie dahinter. In der Server Edition trägt jeder Eintrag außerdem die Zeit von der Erkennung bis zur Reaktion in Millisekunden (detect_to_receive_ms, receive_to_action_ms, detect_to_action_ms), und das Ergebnis enthält den Zustand des Falco-Heartbeats (heartbeat). |
| get_ssh_guard_incidents | Gibt Zustand und Verlauf des SSH-Brute-Force-Schutzes zurück: ob er sperrt oder nur erkennt (zum Beispiel weil ein anderes Werkzeug sshd bereits schützt), die aktuell gesperrten Quellen mit Restzeit und bis zu 200 jüngste Einträge (eine Quelle wurde gesperrt, nur erkannt, oder eine Anmeldung gelang nach einer Serie von Fehlversuchen derselben Quelle). Die versuchten Benutzernamen werden unter Linux nicht gespeichert (nur die Anzahl) und unter Mac bereinigt mit bis zu 5 Namen zurückgegeben. Der Mac liefert zusätzlich die letzten SSH-Anmeldungen (Quelle, Benutzer, Methode, Schlüssel-Fingerabdruck). Schreibgeschützt: Kein MCP-Tool hebt eine Sperre auf. Unter Linux kann nur root die Sperrliste lesen; ein Aufruf ohne root liefert nur die Anzahl. Linux: die Server Edition sowie die Client Edition, solange sshd läuft. Mac: nur Pro. |
| get_resource_guard_incidents | Liefert die Historie des Ressourcen- und Prozessanomalie-Schutzes (Speicherlecks, Crash-Loops) samt Konfidenzstufe (dieser Guard gehört zur Server Edition; die Client-Edition führt ihn nicht aus, daher ist das Ergebnis dort immer leer). |
| get_notification_history | Gibt den Verlauf der von RoamSwitch gesendeten Benachrichtigungen (Sicherheitslog-Auffälligkeiten, ClickFix-Erkennungen u. a.) der letzten 7 Tage zurück, neueste zuerst. |
| get_incident_timeline | Führt die Erkennungen aller Schutzmodule zu einer chronologischen Zeitleiste zusammen — mit Prozessabstammung und MITRE-ATT&CK-Tags (experimentell). |
Die aktive Schwachstellenprüfung erfasst zusätzlich für jede bestätigte Prüfung, wie viele Tage seit ihrer letzten tatsächlichen Ausführung und Bestätigung vergangen sind (pass_age) — und unterscheidet damit „dieses Prüfung existiert“ von „diese Prüfung wurde tatsächlich kürzlich verifiziert“. Da es noch keinen geplanten Ausführungsmechanismus gibt, spiegelt dieser Wert lediglich wider, wie oft der Scan tatsächlich ausgeführt wurde. Dieselbe Anzahl vergangener Tage ist über die CLI (roamswitch vuln-status), die GUI und MCP (get_vulnerability_scan_history) abrufbar, sodass Betreiber oder Prüfer erkennen können, wann zuletzt tatsächlich geprüft wurde, statt allein aus der Existenz der Funktion auf eine aktuelle Prüfung zu schließen.
Der MCP-Server öffnet selbst kein Netzwerk. Nur get_sensor_audit_results verbindet sich direkt mit dem Unix-Socket des Daemons (/run/roamswitch/roamswitch.sock); alle anderen Tools rufen entweder die Logik von roamswitch-core direkt auf oder lesen nur Statusdateien, die der Daemon geschrieben hat (roamswitchkit arbeitet in der Gegenrichtung: Es ist das SDK, mit dem die CLI und andere roamswitch-mcp als Kindprozess starten). Ausnahmen sind zwei standardmäßig deaktivierte Tools: run_active_vuln_scan sendet nicht-destruktive Prüfanfragen an 127.0.0.1, also an den Host selbst, und run_npm_audit_signatures startet den Befehl npm, der die npm-Registry abfragt (die MCP-Binärdatei selbst enthält keinen HTTP-/TLS-Stack). Die Auswertung von get_security_report und verify_security_findings sendet nichts ins LAN, und das Gateway wird nur im ARP-Cache und in anderen lokalen Informationen nachgeschlagen. Ein Ping kann nur in anderen Abläufen ausgehen, die die Gateway-MAC neu auflösen (ARP-Überwachung des Daemons, Notfallwiederherstellung, Sensor-Kopplung, get_guard_status und Ähnliches).
Eine bei einer Fire-Drill-Übung mit einem lokalen LLM entdeckte und behobene Fehlzuordnung
Im September 2026 führten wir mit diesem MCP-Server eine Übung durch, bei der ein lokales LLM (Qwen 3.8 27B) einen Vorfall untersuchen sollte, und entdeckten dabei einen Fall, in dem das Modell die von get_port_anomaly_incidents zurückgegebenen Daten falsch interpretierte und eine unabhängige, ältere Portsperrung in die Erzählung eines laufenden Vorfalls einflocht. Die Ursache: Eine zeitstempellose Momentaufnahme der aktuell blockierten Ports wurde in derselben Antwort wie die echte, zeitgestempelte Vorfallshistorie zurückgegeben, ohne dass etwas zwischen beiden unterschied. Die Korrektur fügt explizite Hinweisfelder hinzu, die kennzeichnen, welches Feld eine Zeitleiste und welches eine Momentaufnahme ist. Beim erneuten Ausführen desselben Szenarios mit demselben Modell zitierte dieses den Wortlaut des Hinweises und lehnte es ausdrücklich ab, den alten Port dem aktuellen Vorfall zuzuordnen. Die Wirksamkeit der Korrektur wurde sowohl durch einen automatisierten Regressionstest als auch durch die erneute Ausführung mit dem echten lokalen LLM bestätigt.
§9
RoamSwitch für Linux stellt standardmäßig genau eine Art ausgehender Anfrage: den GET des täglichen Updaters auf ein signiertes Manifest (§11). Alles andere – jede Bewertung, Erkennung und Prüfung – läuft lokal ab. Kommunikation, die nur entsteht, wenn ein Betreiber oder Benutzer sie ausdrücklich aktiviert oder auslöst, ist in 9.4 aufgeführt. RoamSwitch für Linux ist proprietäre Freeware, der Quellcode wird nicht veröffentlicht; die folgenden Prüfungen wurden daher von lafine durchgeführt. Die Ergebnisse stehen in 9.2, die Schritte in Anhang C sind allein mit dem verteilten Paket reproduzierbar.
9.1 Prüfmethode
- Crate-Isolation — Ein HTTP-Client-/TLS-Stack ist in nur einem Crate erlaubt:
roamswitch-updater, das die eigenständige, zeitgesteuerte Updater-Binärdatei baut.scripts/audit_no_network.sh(in der CI als Gate ausgeführt) lässt den Build scheitern, wennroamswitch-core,roamswitch-daemon,roamswitch-app,roamswitch-mcp,roamswitchkit(oder die CLI- und Server-Crates) einen HTTP-Client-/TLS-Stack wiereqwest/ureq/rustls/native-tls/openssl-syseinbinden oder wenn eine.rs-Datei außerhalb vonroamswitch-updaterund der in 9.4 genannten DateienTcpStream/TcpListener/UdpSocket/to_socket_addrs/lookup_hostverwendet. Die einzige zusätzliche Erlaubnis betriffttonic/hyper, nur inroamswitch-corefür gRPC über einen UNIX-Domain-Socket zum eBPF-Sensor (Tetragon); dasselbe Skript verbietet die Kombination mit TLS. - Abhängigkeitsbauminspektion – der vollständige
Cargo.lockwurde nach Telemetrie-/Analyse-/Absturzberichts-SDKs durchsucht (sentry,opentelemetry, …). roamswitch-updater-Review – sein einziges Anfrageziel, das Fehlen von Query-String und Cookies, ein fester User-Agent als einziger Header, der die Software nennt, und seine Ed25519-Prüfung von allem, was er herunterlädt.- Subprocess enumeration – jede
Command::new(...)-Aufrufseite wurde überprüft.
9.2 Ergebnisse
| Prüfungselement | Ergebnis |
|---|---|
| HTTP/TLS-Stack | Nur in roamswitch-updater (ureq + rustls) vorhanden. Nicht in core / daemon / app / mcp / kit |
| Telemetrie-/Analyse-/Absturzberichts-SDK | Nicht vorhanden nirgendwo |
TcpStream / TcpListener / UdpSocket | Nur in roamswitch-updater und in den vier Dateien der Opt-in-Funktionen aus 9.4 |
| Verwendete Socket-APIs | AF_UNIX (lokale IPC); AF_NETLINK (NFQUEUE-Verdict-Kanal, nftables und ip neigh-Steuerung – kein Paketaustritt); AF_INET nur in roamswitch-updater und in den Opt-in-Funktionen aus 9.4 (TLS/HTTP übernehmen die System-Subprozesse openssl/curl); AF_PACKET nur, wenn die ARP-Neuprüfung (§4) ein einzelnes ARP-who-has an das Gateway sendet (im LAN). Der VPN-Tunnel (§4) ist, wenn aktiviert, wg-quick (WireGuard-Backend) oder tailscaled (Tailscale-Backend) – ein Subprozess, nicht der Daemon – und sendet Verkehr an den eigenen Endpunkt bzw. das eigene Tailnet des Benutzers |
| Täglicher Updater | Zwei Anfragen etwa alle 24 Stunden: GET https://lafine.net/updates/v1/manifest und die Signatur manifest.sig (die Datendateien werden zusätzlich nur geholt, wenn ihre Version neuer ist). Keine Abfragezeichenfolge, keine Cookies, fester User-Agent: RoamSwitch-Updater (der einzige Header, der die Software nennt), keine gerätespezifische Kennung. Alle Nutzlasten Ed25519-verifiziert. updates.enabled = false deaktiviert es vollständig |
| VPN-Tunnel (§4) | Standardmäßig deaktiviert. Wenn diese Option aktiviert ist, erstellt wg-quick einen WireGuard-Tunnel zum Endpunkt im eigenen .conf des Benutzers – ohne Bezug zu lafine. Auflösung des Endpunkt-Hostnamens über getent ahosts (glibc NSS), nicht über eine Rust-Socket-API |
| Lizenzaktivierung | Offline-Ed25519-Signaturüberprüfung. Keine Kommunikation mit einem Aktivierungsserver |
RoamSwitch für Linux löst standardmäßig genau eine Art ausgehender Anfrage aus: die tägliche, rein empfangende Prüfung eines signierten Manifests samt Download signierter Erkennungsdaten, wenn eine neuere Version vorliegt; nichts davon enthält Informationen über Benutzer oder Maschine. Sofern ein Betreiber oder Benutzer es nicht ausdrücklich aktiviert oder auslöst, kontaktiert nichts sonst im Produkt einen externen Server (9.4). Der Ping, der für die Fixierung der Nachbartabelle und die ARP-Überwachung ins LAN geschickt wird (#2 in 9.3), geht nur an Loopback-, private, Link-Local- und ULA-Adressen und wird nie an eine öffentliche Adresse gesendet.
9.3 Vollständige Liste der nach außen gerichteten Operationen
Alle Vorgänge im Standardbetrieb, die – direkt oder indirekt – dazu führen können, dass ein Paket die lokale Maschine verlässt (die folgende Tabelle; Vorgänge, die nur auftreten, wenn ein Betreiber oder Benutzer sie aktiviert oder auslöst, stehen in 9.4):
| # | Betrieb | Ziel | Auslöser | Was wird gesendet? |
|---|---|---|---|---|
| 1 | Täglicher Updater – GET /v1/manifest und seine Signatur; die Datendateien nur, wenn ihre Version neuer ist (die CVE-Karten für Kernel, OS-Pakete und Sprachen werden etwa alle 30 Tage geprüft; ein Ubuntu-Gerät ohne die Ubuntu-CVE-Karte holt sie beim nächsten täglichen Lauf) | lafine.net/updates/v1 (CDN) | systemd-Timer: Start 15 Minuten nach dem Booten, danach etwa alle 24 Stunden mit einer zufälligen Verzögerung von bis zu 3 Stunden. Aus, wenn updates.enabled = false oder roamswitch-update.timer deaktiviert ist | ein einfaches HTTPS-GET: keine Abfragezeichenfolge, keine Cookies, fester User-Agent: RoamSwitch-Updater, nichts über den Benutzer oder die Maschine. Erhält ein signiertes Manifest + Feed |
| 1a | freshclam (ClamAVs eigener Updater), der vom täglichen Updater aufgerufen wird, wenn ClamAV installiert wird | Das CDN des ClamAV-Projekts | als Teil von #1; außerdem, wenn der Benutzer in der GUI auf die Schaltfläche „Virendefinitionen jetzt aktualisieren (freshclam)“ klickt | Verkehr von ClamAV selbst (ein separates Projekt); RoamSwitch startet es nur |
| 2 | ping -c 1 -w 1 -W 1 <Gateway-IP> (derselbe einzelne Ping je einmal auch an den IPv6-Router und an die DNS-Server im LAN) | das LAN-Standard-Gateway; bei der ARP/NDP-Fixierung zusätzlich der IPv6-Standardrouter und die in resolv.conf aufgeführten DNS-Server (unter systemd-resolved /run/systemd/resolve/resolv.conf), soweit ihre Adresse eine Loopback-, private, Link-Local- oder ULA-Adresse ist. An einen öffentlichen Resolver (etwa Quad9 aus dem Bedrohungsschutz-DNS) wird kein Paket gesendet | Beim Gateway nur, wenn seine MAC benötigt wird (ARP-Überwachung und Ähnliches) und weder im ARP-Cache noch in der Nachbartabelle noch in der 15 Sekunden gültigen Kopie im Arbeitsspeicher steht (höchstens einmal alle 8 Sekunden pro Ziel). Beim IPv6-Router und bei den DNS-Servern dann, wenn die Gateway-ARP-Sperre (gateway_arp_lock_enabled, standardmäßig an) die Nachbartabelle neu fixiert (beim Wechsel in ein nicht vertrauenswürdiges Netzwerk und beim Umschalten der Einstellung) | Nur eine einzelne ICMP-Echo-Anfrage (mit den Standarddaten von ping). Keine DNS-Auflösung |
| 3 | Starten des Systembrowsers (xdg-open) | https://roamswitch.com/linux (Produktseite), https://lafine.net/ (Betreiberseite, Nutzungsbedingungen, Kontakt) und https://github.com/lafine1211/roamswitch-support (Versionshinweise und Support) | nur wenn der Benutzer auf eine Schaltfläche wie „Versionshinweise öffnen“ klickt | der RoamSwitch-Prozess öffnet keinen Socket; Es übergibt die URL an den Betriebssystembrowser |
| 4 | lösenctl dns | — (es findet keine Kommunikation durch RoamSwitch selbst statt) | Bedrohungsschutz-DNS in einem nicht vertrauenswürdigen Netzwerk (standardmäßig an, abschaltbar). <iface> ist jede physische Netzwerkkarte, die eine Standardroute trägt (kabelgebunden und drahtlos gleichzeitig; lo / tailscale* / wg* / docker* / veth* ausgeschlossen); wird auch auf ein vertrauenswürdiges Netzwerk angewendet, wenn dns_scope = always_on; jeden Sentinel-Zyklus in Einklang gebracht | es ändert nur die OS-Resolver-Einstellung; RoamSwitch selbst sendet keine DNS-Anfrage. Danach geht die Namensauflösung dieser Netzwerkschnittstelle an das gewählte Bedrohungsschutz-DNS (standardmäßig Quad9) |
| 5 | Paketmanager-Updates | die apt-/dnf-/zypper-/pacman-Repositorys der Distribution | wenn der Benutzer apt upgrade usw. ausführt oder auf die GUI-Schaltfläche „Jetzt aktualisieren“ klickt (wodurch apt-get / dnf / zypper / pacman über pkexec ausgeführt wird) | Bei apt-Systemen liest RoamSwitch nur die lokale Ausgabe von apt-cache policy und startet den Paketmanager. Bei dnf-Systemen führt es (unter anderem beim Öffnen des Update-Tabs) dnf check-update aus, was die konfigurierten Repositorys abfragen kann (zypper: zypper list-updates, pacman: pacman -Qu); in jedem Fall hat das nichts mit lafine zu tun |
| 6 | VPN-Tunnel (§4) – WireGuard-Backend: Der Tunnel wg-quick baut / Tailscale-Backend: tailscale set --exit-node leitet den gesamten Datenverkehr über den Ausgangsknoten | der eigene VPN-Endpunkt/Tailnet des Benutzers (WireGuard: der Endpunkt im .conf; Tailscale: der ausgewählte Exit-Knoten und die DERP-Relays) | wenn vpn_on_untrusted_enabled und das Netzwerk nicht vertrauenswürdig ist. Standardmäßig deaktiviert | verschlüsselter WireGuard/Tailscale-Verkehr; Das Ziel ist der eigene VPN-Server/Tailnet des Benutzers, unabhängig von Lafine. WireGuard-Endpunktauflösung über getent ahosts (glibc NSS); Tailscale wird von tailscaled gesteuert (ein separater Prozess) |
Alle übrigen RoamSwitch-Funktionen – nftables-Steuerung, ARP/NDP-Fixierung der Neighbour-Tabelle (ip neigh, kein Paketaustritt), Link-Guard (NFQUEUE, nur AF_NETLINK), Port-Scanning (Auswertung der ss-Ausgabe), ARP-Überwachung, Gesundheitsbewertung, Entropie-Überwachung, Kanarien, fanotify, USB-Überwachung (evdev-Grab), Quarantäne, Log-Audit, URL- und Geheimnis-Audit – kommen ausschließlich mit lokalen Dateilesevorgängen und der Auswertung von Subprozess-Ausgaben aus. Der VPN-Tunnel aus §4 ist die „vom Benutzer ausdrücklich konfigurierte ausgehende Kommunikation“; sein Ziel ist der eigene VPN-Server des Benutzers – es fließen keine Daten zur Infrastruktur von lafine. Das Ziel jeder Funktion aus 9.4 wird dort angegeben.
9.4 Vorgänge, die nur bei Opt-in oder auf Benutzeraktion nach außen gehen
Die Tabelle in 9.3 zeigt, was standardmäßig geschieht. Im Folgenden stehen die Stellen im Code, die einen Socket öffnen oder die Kommunikation an ein externes Programm (curl / openssl / npm) übergeben und die nur laufen, wenn ein Betreiber oder Benutzer sie ausdrücklich aktiviert oder auslöst. scripts/audit_no_network.sh erlaubt Socket-APIs nur in fünf Dateien – event_forward.rs, webhook_guard.rs, active_vuln_scan.rs, web_vuln_scan.rs und sensor_pairing.rs (webhook_guard.rs löst nur dann, wenn die standardmäßig deaktivierte Einstellung forward_webhook_block_private_addresses aktiviert ist, den Namen des Webhook-Ziels mit dem System-Resolver auf, um zu prüfen, dass es keine interne Adresse ist; es verbindet sich nie. Dazu kommt tests/fleet_roundtrip.rs, nur für Tests, das sich ausschließlich mit einem Mock-Server auf 127.0.0.1 verbindet) – und lässt den Build scheitern, wenn anderer Quellcode TcpStream o. Ä. verwendet. Auch diese Funktionen fügen kein HTTP-/TLS-Crate hinzu: TLS übernimmt das System-openssl, HTTP das System-curl, jeweils als Subprozess.
- Ereignisweiterleitung (
event_forward.rs) — standardmäßig aus (forward_enabled = false), und Ziele sind nur die, die der Betreiber von Hand konfiguriert; es gibt kein eingebautes Ziel. Unterstützte Senken sind Syslog (RFC 5424 oder CEF, über UDP / TCP / TLS), eine JSON-Lines-Datei und ein mit HMAC-SHA256 signierter Webhook. TLS-Syslog läuft über das System-openssl s_client, der Webhook über das System-curl(Geheimnisse wie URL und Signatur werden in einer Konfiguration über die Standardeingabe übergeben, nie in der Kommandozeile); der Daemon enthält kein TLS-/HTTP-Crate. Gesendet werden nur diese Felder: Hostname, Ereignis-ID, Zeitstempel, Quelle, Schweregrad, Regel, Aktion, PID, Prozessname und Zusammenfassung (keine Dateiinhalte und kein Rohprotokoll der Ausführungsaufzeichnung). Über TCP / TLS / Webhook nicht zugestellte Ereignisse werden in einer0600-Warteschlange auf der Platte (Standardgrenze 20 MB / 72 Stunden) gehalten und erneut versucht. - Fleet (Business-Stufe, nur Geräteseite) (
roamswitch-core/src/fleet/) — der geräteseitige Code ist in der Binärdatei enthalten, aber ein nicht registriertes Gerät sendet nichts und löst nicht einmal den Fleet-Hostnamen auf (der Worker liest nur eine lokale Statusdatei). Die Registrierung erfolgt nur, wenn ein Betreiberroamswitch fleet enrollausführt. Der Verwaltungsdienst ist weder bereitgestellt noch veröffentlicht, es gibt also derzeit nichts, womit man sich verbinden könnte. Die im Code vorhandenen Design-Zusicherungen sind: (a) Das Gerät akzeptiert nur von der Organisation signierte Richtlinien-Konfigurationsdaten, geprüft gegen den bei der Registrierung festgeschriebenen öffentlichen Organisationsschlüssel; eine Richtlinie, die die Prüfung nicht besteht, wird nicht angewendet. Vorgesehen ist, dass der Signaturschlüssel der Organisation beim Kunden liegt und nicht bei lafine. (b) Es gibt keinen Fernbefehlsweg – auf der Geräteseite existiert kein Endpunkt, kein Feld und kein Codepfad, über den man dem Gerät Isolieren, Aufheben, Sammeln oder Ausführen befehlen könnte. (c) Eine Richtlinie kann die lokale Untergrenze nicht abschwächen: Das Abschalten eines Wächters oder das Behindern von Aufhebung / Notfallwiederherstellung lässt sich im Schema gar nicht ausdrücken, und es gilt jeweils der strengere Wert. Das Ziel der Ereignisweiterleitung darf eine Richtlinie zudem nur auf Hosts ändern, die der lokale Root erlaubt hat (fleet_forwarding_allowed_hosts, standardmäßig leer). (d) Ein Gerät sendet nur eine minimale Statuszusammenfassung – App-Version, Betriebssystemfamilie, Isolationszustand (normal / isoliert), angewendete Richtlinienversion, Gesundheitswert (0–100) und Schlüsselepoche – sowie Geräte-ID und Organisations-ID in den Signatur-Headern. Es nutzt das System-curl(TLS) und nur für ein registriertes Gerät. - Sensor-Kopplung (
sensor_pairing.rs) — standardmäßig aus (sensor_pairing_enabled). Sie verbindet sich nur direkt mit der vom Betreiber eingegebenen Sensor-Adresse; es gibt kein eingebautes Ziel. Sie unterstützt TLS 1.3 (über das System-openssl, mit Zertifikat-Fingerprint-Pinning), doch eine ältere Kopplung ohne Pin fällt mit einer Warnung auf Klartext zurück. Der Sensor ist ein eigenes Produkt und nicht von den Zero Telemetry-Aussagen dieses Dokuments abgedeckt. - Aktive Schwachstellenprüfung (
active_vuln_scan.rs/web_vuln_scan.rs) — standardmäßig deaktiviert und nur per Opt-in in den Einstellungen nutzbar. In dieser Endgeräte-Edition beschränkt sich der Pfad auf Sondierungen an127.0.0.1für auf dieser Maschine bereits beobachtete lauschende Ports (durch die eigenen Tests der Module festgeschrieben). - Die Schaltfläche „Nach Updates suchen“ der GUI – nur wenn der Benutzer die Schaltfläche drückt und nur bei apt-basierten Distributionen, führt die GUI mit dem System-
curleinen einzelnenGETaufhttps://lafine.net/apt/dists/stable/main/<arch>/Packagesaus, um die neueste Version zu ermitteln (Timeout 4 Sekunden; eine öffentliche URL ohne Geheimnis, ohne angehängte Kennung oder Query-String). Bei dnf-, zypper- und pacman-Systemen wird curl nicht verwendet; stattdessen wird der jeweilige Paketmanager abgefragt (#5 in 9.3). - npm-Signaturprüfung —
roamswitch audit-npm-signatures <DIR> --confirmläuft nur, wenn die Einstellungnpm_audit_signatures_enabled(Standard false) aktiviert ist und der Benutzer den Befehl mit--confirmausführt; dann kontaktiertnpmselbst registry.npmjs.org.
§10
- Kein Konto – keine Benutzerregistrierung, kein Login, keine E-Mail-Adresse jemals angefordert.
- Konfiguration ist nur lokal – wird im Klartext unter
~/.config/roamswitch/config.jsongespeichert und verlässt den Computer nie. Es gibt keine Cloud-Synchronisierung. - Bewertungsergebnisse sind nur lokal – Sicherheitsberichte und Protokollprüfungsergebnisse werden nur auf dem Bildschirm angezeigt und, wenn der Benutzer dies wünscht, in eine lokale Datei exportiert.
- Lizenzschlüssel werden offline überprüft – Pro-/Business-Lizenztoken enthalten eine Ed25519-Signatur und werden mit einem öffentlichen Schlüssel überprüft. Es erfolgt keine Abfrage an einen Lafine-Server.
- Keine Absturzmeldung – im Panikfall wird nirgendwo ein Stack-Trace gesendet.
- Der tägliche Updater sendet nichts über Sie – keine Abfragezeichenfolge, keine Cookies, keine geräte- oder installationsspezifische Kennung, als einziger Header, der die Software nennt, ein fester
User-Agent: RoamSwitch-Updater. Es handelt sich um einen Download, nicht um einen Bericht. Link-Guard-Urteile, blockierte Hosts und Scan-Ergebnisse werden nur in die lokale Aktivitätsansicht/das Journal geschrieben und niemals übertragen. - Solange DNS mit Bedrohungsschutz verwendet wird, gehen DNS-Abfragen an einen externen Resolver. DNS mit Bedrohungsschutz (§4.5; standardmäßig an, nur für nicht vertrauenswürdige Netzwerke) richtet den DNS-Resolver des Betriebssystems auf Quad9 (
9.9.9.9; alternativ lässt sich1.1.1.2von Cloudflare wählen) aus. In dieser Zeit sendet nicht RoamSwitch, sondern das Betriebssystem die Abfragen an diesen Resolver; RoamSwitch selbst sendet nichts. Zum Abschalten setzen Siedns_enabledauffalse. - Der Benachrichtigungsverlauf wird nach 7 Tagen gelöscht und in der Länge begrenzt — der Verlauf gesendeter Benachrichtigungen wird lokal gespeichert, und bei jedem Schreiben werden Einträge gelöscht, die älter als 7 Tage sind. Ein Titel wird auf 200 Zeichen und ein Text auf 2000 Zeichen gekürzt (ein Desktop-Benachrichtigungs-Popup zeigt höchstens 1000 Zeichen Text). Dieser Verlauf verlässt die Maschine nicht, sofern die Ereignisweiterleitung (standardmäßig aus) nicht aktiviert ist.
- Auch das Ausführungsprotokoll bleibt lokal — das Protokoll des Prozess-Ausführungsrekorders (§5) wird standardmäßig nur auf der Maschine gespeichert (
/var/lib/roamswitch/exec_log,0600). Da es Kommandozeilenargumente enthält, wird es automatisch nach Aufbewahrungsdauer (Standard 14 Tage) und Größe (Standard 200 MB) gelöscht.
§11
| Auflage | Für | Preis | Lizenz |
|---|---|---|---|
| Community Edition | Linux, private Nutzung und betrieblicher Einsatz im Unternehmen (keine Begrenzung der Geräteanzahl) | Kostenlos | Proprietäre Freeware (gebündelte EULA) |
| Business (geplant) | Flottenmanagement, Richtlinienverteilung, unterzeichnete interne Vereinbarung, SLA für Organisationen | Bezahlt | Kommerzielle Lizenz. Gleiches binäres + Tier-Gate |
Sobald die Business-Stufe angeboten wird, ist vorgesehen, Käufern von macOS RoamSwitch Pro Lifetime die Business-Funktionen auf ihren eigenen Linux-Rechnern kostenlos zu gewähren. Die Business-Stufe wird derzeit nicht angeboten, und es gibt keinen Verwaltungsserver.
Vertrieb und Lieferkette
| Kanal | Detailliert |
|---|---|
| APT | https://lafine.net/apt (stable main). Release signiert mit einem RSA-4096-Schlüssel |
| U/min | https://lafine.net/rpm (getrenntes Fedora / openSUSE). repomd.xml GPG-signiert |
| AUR | roamswitch-bin (in Vorbereitung. Da AUR derzeit keine neuen Konten annimmt, wird es vorerst mit makepkg aus https://lafine.net/linux/dl/PKGBUILD gebaut; das Tarball von lafine.net/linux/dl wird per sha256 und abgetrennter Signatur (validpgpkeys) überprüft) |
| Tarball | .tar.gz + .sha256 + .asc (abgetrennte Signatur mit dem Repository-Signaturschlüssel) für x86_64 / aarch64 unter https://lafine.net/linux/dl/. Das Quell-Repository ist privat, daher ist dies und nicht GitHub Releases die öffentliche Bezugsquelle |
- Pinned glibc floor – Release-Binärdateien werden in einem Debian 12-Container (Bookworm, Glibc 2.36) erstellt. Dies verhindert Nichtübereinstimmungen der Symbolversionen unter Debian 12 / Ubuntu 22.04 und höher. Ein CI-Schritt „Verify glibc floor“ schlägt beim Build fehl, wenn eine Abhängigkeit eingeführt wird, die mehr als 2.36 erfordert.
- Signierungsschlüsselverwaltung – der private Schlüssel für die Signierung des apt/rpm-Repositorys ist nur in einem verschlüsselten GitHub Actions-Geheimnis vorhanden; nur der öffentliche Schlüssel wird an das Repository übergeben.
11.3 Der tägliche Updater
roamswitch-updater ist eine eigenständige Binärdatei, die von einem systemd-Timer ausgeführt wird (roamswitch-update.timer: 15 Minuten nach dem Start, danach alle 24 Stunden, mit einer zufälligen Verzögerung von bis zu 3 Stunden). Standardmäßig ist sie die einzige Komponente, die eine externe Verteil-URL erreicht (abgesehen von den Opt-in-Funktionen in 9.4). Jeder Lauf:
GET https://lafine.net/updates/v1/manifestund seine abgetrennte Signatur.- Überprüfen Sie die Ed25519-Signatur des Manifests mit einem dedizierten Bedrohungs-Feed-Signaturschlüssel – getrennt vom Sparkle-App-Update-Schlüssel. Der Feed wird täglich vom serverseitigen CI neu signiert, sodass der private Schlüssel in einem CI-Geheimnis gespeichert ist. Wenn man es auf den Feed beschränkt, bedeutet ein Leck, dass ein Angreifer nur eine fehlerhafte Blocklist bereitstellen kann (Sinkhole/Warnung – kein Codepfad, kein App-Update-Pfad). Der App-Update-Signaturschlüssel verlässt niemals den macOS-Schlüsselbund. Ein Manifest, das nicht überprüft wird, wird verworfen – der Updater greift niemals auf nicht signierte Daten zurück.
- Wenn sich die Bedrohungs-Feed-Version geändert hat, laden Sie den Feed herunter, überprüfen Sie seine SHA-256- und Ed25519-Signatur und installieren Sie ihn atomar für den Link Guard (§4). Die übrigen Daten werden nur geholt, wenn das Manifest eine neuere Version zeigt (die CVE-Karte für den aktiven Scan und die Liste beliebter npm-Pakete). Die CVE-Karten für Kernel, OS-Pakete und Sprach-Ökosysteme werden nur geholt, wenn seit der letzten Aktualisierung etwa 30 Tage vergangen sind. Die Ubuntu-CVE-Karte wird nur unter einer unterstützten Ubuntu-Version geholt; ein Gerät, das sie noch nicht hat, holt sie beim nächsten täglichen Lauf, ohne die 30 Tage abzuwarten. Alles wird erst nach der Signaturprüfung installiert.
- Ist die Manifestversion neuer, werden auch die Erkennungsregeln der Web-Anwendungsschicht (§5) abgerufen. SHA-256 und Ed25519-Signatur werden geprüft, zudem wird sichergestellt, dass die Datei als Regeln lesbar ist, bevor sie atomar installiert wird. Eine nicht lesbare Datei wird nie installiert, und die geltenden Regeln werden nicht ersetzt. Es kommt kein neues Ziel hinzu; der Abruf läuft über denselben Manifest-Abruf. In der Server-Edition gilt
cve_kernel_map_updates_enabled: Ist es aus, findet überhaupt keine Netzwerkkommunikation statt. - Wenn ClamAV installiert ist, rufen Sie
freshclamauf. - Notieren Sie die neueste App-Version für eine Benachrichtigung (der Updater never installiert die App; unter Linux führt der Benutzer
apt upgradeaus).
Das Scheitern eines Schritts (offline, eine fehlerhafte Signatur, freshclam fehlt) wird als lastError in updates.json aufgezeichnet, und der Prozess endet immer mit exit 0, sodass ein Timer-Lauf nie eine systemd-Fehlerbenachrichtigung erzeugt. Der gesamte Mechanismus wird durch "enabled": false in updates.json oder durch systemctl disable --now roamswitch-update.timer deaktiviert; das Produkt läuft dann mit den im Paket gebündelten Daten. Der Bedrohungs-Feed wird auch im Paket ausgeliefert, sodass eine Neuinstallation sofort über einen funktionierenden Feed verfügt und apt upgrade ihn auch dann aktualisiert, wenn der Updater deaktiviert ist.
§12
- OS: Ubuntu 22.04 / 24.04 und höher, Debian 12 und höher, Linux Mint / Pop!_OS / elementary / Zorin, Fedora / RHEL-Familie, openSUSE, Arch-Familie (das AUR-Paket ist in Vorbereitung; Installation über das PKGBUILD), Raspberry Pi OS 64-bit (Bookworm), Ubuntu für Raspberry Pi
- Architecture: x86_64 / aarch64
- Erforderlich:
systemd,nftables,iproute2(ip neigh, die ARP/NDP-Sperre),conntrackundlibnotify(Desktop-Benachrichtigungen) (alles außersystemdwird automatisch von den.deb/.rpm-Abhängigkeiten eingezogen) - Optional:
clamav(Malware-Scan),nmcli(Wi-Fi-Verschlüsselungserkennung),iw(Ersatz für Funkinformationen),bluez(Bluetooth-Guard),systemd-resolved(Konfiguration des Bedrohungsschutz-DNS),lsof(Ersatz für die Erkennung lauschender Ports),nmap(Ergänzung der aktiven Schwachstellenprüfung),wireguard-tools(das WireGuard-Backend des VPN-Tunnels + Kill-Switch, §4),tailscale(sein Tailscale-Backend, §4),polkit/pkexec(Ausführen eines Upgrades, einer Deinstallation oder eines Daemon-Neustarts über die GUI) - Nicht unterstützt: Nicht-Systemd-Distributionen (Alpine / Void / Devuan)
- Display: 1280×720 oder größer (Fenster und Schriftart passen sich automatisch der Bildschirmgröße an und unterstützen kleine Raspberry Pi-Displays)
Anhang A
| Kiste | Zweck | Netzwerk |
|---|---|---|
| serde / serde_json | Serialisierung von Konfiguration und IPC | keine |
| Tokio | Async-Laufzeit (features = ["full"]; standardmäßig werden nur Unix-Sockets verwendet) | keine (standardmäßig kein TCP; Ausnahme ist die Opt-in-Sensor-Kopplung) |
| Tracing / Tracing-Abonnent | Protokollierung (lokal / journalistisch) | keine |
| dieser Fehler / jedenfalls | Fehlerbehandlung | keine |
| Regex | String-Parsing (Diagnose, CSS-Skalierung) | keine |
| URL | URL-Analyse (audit_url_safety-Heuristik) | none (wird nicht abgerufen) |
| Chrono | Datums-/Uhrzeitverarbeitung | keine |
| ed25519-dalek | Offline-Überprüfung von Lizenzsignaturen und der signierten Daten des Updaters wie Manifest und Bedrohungs-Feed (wird auch bei der Opt-in-Sensor-Kopplung verwendet) | keine |
| base64 / sha2 | Lizenz-Tokens, Canary-Hashes | keine |
| libc | chown / kill / Systemaufrufe | keine |
| idna | Dekodierung von IDN/Punycode-Hosts zur Homographenerkennung | keine |
| nfq (nur Daemon) | NFQUEUE-Bindungen für den Link Guard – reines Rust, AF_NETLINK | keine (Urteilskanal, kein Ausgang) |
| offen | ruft xdg-open auf, um Links wie „Versionshinweise öffnen“, die EULA und die Support-Seiten zu öffnen | Der Prozess selbst kommuniziert nicht |
| GTK3 / ksni (nur App) | GUI und Fach | keine |
| serde_yaml | liest /etc/roamswitch/guard.yaml (core) | keine |
| toml | analysiert Cargo.lock / poetry.lock (CVE-Scan von Sprachpaketen, core) | keine |
| md-5 | Hash für die JA3-Fingerprints des Link Guard (nicht für Authentifizierung oder Integrität, core) | keine |
| bs58 | Base58-Prüfung privater Schlüssel von Kryptowerten (Erkennung von Geheimnissen, core) | keine |
| rand | erzeugt den Geräteschlüssel des Opt-in-Sensor-Pairings (core) | keine |
| tonic / tonic-prost / prost / tower / hyper-util | gRPC zum Tetragon-Sensor; nur Unix-Domain-Socket, kein TLS (core) | keine (nur Unix-Socket) |
| flate2 | gzip-Entpackung der CVE-Map für RHEL-Pakete (nur updater; reines Rust) | keine (nur Entpacken) |
| inotify | überwacht Zugriffe auf die Honeytoken-Köder (roamswitch-honeytokens) | keine |
| aya | Loader des experimentellen XDP-Boot-Gates (roamswitch-xdp-gate, vom Daemon eingebunden) | keine (nur bpf() / netlink) |
| urlencoding / gdk / gdk-pixbuf / glib / pango | URL-Dekodierung in der GUI und die umgebenden GTK3-Crates (nur app) | keine |
| ureq + rustls (roamswitch-updater only) | die HTTPS-GETs des täglichen Updaters (Manifest, Signatur und alle geänderten Daten) | der einzige HTTP/TLS-Stack im Baum; auf die Updater-Binärdatei beschränkt |
In roamswitch-core, roamswitch-daemon, roamswitch-app, roamswitch-mcp oder roamswitchkit findet sich weder ein HTTP-Client, der ins Internet gelangen kann, noch ein TLS-Stack oder ein Telemetrie-SDK. Das Paar tonic / hyper in roamswitch-core dient nur dem gRPC mit Tetragon über einen Unix-Domänen-Socket, hat kein TLS und gelangt nie ins Netzwerk. ureq + rustls sind nur in roamswitch-updater vorhanden (scripts/audit_no_network.sh erzwingt dies in CI). Es gibt nirgendwo ein Telemetrie-SDK.
Anhang B
table inet roamswitch { # Profil-Firewall (open / balanced / lockdown)
chain input {
type filter hook input priority 0; policy <accept|drop>;
ct state established,related accept
iif "lo" accept
ip protocol icmp accept # open ist policy accept ohne Regeln; balanced / lockdown sind policy drop (ICMP / ICMPv6 sind nur in balanced erlaubt)
}
chain output {
type filter hook output priority 0; policy accept;
}
}
table inet roamswitch { # Bei Air-Gap (Isolation) wird dieselbe Tabelle neu aufgebaut: input und output mit policy drop, nur lo ist erlaubt (auch bestehende Verbindungen werden nicht durchgelassen)
chain input { type filter hook input priority -100; policy drop; iif "lo" accept }
chain output { type filter hook output priority -100; policy drop; oif "lo" accept }
}
table inet roamswitch_linkguard { # §4.5 — unabhängig von der Profiltabelle
chain output {
type filter hook output priority 0; policy accept;
udp dport 443 reject with icmpx type port-unreachable # nur wenn block_quic aktiviert ist (standardmäßig aus)
meta l4proto udp udp dport 53 queue num 92 bypass
meta l4proto tcp tcp dport 53 queue num 92 bypass
meta l4proto tcp tcp dport { 80, 443 } ct state new,established ct original packets 1-14 queue num 92 bypass # nur die ersten 14 Pakete jeder Verbindung werden zur Prüfung in die Queue gestellt
}
}
table inet roamswitch_dev_guard { # §4 Port-Anomalie-Wächter / manuelle Port-Isolierung, separate Tabelle
chain input {
type filter hook input priority -10; policy accept;
iif != "lo" tcp dport { … } drop
}
}
table inet roamswitch_portscan { # Erkennung und Blockierung von Portscans (standardmäßig an)
chain block { type filter hook input priority -200; policy accept; ip saddr @blocked_ips ct state new log … drop }
chain detect { type filter hook input priority -100; policy accept; iifname != "lo" ct state new tcp flags syn log … }
}
table inet roamswitch_egress_block { # Blockliste für ausgehenden Verkehr zu bösartigen IPs (standardmäßig an)
chain output { type filter hook output priority -150; policy accept; ip daddr { … } log … drop }
chain forward { type filter hook forward priority -150; policy accept; ip daddr { … } log … drop }
}
table inet roamswitch_docker_guard { # Gegenmaßnahme gegen die Umgehung der Firewall durch veröffentlichte Docker-Ports (nur mit dem nativen nftables-Backend von Docker)
chain forward { type filter hook forward priority -10; policy accept; … iifname { … } drop }
}
table inet roamswitch_isolate { # prozessgenaue Eindämmung nach einer eBPF-Erkennung (per cgroup / UID)
chain process_block { type filter hook output priority -100; policy accept; … drop }
}
table inet roamswitch_vpn { # §4 Kill-Switch für das WireGuard-Backend
chain output {
type filter hook output priority -150; policy drop;
oifname "lo" accept
oifname "roamswitch" accept
meta l4proto { icmp, ipv6-icmp } accept
udp sport 68 udp dport 67 accept # DHCP
ip daddr { <endpoint v4> } udp dport <port> accept
ip6 daddr { <endpoint v6> } udp dport <port> accept
ct state established,related accept
}
chain input { type filter hook input priority -150; policy drop; … } # symmetrisch
}
table inet roamswitch_ts { # §4 Kill-Switch für das Tailscale-Backend (weniger streng)
chain output {
type filter hook output priority -150; policy drop;
oifname "lo" accept
oifname "tailscale0" accept
meta l4proto { icmp, ipv6-icmp } accept
udp sport 68 udp dport 67 accept # DHCP (v6-Seite ist ebenfalls symmetrisch)
ip daddr 100.64.0.0/10 accept # tailnet CGNAT
ip6 daddr fd7a:115c:a1e0::/48 accept
ip daddr 100.100.100.100 udp dport 53 accept # MagicDNS
ip daddr 100.100.100.100 tcp dport 53 accept
udp dport 3478 accept # STUN
udp dport 41641 accept # Direkte WireGuard-Verbindung
tcp dport 443 accept # DERP-Fallback
ct state established,related accept
}
chain input { type filter hook input priority -150; policy drop; … } # symmetrisch
}
Das ARP/NDP-Pinning des Gateways/IPv6-Routers/DNS-Resolvers (§4) erfolgt in der Kernel-Nachbartabelle (ip neigh replace … nud permanent), nicht in nftables. Angepinnte Einträge werden in /var/lib/roamswitch/arp_lock.json aufgezeichnet.
Anhang C
Jeder Anspruch in diesem Dokument kann auf Ihrem eigenen Computer überprüft werden. Die folgenden Befehle werden auf einem Host ausgeführt, auf dem das Paket roamswitch installiert ist.
C.1 Überprüfung des ausgehenden Datenverkehrs
Die Daemon-/App-/MCP-Binärdateien verknüpfen keine HTTP-/TLS-Bibliothek:
for b in roamswitch-daemon roamswitch-app roamswitch-mcp; do
ldd "$(command -v $b)" | grep -iE 'ssl|crypto|nghttp|curl' && echo " ^ in $b"
done
# → Keine Ausgabe. Der HTTP/TLS-Stack ist nur statisch in roamswitch-updater eingebunden.
Der laufende Daemon enthält keinen Internet-Socket:
sudo lsof -p "$(pgrep -x roamswitch-daem)" -a -i
# → Keine Ausgabe = null TCP/UDP-Internetverbindungen
sudo lsof -p "$(pgrep -x roamswitch-daem)" -a -U | grep roamswitch
# → Nur /run/roamswitch/roamswitch.sock und events.sock (empfängt eBPF-Erkennungsereignisse) (der Link Guard fügt einen AF_NETLINK-Socket hinzu,
# aber das ist ein Kernel-Kanal, kein Internet-Socket)
Der einzige RoamSwitch-zuordenbare ausgehende Datenverkehr ist der tägliche Updater:
watch -n 5 'sudo ss -tupn | grep -E "roamswitch-(daem|app|mcp)" || echo "(none)"'
# → Immer "(none)". Keiner dieser drei öffnet jemals einen Internet-Socket.
systemctl list-timers roamswitch-update.timer
sudo systemctl start roamswitch-update.service
journalctl -u roamswitch-update.service -n 20 --no-pager
# → Nur HTTPS-GETs an lafine.net/updates/v1 (Manifest, Signatur und geänderte Daten), danach wird beendet. Ist ClamAV installiert, verbindet sich freshclam zusätzlich mit den ClamAV-Spiegelservern.
Deaktivieren Sie es und bestätigen Sie die völlige Stille:
sudo systemctl disable --now roamswitch-update.timer
# oder /var/lib/roamswitch/updates.json auf "enabled": false setzen
sudo strace -f -e trace=network -p "$(pgrep -x roamswitch-daem)" 2>&1 | grep -i 'connect('
# → Verbindet sich nur mit AF_UNIX / AF_NETLINK. AF_INET / AF_INET6 tauchen nie auf.
C.2 Reproduzierbare Verteidigungsüberprüfung (Docker Test Suite)
Die meisten Abwehrmechanismen von RoamSwitch (Air-Gap-Durchsetzung, Selbstheilung nach Firewall-Übergriffen, /tmp Noexec, Yama LSM, Homograph-Phishing-Erkennung und weitere) lassen sich mit der Docker-Testsuite im öffentlichen Support-Repository (roamswitch-support) auf dem eigenen Rechner reproduzieren. Die Suite berührt nur ihren eigenen Netzwerk-Namespace und Dateien im Container, sodass Host-Netzwerk und Host-Dateien nicht beeinträchtigt werden. Sie läuft allerdings mit --privileged; daher werden kernelweite Einstellungen, die der Container mit dem Host teilt (etwa ptrace_scope von Yama und suid_dumpable), auch auf dem Host geändert, und das Entfernen des Containers macht sie nicht rückgängig. Führen Sie sie in einer Wegwerfumgebung aus.
# Testsuite abrufen und reproduzieren (automatisierte Verifikation in einem isolierten Container mit dem offiziellen Distributionspaket)
git clone https://github.com/lafine1211/roamswitch-support.git
cd roamswitch-support/test/docker
docker build -t roamswitch-test .
docker run --rm --privileged roamswitch-test
Der Testcontainer ruft automatisch das offizielle Distributionspaket aus dem APT-Repository (lafine.net/apt) ab und führt die Prüfungen in einem isolierten Netzwerk- und Mount-Namespace aus und wertet sie aus. Die öffentliche Suite besteht aus pentest.sh (die sieben Szenarien PENT-1 bis 7) und selftest.sh (destruktive Selbsttests des Daemons für Air-Gap, Selbstheilung, Canaries, Burst-Erkennung und den Quarantäne-Vault). Die IDs in den folgenden Tabellen sind laufende Nummern aus den Prüfprotokollen und entsprechen nicht eins zu eins den Prüfungen in den Skripten. BadUSB (SP-6), die Modi des Link Guard (SP-7-Familie), ARP-Fixierung und VPN-Kill-Switches (SP-8 bis 10), die einzelnen Prüfungen der Kernel-Härtung (SP-11-Familie) sowie PENT-8 und 9 gehören nicht zur öffentlichen Suite; sie wurden auf anderem Weg bestätigt (echter Host, getrennte Netzwerk-Namespaces, manuell eingespeiste Ereignisse).
(1) Autonome Netzwerkverteidigung und Luftspalt-Selbstheilung
| Ausweis | Szenario | Verifizierungsmethode | Bestehenskriterium |
|---|---|---|---|
| SP-3 | Air-Gap-Aktivierung → Austrittsabfall | Senden Sie enable_air_gap IPC | policy drop wird auf den Ausgabe-Hook angewendet; Der gesamte ausgehende Datenverkehr wurde blockiert |
| SP-3b | Erzwungene Bereinigung und Selbstheilung der Firewall | Löschregeln über nft delete table inet roamswitch | Die Anti-Clobber-Selbstheilung stellt die Drop-Regeln innerhalb von 5 Sekunden wieder her |
| SP-3c | Beim Daemon-Neustart fehlgeschlagen | Den Daemon mitten im Air-Gap beenden (selftest.sh verwendet kill, also SIGTERM) und neu starten | Die Egress-Drop-Richtlinie bleibt auch nach dem Neustart nahtlos bestehen |
| SP-3d | Autorisierte Air-Gap-Wiederherstellung | Autorisierten disable_air_gap IPC senden | Drop-Richtlinie aufgehoben, alle Markierungsdateien entfernt, Austritt wiederhergestellt |
| SP-8 | Präventives ARP/NDP-Pinning | In isolierter NetNS-Gateway-Umgebung aktivieren → gefälschtes Gratis-ARP senden | Gateway-Nachbareintrag bleibt PERMANENT; gefälschtes ARP ignoriert |
| SP-9 | VPN-Kill-Switch (WireGuard) | Live WireGuard-Server in separaten Netzen, Import .conf → vpn_up | Handshake wird bis inet roamswitch_vpn abgeschlossen; Null Lecks beim Tunneltod |
| SP-10 | VPN-Kill-Switch (Tailscale) | Stub tailscale CLI + separate Netze, tailscale0 IF | Off-Tunnel-Klartext-TCP/80 und lokales DNS blockiert; DERP und MagicDNS erlaubt |
(2) Kernel- und Mount-Hardening
| Ausweis | Szenario | Verifizierungsmethode | Bestehenskriterium |
|---|---|---|---|
| SP-11a | Härtung des Netzwerksystems | Führen Sie apply_kernel_sysctl_hardening IPC aus | rp_filter=1, tcp_syncookies=1, accept_redirects=0 erreichen Zielwerte |
| SP-11b | Speicherschutz und Yama LSM | Überprüfen Sie ptrace_scope und suid_dumpable | kernel.yama.ptrace_scope=1 (blockiert Snooping), fs.suid_dumpable=0 (kein Core-Dump) |
| SP-11c | /tmp & /dev/shm noexec-Verteidigung | Führen Sie apply_mount_hardening IPC aus | /tmp und /dev/shm erneut gemountet noexec,nosuid,nodev; Hinrichtung verweigert |
| SP-11d | Legitime Benutzerausführung bleibt erhalten | Skripte im Standard-Home-Verzeichnis (~/) ausführen | Läuft ungehindert, ohne legitime Entwickler-/Administrator-Workflows zu unterbrechen |
(3) Mehrschichtige Malware- und Ransomware-Abwehr und Canaries
| Ausweis | Szenario | Verifizierungsmethode | Bestehenskriterium |
|---|---|---|---|
| SP-1 | Canary-Manipulationserkennung | Decoy-Canary-Datei (.xlsx) in ~/Documents/ abschneiden oder umbenennen | Manipulationen werden innerhalb von Sekunden erkannt und lösen einen sofortigen Air-Gap aus |
| SP-2 | Ransomware-Massenverschlüsselungs-Burst-Erkennung | Ein einzelner Prozess generiert schnell mehrere Dateien mit hoher Entropie | Beleidigender Arbeitsprozess mit SIGSTOP eingefroren; Luftspalt ausgelöst |
| SP-2b | Kein falsch positives Ergebnis am shred | Führen Sie shred -n 3 -u über Testdateien hinweg aus | Die Übereinstimmung mit der Zulassungsliste verhindert die Erkennung falsch positiver Ergebnisse oder das Einfrieren |
| SP-2c | Kritische Prozesse sind nie eingefroren | Validieren Sie die Logik des Einfrierens des Ziels während der Burst-Erkennung | Kritische Daemons (dockerd, systemd, containerd) werden nie eingefroren |
| SP-4 | Die EICAR-Testzeichenfolge dient nur der Benachrichtigung | Schreiben Sie die EICAR-Testzeichenfolge in ~/Downloads/ | Keine Benachrichtigung, nur ein Eintrag im Benachrichtigungsverlauf; die Datei wird niemals automatisch unter Quarantäne gestellt |
| SP-4b | Echte Malware-Signatur zuerst bestätigen | Schreiben Sie eine echte Signatur außerhalb überwachter Ordner | Ruft den modalen Genehmigungsdialog auf; Quarantäne erfolgt nur nach Bestätigung durch den Benutzer |
| SP-4c | Härtung der Quarantäne-Vault-Berechtigungen | Überprüfen Sie die Berechtigungen des Tresorverzeichnisses und der Beispieldateien | Vault-Verzeichnis auf 0700 festgelegt, unter Quarantäne gestellte Proben auf 0400 festgelegt |
| SP-4d | Privilegierte IPC-sichere Wiederherstellung der Originaldatei | Senden Sie restore_quarantine_file IPC | Datei mit Benutzerberechtigungen (0644) im ursprünglichen Pfad wiederhergestellt und zu Ausschlüssen hinzugefügt |
(4) Passiver Link Guard und Phishing-Abwehr
| Ausweis | Szenario | Verifizierungsmethode | Bestehenskriterium |
|---|---|---|---|
| SP-7 | mode = block harte Durchsetzung | Stellen Sie eine Verbindung zu in der Feedliste aufgeführten oder blocklistExtra-Hosts her | Auf der TLS-Ebene abgelegt (SNI-Analyse); Nicht gelistete sichere Hosts erreichen HTTP 200 |
| SP-7b | mode = warn Fail-Closed Hold | Ohne Benutzerreaktion eine Verbindung zum Warnhost herstellen (Zeitüberschreitung 8 Sekunden) | Verwirft Pakete bei Zeitüberschreitung (fail-closed); nur mit ausdrücklicher Genehmigung gestattet |
| SP-7c | mode = off Kompletter Abriss | Linkschutz deaktivieren | Die Tabelle inet roamswitch_linkguard ist vollständig deinstalliert |
(5) BadUSB-Mitigation und Gerätekontrolle
| Ausweis | Szenario | Verifizierungsmethode | Bestehenskriterium |
|---|---|---|---|
| SP-6 | Bestandsschutz für verbundene Tastaturen | Überprüfen Sie die angeschlossenen Tastaturen beim Start des Daemons | Bestandsschutz für bestehende Geräte; nur nachfolgende Hot-Plugs griffen |
(6) Selbsttest-Punkte, die Angriffe nachbilden (PENT-1 bis 7 in der öffentlichen Docker-Suite, PENT-8 und 9 aus gesonderten manuellen Prüfungen)
| Ausweis | Angriffsvektor | Simulationsdetails | Verteidigungs-/Erkennungskriterien |
|---|---|---|---|
| PENT-1 | C2-Exfiltration | Ausgehender HTTP/TCP-Traffic zu C2 unter Air-Gap versucht | Alle Pakete wurden bei Netfilter verworfen; Null Leckage |
| PENT-1b | FW-Löschung erzwingen | Löschregeln mit nft delete table inet roamswitch | Die Anti-Clobber-Selbstheilung stellt die Regeln innerhalb von Sekunden wieder her |
| PENT-1c | Luftspaltsichere Wiederherstellung | Problem mit authentifiziertem disable_air_gap IPC | Drop-Regeln entfernt; Markierungen gelöscht; Konnektivität wiederhergestellt |
| PENT-2 | /tmp Hintertür | Abgelegtes Backdoor-Skript in /tmp ausführen | Verweigert durch noexec Mount-Schutz (Permission denied) |
| PENT-2b | /dev/shm Gemeinsamer Speicher | Binäre Nutzlast ausführen, die in /dev/shm platziert ist | Blockiert durch noexec Reittierverteidigung |
| PENT-2c | Erhaltung des Benutzerbereichs | Skript im legitimen Benutzerverzeichnis (/home/tester/) ausführen | Ungehinderte Ausführung; Keine Unterbrechung des Arbeitsablaufs |
| PENT-3 | ptrace Memory Snooping | PTRACE_ATTACH als Ziel zum Extrahieren von Geheimnissen/Tokens | Abgelehnt von Yama LSM kernel.yama.ptrace_scope=1 |
| PENT-3b | Core Dump Secret Scraping | Lösen Sie einen Prozessabsturz aus, um einen Speicherauszug zu erhalten | Verhindert durch fs.suid_dumpable=0 |
| PENT-4 | Kanarische Manipulation | Zero-out-Kanarienvogel-Köderdatei in ~/Documents/ | Echtzeiterkennung von Größenanomalien und Hash-Änderungen |
| PENT-4b | Kanarisches Massenwischen | Massenlöschung von Canary-Decoy-Dateien | Das Verschwinden der Datei wurde sofort erkannt, was zu einem Vorfall führte |
| PENT-5 | Spoofing von IP-Adressen | Übertragen Sie Pakete mit gefälschter Quell-IP | Von rp_filter=1 gelöscht (Reverse-Path-Filter) |
| PENT-5b | SYN Flood DoS | Überfluten Sie halboffene TCP-Verbindungen | Statustabelle geschützt durch tcp_syncookies=1 |
| PENT-5c | ICMP-Route-Hijack | Fügen Sie gefälschte ICMP-Redirect-Pakete ein | Ignoriert wegen accept_redirects=0 |
| PENT-6 | Kyrillisches Homograph-Phishing | Navigieren Sie zu gооgle.com (kyrillischer Homograph) | Identifiziert durch LinkGuard, bewertet mit 40 (GEFÄHRLICH/Block) |
| PENT-6b | Roher IP- und Klartextverkehr | Direkte ausgehende Verbindung zur Raw-IP | Präzise als Sicherheitsrisikofaktor gekennzeichnet |
| PENT-7 | OpenAI-API-Schlüsselleck | Machen Sie das sk-proj-...-Token im Code oder in Protokollen verfügbar | Durch Shannon-Entropieanalyse erkannt und maskiert |
| PENT-7b | GitHub-Token-Leak | Offenlegen des persönlichen Tokens ghp_... im Code | Übereinstimmung durch Tokenmuster und Entropieüberprüfung |
| PENT-8 | Kernel-LPE (Frag Gap)-Preemption | Unprivilegierter unshare -U -r (CVE-2026-53362-Versuch) | Bei der Messung mit v1.1.0 sofort abgelehnt von user.max_user_namespaces = 0 (Operation not permitted). Die aktuelle Client Edition verweigert User-Namespaces standardmäßig nicht (auto_enable_userns_restriction in guard.yaml ist standardmäßig deaktiviert; die Server Edition wendet es immer an) |
| PENT-9 | eBPF-Bedrohungssensor und Prozess-Freeze | Kritischer/Notfallalarm, der über den Falco-eBPF-Socket eingespeist wird | Prozess über SIGSTOP innerhalb von Millisekunden eingefroren (Status: Ts); Air-Gap eingesetzt |
Art der Prüfungen – Von den Punkten in der obigen Tabelle bestätigen PENT-2/2b (noexec), PENT-3/3b (Yama, Core-Dumps) und PENT-5/5b/5c (rp_filter, SYN-Cookies, ICMP-Redirects), dass eine von RoamSwitch konfigurierte Standardfunktion von Kernel oder mount wirksam ist. PENT-8 (User-Namespaces verbieten) ist von derselben Art, stammt aber aus einem Protokoll von v1.1.0, und die aktuelle Client Edition wendet es standardmäßig nicht an. Die Punkte, die die eigene Erkennungs- und Eindämmungslogik von RoamSwitch angreifen, sind PENT-1/1b/1c (Air-Gap und Selbstheilung), PENT-4/4b (Canaries), PENT-6/6b (Link Guard), PENT-7/7b (Erkennung von Geheimnissen) und PENT-9 (Einfrieren und Eindämmen nach einer eBPF-Erkennung). PENT-2c bestätigt, dass die normale Arbeit nicht beeinträchtigt wird.
(7) Zusammenfassung des Selbsttests (Standalone Hardened vs. eBPF Enhanced)
Zusammenfassung der Ergebnisse des vollständigen, Angriffe nachstellenden Selbsttests, der in einer isolierten Docker-Umgebung durchgeführt wurde (Ziel: Ubuntu 24.04 mit RoamSwitch Client Edition; Angreifer: Nmap / curl / hping3 u. a.). Die Tabelle unten zeigt eine Messung von Client v1.1.0 vom 2026-09-06; am 2026-09-25 bestand ein korrigierter Build, der aus dem 1.10er-Quellcode gebaut wurde (kein öffentliches Release), 11 von 11 Punkten der Client-Suite (siehe audit/RESULTS-PENTEST-2026-09-25.ja.md im öffentlichen Repository).
| Verifizierungskategorie | Ohne Falco (Standalone Hardened) | Mit Falco (eBPF Enhanced) | Urteil der Verteidigung |
|---|---|---|---|
| Externer Port-Scan-Widerstand (Nmap SYN) | PASS (100 % gefiltert / DROP in Lockdown) | PASS (100 % gefiltert / DROP in Lockdown) | Total External Stealth |
| External Direct Access Cutoff (TCP/80, 3306) | PASS (Timeout-Abbruch / keine Antwort) | PASS (Timeout-Abbruch / keine Antwort) | Null eingehende Exposition |
| Kernel-LPE (Frag Gap)-Abschwächung | PASS (Messung mit v1.1.0; unshare wird dort blockiert, wo user.max_user_namespaces = 0 gesetzt ist. In der aktuellen Client Edition standardmäßig aus) | PASS (eBPF-Alarm + SIGSTOP Einfrieren + Luftspalt) | Defense-in-Depth bestätigt |
| Unautorisierte Porterkennung (Anomalie) | PASS (0.0.0.0 Bindung mit HOHEM Risiko gekennzeichnet) | PASS (0.0.0.0 Bindung mit HOHEM Risiko gekennzeichnet) | 100 % erkannt und geführt |
| Protokollaufblähung und CPU-Overhead-Verhinderung | Kein Protokoll-Footprint (deinstalliert) | PASS (95 % Rauschunterdrückung / 2 MB Puffer / 50 MB Obergrenze) | Desktop-optimiert |
C.3 Bekannte Einschränkungen
| Einschränkung | Auswirkungen | Schadensbegrenzung |
|---|---|---|
Auf einigen Kerneln liefert FAN_MARK_MOUNT auf tmpfs (/tmp) keine Ereignisse | Dateischreibvorgänge unter /tmp werden von fanotify nicht überwacht | /tmp ist kurzlebig und kein überwachter Benutzerordner; Ransomware zielt auf ~/. Markierungsfehler werden explizit protokolliert |
| Keine Fanotify-Zustellung für Container-Overlays/TMPFs | Die Erkennung von Entropieausbrüchen im Container kann nicht validiert werden | validiert auf echter Hardware (ext4); Der Kabelbaum überspringt automatisch über eine Sonde |
Die nftables-Operationen von RoamSwitch teilen sich den Netfilter-Speicherplatz mit Dockers iptables-nft | RoamSwitch-Regeloperationen können die NAT-Regeln von Docker beeinträchtigen | als betrieblicher Vorbehalt dokumentiert; isoliert in dedizierten Tabellen (inet roamswitch und die übrigen roamswitch_*-Tabellen), aber Operationen für den gesamten Regelsatz wie nft flush ruleset sollten vermieden werden |
| Der Link Guard sieht den DoH eines Browsers nur über TLS SNI; Auch das verbirgt Encrypted Client Hello (ECH). | Sobald ECH weit verbreitet ist, ist eine ECH-verwendende Verbindung zu einer ECH-unterstützenden Site nicht anhand des Hostnamens identifizierbar | Die lokale Blockliste und die Heuristik wirken weiterhin auf DNS/HTTP und Nicht-ECH-TLS. Der DNS-Bedrohungsschutz (§4.5, standardmäßig an) deckt den Resolver-Pfad ab |
Die Aktualität des Feeds hängt vom Veröffentlichungsrhythmus ab, wenn enabled in updates.json auf false steht | Bei deaktivierten Aktualisierungen ist der Feed nur so aktuell wie der letzte apt upgrade | die Entdeckungen mit dem höchsten Schweregrad (Markenhomograph) benötigen keine Zuführung; Melden Sie sich erneut an oder aktivieren Sie das DNS zum Schutz vor Bedrohungen, um eine stets aktuelle Abdeckung zu gewährleisten |