Lafine Systems Design · Technische Dokumentation

RoamSwitch Server Edition Architektur-/Sicherheits-Whitepaper

Eine headless arbeitende, autonome Suite für Netzwerksicherheit & Integritätsschutz für Cloud- und On-Premises-Linux-Infrastrukturen. Sie verzichtet auf werbliche Formulierungen; die Angaben lassen sich am tatsächlichen Verhalten des offiziell verteilten Pakets und am Selbsttest in §6 überprüfen.

Version v1.11.1 Geltungsbereich RoamSwitch Server Edition 1.11.1 (DNS-Tunneling-Erkennung, Honeytokens, forensische Beweissicherung, NIST-CSF-/CIS-Controls-Zuordnung, Aktualisierung der signierten Kernel-CVE-Map) Voraussetzungen systemd + nftables Veröffentlicht 2026-10-08

§1Überblick und Grundprinzipien

RoamSwitch Server Edition ist eine Headless-, residente, autonome Netzwerksicherheits- und Integritätsschutz-Suite, die speziell für Linux-Serverinfrastrukturen bei Cloud-Anbietern (AWS, GCP, Azure, Bare-Metal-VPS) und lokalen Rechenzentren entwickelt wurde.

Im Gegensatz zu Client-Workstation-Editionen, die sich auf Mobilität und Wi-Fi-Perimeteranpassung konzentrieren, basiert die Server Edition auf fünf kompromisslosen Grundsätzen: Inbound Default Drop, Critical Path File Integrity Monitoring (FIM), Preemptive Kernel LPE & Privilege Escalation Hardening, eBPF Runtime Threat Telemetry und Autonome Air-Gap-Host-Isolierung mit Notfallwarnungen vor der Trennung.

Das Zero Telemetry-Prinzip – keine Bibliothek für externe Kommunikation im Daemon selbst – wird auf Codeebene durchgesetzt (standardmäßig verlässt nur der Empfang signierter Daten (die Kernel-CVE-Daten, die Web-Regeln und, auf Ubuntu-Servern, die Ubuntu-Paket-CVE-Daten für den CVE-Abgleich der OS-Pakete; Manifest täglich geprüft, die CVE-Daten selbst etwa alle 30 Tage) den Host, der sich auch abschalten lässt, und jede andere Ausnahme ist etwas, das der Betreiber ausdrücklich aktiviert; siehe die Kernprinzipien in §1), und Geheimnisse (Bot-Token und Konfiguration) werden mit den Berechtigungen 0600 geschützt.

1.1 Vergleich: Client Edition vs. Server Edition

Dimension Client-Edition (Desktop/Mobil) Server Edition (Headless/Infrastruktur)
Bereitstellung Laptops, mobile Entwickler-Workstations Cloud-VMs, Bare-Metal-Knoten, Container-Hosts
Netzwerkverhalten Dynamischer Profilwechsel basierend auf WLAN-SSID/Gateway-MAC Statischer eingehender Standard-Drop. Es werden nur explizit zugelassene Ports angezeigt
Benutzeroberfläche GTK3 Desktop GUI + Tray-Anzeige Pure Headless CUI. CLI-Befehle + interaktiver Einrichtungsassistent + eine Terminal-UI (roamswitch-server-tui)
Vorfallbenachrichtigungen Desktop-Benachrichtigungen (libnotify) Direkter Push an Telegram Bot, LINE Messaging API und Webhooks (Slack/Discord)
Primäre Verteidigung ARP-Spoofing im öffentlichen WLAN, BadUSB, Ransomware-Dokumentenverschlüsselung Externer Aufklärungsabwurf, FIM-Manipulationserkennung, Container-Escapes, Kernel-LPE (CVE-2026-53362)

1.2 Grundlegende Architekturprinzipien

  • Zero Telemetry: Standardmäßig wird nichts über Benutzer oder Umgebung nach außen gesendet. Der Daemon selbst enthält keine HTTP-/TLS-Kommunikationsbibliothek; nur für vom Betreiber konfigurierte Benachrichtigungen und Weiterleitungen startet er das System-curl (Telegram / LINE / Webhook; Geheimnisse wie Token und URLs werden in einer Konfiguration über die Standardeingabe übergeben, nie in der Kommandozeile) und openssl (TLS-Syslog-Weiterleitung) als Subprozesse. Die einzige standardmäßig aktive externe Kommunikation ist, abgesehen von Paketmanager-Updates, die folgende. (1) Solange cve_kernel_map_updates_enabled (Standard true) eingeschaltet ist, empfängt roamswitch-updater anonym von lafine.net signierte Daten. Empfangen werden die Kernel-CVE-Daten für die Container-Isolationsprüfung, die Erkennungsregeln der Webanwendungsebene (Web-Regeln) und, auf Ubuntu-Servern, die Ubuntu-Paket-CVE-Daten für den CVE-Abgleich der OS-Pakete. Das signierte Manifest und seine Signatur werden jeden Tag geprüft (zwei GETs); die Kernel-CVE-Daten und die Ubuntu-Paket-CVE-Daten werden nur geholt, wenn seit der letzten Aktualisierung etwa 30 Tage vergangen sind (ein Server ohne Ubuntu-Daten holt sie bei der nächsten täglichen Prüfung), die Web-Regeln nur, wenn das Manifest eine neuere Version hat. Es ist ein einfacher HTTPS-GET ohne Query-String und Cookies, dessen einziger Header, der die Software nennt, ein fester User-Agent: RoamSwitch-Updater ist; nur Daten mit gültiger Ed25519-Signatur werden übernommen, und nichts über diesen Host wird gesendet. Der Betreiber kann sie mit roamswitch server config set cve_kernel_map_updates_enabled false, dem Einrichtungsassistenten oder der Server-TUI abschalten; ein ausdrückliches false in einer bestehenden server.conf bleibt unverändert, und die Prüfung läuft auch abgeschaltet mit der eingebetteten Baseline weiter; der CVE-Abgleich der OS-Pakete auf einem Ubuntu-Server meldet dann jedoch „keine lokalen CVE-Daten“ und liefert kein Ergebnis. Jede andere Ausnahme wird vom Betreiber ausdrücklich aktiviert. (2) Die Ereignisweiterleitung (forward_enabled, Standard false) sendet nur an die vom Betreiber konfigurierten Ziele: Syslog / JSON-Lines-Datei / signierter Webhook. (3) Nur wenn npm_audit_signatures_enabled (Standard false) aktiviert ist und der Betreiber roamswitch audit-npm-signatures <DIR> --confirm ausführt, kontaktiert npm selbst registry.npmjs.org. (4) Nur wenn sensor_pairing_enabled (Standard false) aktiviert ist, verbindet es sich, und zwar mit der vom Betreiber eingegebenen Sensor-Adresse (der Sensor ist ein eigenes Produkt und nicht von Zero Telemetry abgedeckt). (5) Fleet (Business-Stufe) ist ausschließlich geräteseitiger Code: Ein nicht registriertes Gerät sendet nichts und löst keinen Namen auf; der Verwaltungsdienst ist weder bereitgestellt noch veröffentlicht, und es gibt entwurfsgemäß keinen Fernbefehlsweg. (6) Die LLM-Anbindung des mitgelieferten separaten Werkzeugs accessscope (Sicherheitsdiagnose von Zugriffsprotokollen) ist standardmäßig aus. Nur wenn sie aktiviert ist (in der Befehlszeile: wenn --llm angegeben wird), können eine Zusammenfassung der Diagnose, Belegzeilen und Informationen zur Umgebung (bei der Funktion zum Finden von Protokollen) über den vom Betreiber gewählten LLM-Befehl an einen externen Dienst gesendet werden. Der Daemon (roamswitch-server) ist an dieser Kommunikation nicht beteiligt, AccessScope kann seine LLM-Analyse auch als root ausführen (das LLM läuft dann mit Root-Rechten; ein unprivilegierter Benutzer wird empfohlen), und sie liegt außerhalb von Zero Telemetry. Das mitgelieferte separate Werkzeug personalsoc (prüft Protokolle und Schutzstatus) verhält sich genauso: Nur wenn --llm angegeben wird, kann eine Zusammenfassung der Diagnose über den vom Betreiber gewählten LLM-Befehl an einen externen Dienst gesendet werden (außerhalb von Zero Telemetry). Der Befehl pathscope ruft kein LLM auf. (7) Nur wenn clamav_enabled (Standard false) aktiviert ist, führt der Daemon freshclam aus, um ClamAV-Signaturen zu empfangen (einmal, wenn noch keine Signaturdatenbank existiert, und, solange clamav_scan_dirs gesetzt ist, alle clamav_freshclam_interval_secs, Standard 7200 Sekunden).
  • Inbound Default Drop: Neue eingehende TCP-Verbindungen zu anderen als den freigegebenen Ports werden mit nftables verworfen, ohne dass ein RST zurückgesendet wird. Ein Portscan sieht nur die freigegebenen Ports (Loopback, bestehende Verbindungen sowie ICMP und ICMPv6 werden durchgelassen).
  • Fail-Closed Autonomous Containment: Die Regeln für Default Drop und Isolation liegen im Kernel und bleiben daher auch bestehen, wenn der Daemon stoppt oder neu startet (Restart=always). Der Schutz veröffentlichter Docker-Ports wird alle 60 Sekunden, die Egress-Blockliste und die Portscan-Sperre alle 300 Sekunden erneut geprüft, und verschwundene Regeln werden wieder eingerichtet. Die Isolationsregeln im Zustand DEGRADED werden im 15-Sekunden-Takt der Auswertung geprüft und bei Fehlen wieder eingerichtet. Wird der Default-Drop-Regelsatz selbst von außen gelöscht, wird er nicht automatisch erneut angewendet; die Diagnose „Inbound default deny“ in roamswitch server status meldet dies.
  • Schutz durch Berechtigungen 0600: Die Konfigurationsdatei /etc/roamswitch/server.conf wird beim Erstellen und Aktualisieren automatisch auf die Berechtigungen 0600 gesetzt. Geheimnisse wie Token und Webhook-URLs werden auch an curl in einer Konfiguration über die Standardeingabe übergeben und nie in die Kommandozeile geschrieben (die andere Benutzer über /proc/<pid>/cmdline sehen können).

§2Bedrohungslandschaft und Gegnermodell

Moderne, mit dem Internet verbundene Server sind mit gnadenlosen automatisierten Scans, Container-Breakout-Vektoren und Zero-Day-Kernel-Berechtigungseskalationen konfrontiert.

Die wichtigsten Bedrohungsvektoren werden angegangen
  1. __
  2. __
  3. __
  4. Container-Socket-Breakout: Falsch konfigurierte Container mit gemounteten /var/run/docker.sock- oder --privileged-Flags führen Root-Aktionen auf dem Host-Betriebssystem aus.
  5. Prozessspeicher-Snooping: Angreifer hängen ptrace an oder lesen /proc/$pid/mem über Prozesse hinweg, um private Schlüssel oder Anmeldeinformationen zu extrahieren.

§3Systemarchitektur

RoamSwitch Server Edition arbeitet als native Rust-Binärdateien, die für minimalen Speicher und keinen CPU-Overhead ausgelegt sind.

┌─────────────────────────────────────────────────────────────┐
│  Benutzer- & Administratorbereich                       │
│                                                             │
│   roamswitch (CLI)             roamswitch-mcp (AI Agent)    │
│   · server status (34 Punkte)   · Sicherheitsaudit-Tools    │
│   · server config / setup      · stdio JSON-RPC             │
│   · fim verify / update                                     │
│        │                               │                    │
└───────┼───────────────────────────────────┼─────────────────┘
         │ (CLI-Befehle & Konfigurationsübernahme) │ (stdio)
┌───────▼───────────────────────────────────▼─────────────────┐
│  Systemfundament (systemd + Root-Rechte)                    │
│                                                             │
│   roamswitch-server-daemon                                  │
│   ├── CriticalPathFim (SHA-256-Hintergrundprüfung)          │
│   ├── eBPF/Falco-Integrationsmodul                          │
│   ├── Notifier (sofortige Telegram-/LINE-/Webhook-Alarme)   │
│   └── Air-Gap Controller (setzt nftables-Notfallregeln)     │
│                                                             │
│   Konfiguration: /etc/roamswitch/server.conf (Rechte 0600)  │
│   Integritäts-DB: /var/lib/roamswitch/fim.db                │
└─────────────────────────────────────────────────────────────┘

§4Kernverteidigungsmechanismen

4.1 Grenzsicherheit (Inbound Default Drop)

nftables wendet policy drop auf die input-Chain der Tabelle inet roamswitch_server an. Erlaubt sind nur neue eingehende TCP-Verbindungen zu den vom Administrator festgelegten Ports (ssh_ports, allowed_ports); Verbindungen zu nicht freigegebenen Ports laufen in ein Timeout (werden verworfen). Loopback, bestehende Verbindungen sowie ICMP und ICMPv6 sind erlaubt.

Selbst wenn ein Air-Gap (Notfall-Isolation) ausgelöst wird, bleiben die Admin-Pfade – die Wartungs-SSH-Ports (ssh_ports) und die registrierten Wartungs-Quell-IPs (whitelist_ips), neue wie bestehende Verbindungen – im Regelwerk erhalten; das verhindert, dass eine Wiederherstellung aus der Ferne unmöglich wird (preserve_ssh_on_isolation, Standard true). Jede andere bestehende Verbindung (etwa ein vom Angreifer bereits geöffnetes C2 oder eine Reverse-Shell) wird durch die Default-Drop-Ketten getrennt. Ist keine Administrationsquelle angegeben (whitelist_ips und die erlaubten Adressen in guard.yaml sind leer), nehmen die SSH-Wartungsports auch während der Isolation neue Verbindungen von jeder Quelle an; der Server gibt beim Start eine Warnung aus. Mit preserve_ssh_on_isolation=false kappt die Isolation auch SSH. Die Server-Edition bis 1.10.4 hatte einen Fehler. Der Isolationsregelsatz verwarf die SSH-Antworten, sodass das SSH des Betreibers während der Isolation nicht funktionierte. In 1.10.5 wurde er behoben.

4.2 Dateiintegritätsüberwachung kritischer Pfade (FIM)

Überwacht die SHA-256-Hash-Integrität der für Systemstart, Authentifizierung, Netzwerk und Systemverwaltung wichtigsten Dateien. Erfasst werden 23 feste Pfade (/etc/shadow, /etc/passwd, /etc/sudoers, /etc/ssh/sshd_config, /bin/login, /usr/bin/sudo, /usr/sbin/sshd, /usr/lib/systemd/systemd u. a.); jede Datei direkt in 12 Verzeichnissen (/etc/pam.d, /etc/sudoers.d, /etc/ssh/sshd_config.d, /etc/cron.d und /etc/cron.{hourly,daily,weekly,monthly}, /etc/systemd/system, /etc/ld.so.conf.d, /etc/profile.d, /root/.ssh), wobei auch das Auftauchen neuer Dateien erkannt wird (ausgenommen sind known_hosts und known_hosts.old in /root/.ssh, die bei jeder SSH-Verbindung neu geschrieben werden); die eigenen Binärdateien von RoamSwitch; die authorized_keys jedes anmeldefähigen Benutzers; und /etc/ld.so.preload, die nicht existieren darf (ihr Auftauchen wird erkannt). Nach regulären Paketaktualisierungen wird die saubere Basislinie automatisch aktualisiert: auf Debian-basierten Systemen durch den Hook /etc/apt/apt.conf.d/99roamswitch-fim (apt upgrade usw.), auf RHEL-basierten Systemen und openSUSE durch eine systemd.path-Unit, die /var/lib/rpm überwacht (roamswitch-fim-update.path); beide führen roamswitch fim update aus.

Bestimmung des Einbruchswegs (wer die Änderung vorgenommen hat und über welche SSH-Anmeldung)

Die Benachrichtigungen über eine geänderte Datei (Critical-Path-FIM und Lockfile-FIM) enthalten jetzt den Prozess, der die Änderung vorgenommen hat (Konto, ausführbare Datei, Befehl), und die SSH-Anmeldung, zu der dieser Prozess gehört (Quell-IP und Port, Anmeldezeit, Authentifizierungsmethode und Fingerabdruck des öffentlichen Schlüssels). Das ist standardmäßig aktiv (fim_intrusion_context_enabled). Im Moment des Lesens eines Ereignisses legt der Daemon einen Schnappschuss von /proc/<pid> des schreibenden Prozesses an (ausführbare Datei, Benutzer, loginuid, sessionid, cgroup, Elternkette), denn ein Prozess wie tee oder sed ist eine Millisekunde später verschwunden. Ein bereits beendeter Prozess wird aus dem Ausführungsrekorder ergänzt (sofern aktiviert). Die Zuordnung zu einer Anmeldung nutzt zuerst die Sitzungstabelle des SSH-Schutzes und sonst die Accepted-Zeilen von logind und journald. Sie funktioniert auch bei deaktiviertem SSH-Schutz. Es wird nichts nach außen gesendet.

Vertraut wird nur dem, was der Kernel meldet: die ausführbare Datei aus /proc/<pid>/exe (nicht argv[0]), die Anmeldung aus loginuid (wird bei der Anmeldung einmal gesetzt und über sudo und su hinweg vererbt) und dem session-N.scope der cgroup, der Rest aus der Elternkette. Werte, die ein Prozess selbst ändern kann, etwa comm, die Befehlszeile und die Umgebung, werden nur angezeigt und nie für eine Entscheidung herangezogen; ein Prozess, der sich nur sshd nennt, gilt nicht als SSH-Anmeldung. Eine Benachrichtigung hält drei Antworten auseinander: gefunden (Quelle, Zeit, Methode, Schlüssel); „Es wurde keine SSH-Anmeldung gefunden“ (die Prüfung ergab einen systemd-Dienst, einen Container, eine lokale Anmeldesitzung oder einen Prozess ohne Anmeldesitzung); und „Der Anmeldeweg konnte nicht ermittelt werden“ (der Prozess war schon beendet und steht nicht im Ausführungsrekorder, logind hat nicht geantwortet, die Änderung stammt aus dem periodischen Scan und der Prozess ist unbekannt, und so weiter). Was nicht geprüft werden konnte, wird nie als „keine Anmeldung“ gemeldet. Die Benachrichtigung geht auch dann hinaus, wenn die Abfrage scheitert.

/etc/ssh/sshd_config: modified
  Prozess: root (angemeldet als admin) / /usr/bin/tee / Befehl: tee /etc/ssh/sshd_config (pid 4121)
  SSH-Anmeldung: die Sitzung, die admin um 2026-10-17 03:12:08 von 203.0.113.25:51544 aus geöffnet hat (Authentifizierung: publickey, Schlüssel SHA256:AbCdEf0123456789)

/etc/sudoers: modified
  Der Anmeldeweg konnte nicht ermittelt werden (die Änderung wurde von der periodischen Prüfung gefunden, der ändernde Prozess ist unbekannt)

Auch Änderungen, die eine neue Datei unter demselben Namen ablegen, werden jetzt erkannt: install, sed -i sowie cp mit anschließendem mv im selben Verzeichnis. Eine Markierung je Datei hängt am Inode, weshalb diese Art von Änderung früher kein Ereignis auslöste. Jetzt werden auch die Verzeichnisse markiert, die überwachte Dateien enthalten, und wird im selben Verzeichnis eine Datei mit anderem Namen geschlossen, schlägt der Daemon den Namen wenige Millisekunden später erneut nach. Grenze: Eine in einem anderen Verzeichnis geschriebene und per mv hineinverschobene Datei findet erst der periodische Scan (fim_check_interval_secs). Dann ist der schreibende Prozess nicht bekannt, und die Benachrichtigung sagt das auch.

Die Messungen liefen auf einer Ubuntu-24.04-VM, in der die Quelle des Operators in einem eigenen Netzwerk-Namespace (netns) lag. Bei sudo tee, bei einem mit nohup abgekoppelten Prozess (seine Quell-IP wurde auch nach dem Abmelden des Operators noch bestimmt, mit dem Hinweis „Diese Sitzung ist bereits beendet“), bei einer sudo -i-Kette und bei einem sehr kurzlebigen cat zeigte die Benachrichtigung IP, Benutzer und Authentifizierungsmethode. Eine lokale Anmeldung ergab „Es wurde keine SSH-Anmeldung gefunden“. Ein Prozess, der seinen Namen mit exec -a "sshd: …" tarnte, wurde nicht für SSH gehalten.

Neben der Benachrichtigung wird der Befund in der Vorfallszeitleiste (Typ fim) und in /var/lib/roamswitch/fim_intrusions.json (nur root, die letzten 100) festgehalten. Das MCP-Tool verify_fim liefert ihn in einem zusätzlichen Feld, recentIntrusionContext (nur bei Ausführung als root). Das Urteil darüber, ob eine Datei manipuliert wurde, ändert sich nicht. Grenzen: Bei deaktiviertem Ausführungsrekorder und einem nur einen Augenblick lebenden schreibenden Prozess ist die ausführbare Datei nicht bekannt; stattdessen werden die ausführbare Datei und die Befehlszeile des Elternprozesses angezeigt. Die Benachrichtigungen der Persistenzüberwachung (persistence_watch) enthalten keine Prozessangaben und erhalten daher keinen Einbruchsweg. Der Weg zeigt den ändernden Prozess und dessen Anmeldung, nicht mehr: der Zugang selbst (die ausgenutzte Schwachstelle oder die Art, wie ein Schlüssel gestohlen wurde) wird nicht gezeigt. Zum Abschalten fim_intrusion_context_enabled=false setzen.

4.3 Kernel- und Container-Härtung

Frag Gap (CVE-2026-53362) Schadensbegrenzung: Erzwingt user.max_user_namespaces = 0 über sysctl und neutralisiert LPE-Vektoren. Yama LSM Protection erzwingt kernel.yama.ptrace_scope = 2 und verhindert so eine unbefugte Speicherinspektion. Container-Workloads werden auf docker.sock-Gefährdung geprüft. In der Server-Edition ist dieses Verbot nicht privilegierter Namespaces standardmäßig an (harden_userns_enabled). Es verhindert rootless Podman und Ähnliches; setzen Sie es auf false, wenn Sie darauf angewiesen sind.

Die veröffentlichten Ports von Docker (-p) umgehen bekanntermaßen die Standard-Firewall des Hosts. Daher wird mit protect_docker_ports=true (Standard) Verkehr verworfen, der von der externen Schnittstelle kommt und dessen Ziel-Port vor dem DNAT nicht zu den erlaubten Ports (ssh_ports, allowed_ports) gehört (Rückverkehr, Loopback und Container-zu-Container-Verkehr sind nicht betroffen). Beim iptables-/iptables-nft-Backend liegen die Regeln in der Kette DOCKER-USER (IPv4, und über ip6tables auch, wenn Docker-IPv6 aktiv ist); beim nativen nftables-Backend von Docker (ab Docker 29, eine Konfiguration ohne DOCKER-USER) in einer eigenen Tabelle inet roamswitch_docker_guard (forward-Hook, Priorität -10), und dieses eine Regelwerk deckt IPv4 und IPv6 ab. Der Daemon prüft regelmäßig erneut und stellt verschwundene Regeln wieder her. Zusätzlich erkennt ein dauerhaft aktiver Wächter über docker events in Echtzeit den Start eines --privileged-Containers oder das Einbinden von /var/run/docker.sock und meldet es sofort als Container-Ausbruchsrisiko (keine Konfiguration nötig; nur Benachrichtigung, keine automatische Blockierung). Für Hosts, die Dateien zur Weitergabe an andere verarbeiten (etwa Mail-Relays oder Freigaben), bietet der optional aktivierbare File Scan Guard (integriertes YARA plus optional ClamAV) regelmäßiges Scannen und automatische Quarantäne.

Container Exec Guard (container_exec_guard_enabled, Standard true) — setzt fanotify FAN_OPEN_EXEC (Benachrichtigungsklasse) auf die overlay2-Wurzel jedes laufenden Docker-Containers und prüft den Inhalt jeder ausgeführten Datei mit den eingebauten YARA-Regeln, bei einem Treffer wird benachrichtigt. Da er zuerst docker events abonniert und dann die laufenden Container mit docker ps auflistet, sind auch Container abgedeckt, die beim Start des Daemons bereits liefen. Der Inhalt der ausgeführten Datei wird aus dem von fanotify übergebenen Dateideskriptor gelesen und lässt sich daher auch dann prüfen, wenn sich die Datei direkt nach der Ausführung selbst löscht. Er benachrichtigt nur und stoppt oder verweigert keine Ausführung (die Server Edition hat überhaupt kein fanotify der Berechtigungsklasse). Docker 29 hat das veraltete Status aus den Nachrichten von docker events entfernt; daher schlug das Abonnement bis 1.11.0 sofort fehl, und der Guard verband sich alle 5 Sekunden neu, ohne je ein Abonnement zu bekommen. Seit 1.11.1 nutzt er Action, das auch bei älterem Docker denselben Wert hat. Schlägt das Abonnement weiter fehl, verdoppelt sich der Abstand zwischen den Verbindungsversuchen von 5 Sekunden bis auf höchstens 5 Minuten, und die Warnung zur selben Ursache wird nur beim ersten Mal protokolliert.

4.4 eBPF-Laufzeit-Bedrohungstelemetrie und Anti-Bloat-Tuning

Nutzt moderne eBPF-Prüfungen (CO-RE/BTF), um Rechteausweitungen und Container-Ausbruchsversuche in Millisekunden abzufangen. Um die Standardprobleme von Falco zu beseitigen – Protokollaufblähung, Festplattenerschöpfung und CPU-Overhead – standardisiert RoamSwitch ein optimiertes Profil (/etc/falco/config.d/99-roamswitch-optimized.yaml):

  • Schweregradfilterung (priority: warning): Unterdrückt verrauschte Betriebstelemetriedaten (Info/Hinweise) um 95 % und deckt streng umsetzbare Sicherheitsvorfälle auf.
  • Kernel-Level Pre-Drop (drop_failed_exit: true): Verwirft fehlgeschlagene Systemaufruf-Exits direkt im Kernel-Probe, wodurch CPU-Kontextwechsel um über 50 % reduziert werden.
  • Memory Footprint Optimization (cpus_for_each_buffer: 2): Komprimiert Ringpuffer von 8 MB auf 2 MB und begrenzt die Speichernutzung streng auf 30–50 MB.
  • Direct UNIX Domain Socket IPC: Direkte Anbindung über einen Socket im Arbeitsspeicher (/run/roamswitch/events.sock), ganz ohne Festplatten-E/A.
  • Automated Log Cap (/etc/logrotate.d/roamswitch-falco): Tägliche Rotation mit maxsize 50M und 7 komprimierten Zyklen hält das Wachstum der Falco-Logs in Grenzen.

Genauigkeit und Geschwindigkeit der eBPF-Isolation (nicht allein den Falco-Regeln überlassen)

Wie genau und wie schnell die eBPF-Isolation ist, hängt von den Regeln des Sensors (Falco oder Tetragon) ab. Tatsächlich enthalten die Standardregeln von Falco 0.45.0 (29 Stück) keine, die eine Reverse Shell auf dem Host erkennt: Die Regeln für Reverse Shells gelten nur für Container, und einige davon verwirft die Bedingung priority: warning von RoamSwitch. RoamSwitch setzt gute Regeln nicht voraus, sondern gleicht das auf drei Wegen aus: Es misst, wie lange die Isolation dauert, prüft regelmäßig, ob der Alarmweg lebt, und erkennt Reverse Shells auch selbst.

Messung der Isolationsverzögerung: Zu jedem eBPF-Vorfall hält der Daemon fest, wie viel Zeit von der Erkennung durch Falco bis zum Lesen des Alarms vergeht (detect_to_receive_ms), vom Lesen bis zum Abschluss der Reaktion (receive_to_action_ms, gemessen nach der Rückkehr des Isolationsaufrufs; beim Host-Air-Gap bis zum Laden des Regelsatzes) und die Summe (detect_to_action_ms). Die Werte erscheinen als zusätzliche Felder in ebpf_incidents.json und im MCP-Tool get_ebpf_incidents. Die Benachrichtigung über einen isolierten Prozess enthält eine Zeile „von der Erkennung bis zur Reaktion: N ms“. Gemessen auf einer Ubuntu-24.04-VM (Falco 0.45.0, modern eBPF): 1 bis 2 ms von der Erkennung bis zum Empfang, 41 bis 62 ms vom Empfang bis zu Prozessisolation plus SIGKILL (42 bis 64 ms insgesamt) und 109 ms insgesamt für das Host-Air-Gap (innerhalb des Ziels von 150 ms). Die Zahlen gehören zu dieser VM. Tetragon setzt den Zeitstempel beim Empfang, daher gibt es dort kein detect_to_receive_ms.

Heartbeat (ebpf_heartbeat_interval_secs; standardmäßig 600 Sekunden, 0 schaltet ihn ab, sonst 60 bis 86400): Das Paket bringt eine eigene Falco-Regel von RoamSwitch mit, 96-roamswitch-heartbeat.yaml. In jedem Intervall öffnet der Daemon einen Wegwerfpfad, den nur root nutzen kann (ein Zufallsname unter /run/roamswitch/heartbeat/), und misst, wie lange der Alarm dieser Regel braucht, um über die Ausgabe von Falco zurückzukommen. Ein Hin und Zurück zeigt zugleich, dass die Regel geladen ist, dass Falco läuft und dass der Ausgabeweg lebt. Nur wenn zwei Prüfungen in Folge nicht zurückkommen (die zweite eine Minute nach der ersten), warnt er („Die Regeln sind nicht geladen oder die Ausgabe kommt nicht an“), höchstens einmal in 24 Stunden. Eine Heartbeat-Zeile wird verworfen, ohne Isolation, Benachrichtigung, Allowlist oder Vorfallsprotokoll zu erreichen. Es wird nichts nach außen gesendet. Gemessen wurden 2 bis 6 ms für den Hin- und Rückweg; nach dem Entfernen der Regel kam die Warnung nach etwa 164 Sekunden, nach der Wiederherstellung war der Zustand nach etwa 75 Sekunden wieder normal.

Der Zustand liegt in /var/lib/roamswitch/ebpf_heartbeat.json und wird vom Feld heartbeat des MCP-Tools get_ebpf_incidents und von der Diagnose K-04 (eBPF-Laufzeit-Agent; die Zahl der Diagnosepunkte bleibt 34) gelesen. Auch wenn Falco läuft, fällt K-04 durch, wenn der Heartbeat nicht zurückkommt. Grenzen: Geprüft wird ein Hin und Zurück einer einzigen Regel (der Systemaufrufe der Familie open); dass eine andere Regel für sich kaputt ist, erkennt das nicht. Was zwischen zwei Prüfungen (standardmäßig 10 Minuten) kaputtgeht, fällt erst bei der nächsten auf. Für Tetragon wird es nicht durchgeführt. Auf einem Host, auf dem Falco nicht läuft oder die Regeldatei fehlt, wird nichts geprüft und vor nichts gewarnt (das übernimmt die bestehende Meldung „Schutz gestoppt“). Falco schreibt je Prüfung eine Warnzeile ins Syslog (standardmäßig 144 Zeilen am Tag).

Reverse-Shell-Erkennung (eigene von RoamSwitch)

Ohne sich auf die Regeln von Falco zu stützen, liest RoamSwitch selbst alle 2 Sekunden /proc und sucht nach einer Shell oder einem Interpreter (sh, bash, python, perl, ruby, php, node und ähnliche), deren Standardein- und -ausgabe an einer einzigen TCP-Verbindung hängen, die dieser Host zu einer externen Adresse aufgebaut hat. Erfasst werden bash -i >& /dev/tcp/…, python, perl, nc -e und socat exec:. Gemeldet wird nur, was zweimal hintereinander gesehen wird, einmal je Prozess. Standardmäßig zählen nur öffentliche externe Adressen; private Adressen (RFC 1918, CGNAT, Link-Local) zählen nur mit reverse_shell_watch_include_private=true, weil ssh-ProxyCommand, Container und lokale Entwicklung sie häufig und legitim machen. Loopback wird nie überwacht. Vom Host angenommene Verbindungen (durch inetd oder socat TCP-LISTEN) sind ebenfalls nicht erfasst. Gemessen auf einer Ubuntu-24.04-VM, wurden bash /dev/tcp, python, perl, nc -e und socat exec: jeweils etwa 2,4 Sekunden nach dem Verbindungsaufbau erkannt. ssh, ssh mit ProxyCommand, git über ssh und ein nc-Client werden nicht erkannt.

Ein Treffer läuft als Critical-eBPF-Ereignis mit dem Namen RoamSwitch Reverse Shell über denselben Weg wie ein Falco-Alarm (Allowlist, Benachrichtigungs-Abkühlzeit, die Aktionen je Schweregrad aus guard.yaml, Vorfallsprotokoll). Standardmäßig wird der Prozess isoliert und beendet (kill). Eine Reverse Shell, die root gehört, lässt sich nicht pro Prozess isolieren und geht daher, wie jedes Critical-Ereignis, bis zum Air-Gap des gesamten Hosts weiter. Wer fürchtet, dass ein legitimes Programm fälschlich erfasst wird, hat zwei Auswege: reverse_shell_watch_notify_only=true (eine Warnung nur mit Benachrichtigung; nichts wird isoliert oder beendet; standardmäßig false) und einen Allowlist-Eintrag, sudo roamswitch server allowlist add "RoamSwitch Reverse Shell" <Prozessname>. Die drei Einstellungsschlüssel sind reverse_shell_watch_enabled (standardmäßig true), reverse_shell_watch_include_private (false) und reverse_shell_watch_notify_only (false).

Grenzen: Es wird nach Namen (Prozessname und Name der ausführbaren Datei) eingegrenzt; ein selbstgebautes Programm unter einem anderen Namen als dem einer Shell oder eines Interpreters, das Standardein- und -ausgabe an einen Socket bindet, wird daher nicht gefunden. Verbindungen über Loopback (etwa die Rückführung von ssh -R) und Verbindungen unter 2 Sekunden werden nicht gesehen, ebenso wenig Prozesse, die im Prozessraum des Hosts nicht sichtbar sind. Diese Erkennung gibt es nur in der Server Edition; der Mac und der Linux-Client haben sie nicht.

4.5 Notfall-Luftspaltisolierung mit Warnungen vor der Trennung

Unmittelbar vor der Unterbrechung der Netzwerkschnittstellen bei kritischen Manipulationen sendet der Daemon synchron Notfallwarnungen an Telegram, LINE und Webhooks. Warnungen hängen automatisch den Server Hostname und Primäre IP-Adresse an.

Notfallalarmformat (JA/EN)
🚨 [RoamSwitch IMMINENT AIR-GAP] CRITICAL: IMMINENT AIR-GAP HOST ISOLATION (cve_2026_53362_lpe)
🚨 CRITICAL SECURITY INCIDENT DETECTED: cve_2026_53362_lpe
Host: production-node-01 (IP: 192.168.1.10)
Process: exploit_payload (PID: 4921)
ACTION: Initiating host Air-Gap network isolation (SSH preservation active).
WARNING: Outbound internet connectivity will be cut immediately after this message.
Timestamp: 2026-09-06 18:00:00
⚠️ Network connectivity will be severed immediately.

Die Aufhebungsbedingungen hängen von der Konfidenz des Auslösers ab. Auslöser mit geringer Konfidenz (z. B. ein eBPF-Ereignis der Stufe Error und darunter) werden über einen kurzen Timer (server_safeguards.safety_timer_secs in guard.yaml, Standard 300 Sekunden) vollständig aufgehoben. Auslöser mit hoher Konfidenz (eBPF Critical/Emergency/Alert, Eskalation zur Host-Isolation durch eine sich wiederholende Regel, Kanarien-Manipulation usw.) stellen nie stillschweigend wieder her. Ab dem kurzen Timer wird die Ursache erneut geprüft (lebt die eingefrorene PID noch, hat die Regel erneut ausgelöst usw.), und die Isolation wird mit Benachrichtigung aufgehoben, nur wenn die Ursache nachweislich beseitigt ist. Lässt sie sich nicht belegen und gibt es bis zur Obergrenze (isolation_hard_cap_secs, Standard 3600 Sekunden; 0 = keine Obergrenze) kein ACK, wechselt sie in DEGRADED. DEGRADED erhält den Admin-Pfad (Wartungs-SSH-Ports und Wartungs-Quell-IPs, neu und bestehend), erlaubt neuen ausgehenden Verkehr nur zu den Wartungs-Quell-IPs und öffnet sich niemals per Timer. Aufgehoben wird nur durch eine Neuprüfung, die das Verschwinden der Ursache belegt, durch roamswitch server ack (ein ACK während DEGRADED bedeutet Aufhebung) oder durch roamswitch emergency-restore. Eine im Zustand FULL per ACK bestätigte Isolation gilt als vom Betreiber übernommen: Sie wird weder per Timer aufgehoben noch bei nachgewiesenem Verschwinden der Ursache automatisch gelöst, und sie wechselt auch nicht in DEGRADED, sondern bleibt bestehen, bis emergency-restore sie aufhebt. Jeder Übergang wird in der Vorfall-Zeitleiste festgehalten und gemeldet.

Prozess-Ausführungsrekorder & Ereignisweiterleitung

Ein rein lokaler Rekorder, der exec über den netlink-Prozess-Connector protokolliert, läuft standardmäßig aktiviert (gemeinsam mit der Client Edition). Er speichert Programmpfad, Kommandozeilenargumente (längenbegrenzt, Steuerzeichen maskiert), Elternprozess-Abstammung, uid, Container-ID, SHA-256 der ausführbaren Datei u. a. in /var/lib/roamswitch/exec_log als JSON Lines mit Hash-Kette (0600; standardmäßig 200 MB / 14 Tage). Die Hash-Kette macht Manipulation erkennbar, aber nicht verhinderbar (ein Angreifer mit Root kann die gesamte Kette neu schreiben). Die nur benachrichtigenden Korrelationsregeln EXR-001 bis EXR-010 (Shell von einem Webdienst gestartet, Ausführung aus /tmp oder memfd usw.) isolieren nie allein. Nur wenn ein Betreiber exec_rules_isolation_optin (Standard false) ausdrücklich aktiviert, wird eine Regel mit hohem Schweregrad als Auslöser mit hoher Konfidenz für die Host-Isolation behandelt.

Die Ereignisweiterleitung (forward_enabled, Standard false) sendet nur an die vom Betreiber konfigurierten Ziele: Syslog (RFC 5424 oder CEF, über UDP / TCP / TLS), eine JSON-Lines-Datei oder einen mit HMAC-SHA256 signierten Webhook. TLS-Syslog läuft über das System-openssl s_client, der Webhook über das System-curl (Geheimnisse werden in einer Konfiguration über die Standardeingabe übergeben, nie in der Kommandozeile); der Daemon enthält kein TLS-/HTTP-Crate. Gesendet werden nur die Felder Hostname, Ereignis-ID, Zeitstempel, Quelle, Schweregrad, Regel, Aktion, PID, Prozessname und Zusammenfassung – für die Erkennungsereignisse, die in der Vorfall-Zeitleiste und im Benachrichtigungsverlauf erscheinen (eBPF, Wechsel des Isolationszustands, FIM, Kanarien usw.), und für Meldungen der Ausführungsregeln – sowie die Segment-Siegel-Hashes des Ausführungsprotokolls. Das Rohprotokoll der Ausführungen ist nicht enthalten.

DNS-Tunneling-/Exfiltrationserkennung

Wird dns_tunnel_detect_enabled (Standard: true) aktiviert, überwacht ein dedizierter NFQUEUE-Consumer die vom Host selbst gesendeten DNS-Abfragen (nur UDP/TCP-Port 53). Eine Abfrage gilt als „verdächtig geformt“ (das für DNS-Tunneling-Tools wie iodine oder dnscat2 typische Muster), wenn ihr Label über 40 Byte lang ist UND ihre Shannon-Entropie über 3,8 liegt, oder wenn ihr Eintragstyp TXT/NULL ist (TXT-Abfragen an clamav.net, die ClamAV für Signaturaktualisierungen nutzt, werden nicht mitgezählt); benachrichtigt wird erst, wenn innerhalb eines gleitenden 60-Sekunden-Fensters 10 oder mehr solcher Abfragen auftreten (wiederholte Benachrichtigungen für dieselbe Domain folgen frühestens nach 300 Sekunden, bei anhaltendem Burst nach 600 und 1200 Sekunden, höchstens im Abstand von 1800 Sekunden). Geprüft wird ausschließlich DNS (UDP/TCP-Port 53); anderer Datenverkehr wird nicht untersucht. Die Funktion benachrichtigt nur und blockiert nie automatisch. Die zugrunde liegende nft-Regel trägt das Flag bypass, sodass DNS-Abfragen unverändert durchgelassen werden, selbst wenn der Erkennungs-Thread gestoppt ist oder nicht reagiert; die Namensauflösung wird durch einen Ausfall dieser Funktion niemals blockiert. Eine Änderung dieser Einstellung wirkt sich erst nach roamswitch server restart aus (kein Live-Reload).

Bekannte Einschränkung: Lange, durch Bindestriche getrennte Hostnamen (etwa prod-us-east-1-web-server-node-0042) sowie legitime, gerade auf Servern realistische Vorgänge, etwa ein Mailserver, der SPF-/DKIM-TXT-Einträge für viele verschiedene Absenderdomänen in kurzer Zeit prüft, führten hier nachweislich zu Fehlalarmen, weil TXT-/NULL-Bursts über einen einzigen globalen Zähler ohne Unterscheidung nach Zieldomäne gezählt wurden. 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 ServerConfig.dns_tunnel_entropy_allowlist (ein durch Kommas getrennter Schlüssel in server.conf, auch über die TUI editierbar) eigene interne Domains hinzufügen. Die Allowlist setzt nur die Prüfung aus Label-Länge und Entropie außer Kraft; die TXT-/NULL-Qtype-Erkennung greift unabhängig davon immer, sodass ein Angreifer einen Tunnel nicht unter einer zugelassenen Domain verstecken kann (die einzige Ausnahme sind TXT-Abfragen an clamav.net, die ClamAV für Signaturaktualisierungen nutzt; sie werden nicht mitgezählt, weil Dritte unter dieser Domain keine Subdomains anlegen können). 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 (das zugrunde liegende 60-Sekunden-Fenster und der Schwellenwert von 10 Abfragen bleiben durch diese Korrektur unverändert; der Abstand zwischen wiederholten Benachrichtigungen wurde später so geändert, dass er bei anhaltendem Burst von 300 Sekunden bis auf höchstens 1800 Sekunden wächst). 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.

Erkennung und Sperrung von SSH-Brute-Force (ssh_guard)

Eine eigene Brute-Force-Abwehr von RoamSwitch, aktiv mit ssh_guard_enabled (standardmäßig true). Sie liest das sshd-Log aus journald mit journalctl -f mit (nur ohne journald wird auth.log oder secure verfolgt), zählt Fehlversuche je Quelladresse und verwirft bei einer Quelle, die die Schwelle erreicht (Standard: 6 innerhalb von 600 Sekunden), in der Tabelle inet roamswitch_sshguard ausschließlich neue Verbindungen (ct state new) zu den SSH-Ports. Zugleich mit der Sperre werden auch die Verbindungen getrennt, die diese Quelle bereits zu SSH offen hatte (die conntrack-Einträge werden gelöscht und eine Regel verwirft die Pakete der Antwortrichtung). Gesperrt wird nur eine Quelle ohne authentifizierte Sitzung, ohne protokollierte Anmeldung per öffentlichem Schlüssel und ohne Ausnahme; das wird unmittelbar vor dem Trennen noch einmal geprüft. Eine authentifizierte Sitzung und eine ausgenommene Quelle werden daher nie getrennt. Eine Sperre beginnt bei 1 Stunde, vervierfacht sich bei jeder Wiederholung und ist auf 7 Tage begrenzt; den Ablauf erledigt der nftables-Timeout. Sie startet kein Air-Gap und sendet nichts nach außen (lokal laufen nur journalctl, nft, loginctl und ähnliche Befehle). Schützt fail2ban (mit aktivem sshd-Jail) oder CrowdSec (mit laufendem Firewall-Bouncer) sshd bereits, überlässt sie das Sperren diesen und erkennt und meldet nur.

Logzeilen enthalten eine Zeichenfolge, die der Angreifer bestimmt (den Benutzernamen). Deshalb wird die Quelladresse nur vom Zeilenende gelesen (from <IP> port <N>), und eine in den Benutzernamen eingetragene gefälschte Quelladresse führt nicht dazu, dass eine unbeteiligte Quelle gesperrt wird. Aus journald werden nur Zeilen gelesen, deren Absenderangaben (_UID, _COMM) zu einem sshd von root gehören; mit logger -t sshd geschriebene Zeilen werden ignoriert. Das Verfolgen einer Datei (auth.log) ist nicht der Standard, weil die Datei kein Feld hat, das für den Absender bürgt, und jeder lokale Benutzer, der syslog verwenden darf, Zeilen fälschen kann. Damit Betreiber nicht ausgesperrt werden, werden das Gateway, DNS, der Host selbst, Loopback, whitelist_ips, ssh_guard_allow, die Quelle einer authentifizierten SSH-Sitzung, jede Adresse mit erfolgreicher Anmeldung per öffentlichem Schlüssel in den letzten 30 Tagen und ein gekoppelter Sensor nie gesperrt. Private Adressen sind nicht ausgenommen. Ein fehlgeschlagener öffentlicher Schlüssel (Failed publickey) wird nicht gezählt.

Gemessen (Ubuntu-24.04-VM mit echtem journald und systemd): Vom 6. Fehlversuch bis zur Sperre vergingen etwa 0,2 Sekunden (0,17 bis 0,24 Sekunden). Die Quelladresse des Betreibers wurde nicht gesperrt, und ein Versuch mit gefälschter Quelladresse im Benutzernamen führte nicht dazu, dass eine unbeteiligte Quelle gesperrt wurde. Ein echter hydra-Lauf (4 parallel) wurde nach 6 Fehlversuchen gestoppt. Geprüft wurden außerdem die Wiederherstellung einer Sperre mit Restzeit nach einem Neustart des Servers, das Aufheben einer Sperre und das Zurückfallen auf reines Erkennen und Melden, solange fail2ban sshd schützt. Diese Werte stammen aus dieser VM-Umgebung. Gemessen mit dem hinzugefügten Trennen der Verbindungen: Die nach einer Sperre noch durchgekommenen Fehlversuche lagen vorher bei 16 bis 24 und danach bei 0 bis 4. Das bloße Löschen der conntrack-Einträge trennte die Verbindungen nicht; erst mit einer zusätzlichen Regel, die die Antwortrichtung verwirft, wirkte es.

Regeln der Web-Anwendungsschicht (Web-Shells und eingeschleuster Code)

Die Server-Edition hatte keinen schreibgesteuerten Scan, nur den periodischen Scan von clamav_scan_dirs. Jetzt überwacht sie die in der Webserver-Konfiguration (Apache, nginx, Caddy) gefundenen Dokumentenwurzeln mit rein benachrichtigendem fanotify (FAN_CLASS_NOTIF, das nie einen anderen Prozess blockieren kann) und prüft PHP-, JavaScript-, JSP- und ASP-Dateien unmittelbar nach dem Schreiben und Schließen mit den Regeln der Web-Anwendungsschicht (Web-Shells, eingeschleuster verschleierter Code, in Bildern versteckter PHP-Code, .htaccess-Missbrauch). Ein periodischer Scan alle 6 Stunden deckt verworfene Ereignisse und bereits vorhandene Dateien ab. Die Regeln gibt es in drei Schichten (eingebaut, vom täglichen Updater nach Signaturprüfung installiert, eigene Dateien in /etc/roamswitch/rules.d/*.json); die 18 Regeln enthalten keine aus echten Proben gewonnene Signatur und beschreiben nur öffentlich dokumentierte Techniken.

In der Server-Edition gilt die automatische Quarantäne standardmäßig nur für critical. Ein high-Treffer löst nur eine Benachrichtigung und den Hook nach der Erkennung aus; Dateien laufender Websites bleiben unangetastet. Benachrichtigungen (Telegram, LINE, Webhook) gibt es in 10 Sprachen; sie nennen die Regel und ob die Datei isoliert oder belassen wurde. Der Regelabruf läuft über denselben einen Abruf wie der tägliche Updater und fügt kein neues Ziel hinzu. Ist cve_kernel_map_updates_enabled aus, gibt es keinerlei Netzwerkkontakt, und die eingebauten Regeln gelten. Mit einem echten fanotify-Watch wurde eine geschriebene Web-Shell innerhalb von 2 Sekunden isoliert, eine harmlose Datei blieb unberührt.

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.

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 (/root/.aws/credentials, /root/.ssh/id_rsa, /root/.docker/config.json, /root/.pypirc und /root/.env.backup, unter /root, da der Daemon als root läuft), jeweils mit dem Marker ROAMSWITCH_HONEYTOKEN (standardmäßig an; honeytokens_enabled schaltet es ab, honeytokens_home ändert den Ort der Köder). 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 begrenzte, kaskadierende Bereitstellung weiterer, verwandter Köder auslösen (ein zusätzliches AWS-Profil, eine SSH-config, eine kubeconfig und Ähnliches). 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, und das Problem, dass die systemd-Sandbox in der Server-Edition Schreibzugriffe auf /root blockierte, wurde ebenfalls in 1.10.5 behoben. 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 /root/.docker/config.json nicht aus. Ein Lesezugriff durch ein anderes Programm wird weiterhin wie bisher erkannt.

Ein Hintergrundwächter (roamswitch-honeytokens) überwacht mit fanotify der Benachrichtigungsklasse (es blockiert nichts) das Lesen und Öffnen jedes Köders. Das Ereignis trägt die PID des Zugreifenden, sodass die zugreifende ausführbare Datei sofort identifiziert wird (wo fanotify nicht verfügbar ist, wird auf inotify und fuser umgeschaltet). Da kein legitimer Prozess einen Grund hat, diese Dateien zu lesen, wird jeder Zugriff, der nicht von den eigenen Binärdateien von RoamSwitch oder, bei den SSH-Ködern, von einem OpenSSH-Client (ssh, scp, sftp, ssh-add, ssh-agent u. a., nicht jedoch ssh-keygen) stammt, als starkes Signal für eine Aufklärung durch einen Angreifer nach einer Kompromittierung gewertet (MITRE ATT&CK T1552, Unsecured Credentials), und es wird eine Benachrichtigung gesendet. Ein Zugriff, dessen ausführbare Datei sich nicht identifizieren lässt, wird nicht durchgelassen, sondern als Erkennung gewertet. Dies dient ausschließlich der Benachrichtigung; der zugreifende Prozess wird dadurch weder eingefroren noch blockiert.

Bekannte Einschränkung: Der Inhalt des /root/.ssh/id_rsa-Köders enthält lesbaren Text und bleibt als Base64-Rumpf eines echten OpenSSH-Schlü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 kann in Umgebungen, in denen fanotify nicht verfügbar ist und auf inotify umgeschaltet wird, die Identifizierung des zugreifenden Prozesses (per fuser-Aufruf) bei sehr kurzlebigen Prozessen scheitern, die sich unmittelbar nach dem Lesen der Datei beenden: PID und Prozessname werden dann nicht ermittelt. In diesem Fall wird der Prozess lediglich als unbekannt erfasst; die Erkennung des Zugriffs selbst (Ereignisauslösung und Benachrichtigung) ist davon nicht betroffen.

Beweissicherungs-Bundles (automatische forensische Erfassung)

Die Beweissicherung wird in diesen Fällen gestartet. Ein Ereignis des eBPF-Laufzeit-Bedrohungssensors führt zu einer erfolgreichen prozessgenauen Netzwerkisolation; diese Isolation schlägt fehl und eskaliert zu einer hostweiten Air-Gap-Isolation; oder eine hostweite Air-Gap-Isolation wird ausgeführt. Auch beim Ransomware-Canary-Pfad wird sie gestartet, wenn eine Manipulation erkannt, der Prozess eingefroren und der Host isoliert wird. Bei hostweiter Abschaltung startet sie vor dem Kappen und verzögert dieses nicht. Bis 1.10.4 lief sie nur nach einer erfolgreichen prozessgenauen Isolation; 1.10.5 hat das erweitert. Ist keine Ziel-PID bekannt, entfällt der /proc-Snapshot. roamswitch-incident-capture wird 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 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. 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 ein Betreiber explizit sudo roamswitch-incident-capture prune [--keep-days N] (Standardaufbewahrung: 30 Tage) ausführt. Eine manuelle Erfassung ist jederzeit über sudo roamswitch-incident-capture snapshot [--pid PID] [--reason TEXT] [--json] möglich.

Erfasste Beweise werden zum Zeitpunkt der Erfassung nicht verifiziert. Um nachträglich auf Manipulation zu prüfen, führen Sie sudo 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.

§534-Check Security Diagnostic Suite

Die Server Edition führt 34 spezielle Sicherheitsprüfungen durch:

# Kategorie Überprüfen Sie den Titel Standard & Logik
1Authentifizierung und ZugriffSSH-Root-Login und Passwort-AuthentifizierungPrüfung von PermitRootLogin no. Ist auch die Passwortauthentifizierung deaktiviert, wird ausschließlich Public-Key-Zugang gemeldet; ist sie aktiviert, besteht die Prüfung dennoch, solange der direkte Root-Login verboten ist
2Authentifizierung und ZugriffLeere PasswortkontenStellt sicher, dass kein Benutzer in /etc/shadow einen leeren Passwort-Hash hat
3Authentifizierung und ZugriffSudoers Privilege HygienePrüft, dass in /etc/sudoers und /etc/sudoers.d keine NOPASSWD: ALL-Regel steht, die ohne Passwort alle Rechte gewährt
4NetzwerkEingehende StandardverweigerungÜberprüft nftables auf die Standardrichtlinie für eingehendes Löschen
5Kernel und IntegritätNicht privilegierte Benutzernamensräume (Frag Gap)Stellt sicher, dass user.max_user_namespaces = 0 (oder kernel.unprivileged_userns_clone = 0) gesetzt ist und damit der LPE-Angriffspfad gesperrt wird
6Kernel und IntegritäteBPF BTF-UnterstützungValidiert Kernel-BTF-Typinformationen über /sys/kernel/btf/vmlinux
7Kernel und IntegritäteBPF LSM AktivPrüft auf bpf im Kernel-Boot-Parameter lsm=
8NetzwerkXDP-Boot-GateSchließt mit einem XDP-Default-Deny-Gate das Zeitfenster beim Booten, bevor die nftables-Tabelle von Link Guard installiert ist (experimentell, nur per Opt-in, standardmäßig nicht geladen). Geprüft wird, ob der gepinnte Link vorhanden ist; „nicht geladen“ gilt nicht als Fehler
9Kernel und IntegritäteBPF Runtime Security AgentPrüft, ob ein Agent wie Falco oder Tetragon läuft. Solange Falco läuft, wird zusätzlich geprüft, ob der Alarm der eigenen RoamSwitch-Regel zurückkommt (Heartbeat); kommt er nicht, fällt die Prüfung durch (mit Nennung fehlender RoamSwitch-Falco-Dateien)
10Kernel und IntegritätEinheitliche Vorfall-ZeitleistePrüft, ob die Zeitleiste, die Vorfälle von Link Guard, Canary, eBPF Guard und Resource Guard chronologisch zusammenführt, aufzeichnen kann (vorhandene Ereignisse oder beschreibbarer Speicher), und zeigt die letzte Eindämmungszeit an
11BehälterDocker-Socket-Mount-AuditErkennt Container-Mounts von /var/run/docker.sock
12BehälterDocker-privilegierte ContainerAudits für --privileged-Container-Workloads mit hohem Risiko
13BehälterIsolation der Container-Runtime (runc/gVisor/Kata)Prüft die Standard-Container-Runtime. Eine runc-basierte Runtime (teilt den Host-Kernel) besteht nicht; gVisor (runsc) oder Kata Containers (VM-Isolation pro Container) bestehen. Nicht anwendbar, wenn Docker/containerd nicht erkannt wird
14BehälterSchutz vor Docker-Firewall-Umgehung (DOCKER-USER)Prüft, ob die Regeln von RoamSwitch tatsächlich in der stets zuerst durchlaufenen DOCKER-USER-Kette (oder in der eigenen Docker-Guard-nftables-Tabelle) vorhanden sind, damit veröffentlichte Container-Ports das Default-Deny der Firewall nicht über Dockers eigene Regeln umgehen können. Wird nur ausgewertet, wenn protect_docker_ports in server.conf aktiviert ist
15Kernel und IntegritätClamAV-Erkennungstest im Livebetrieb (EICAR)Zwei Minuten nach dem Start und danach alle 6 Stunden scannt der Daemon aus seiner eigenen Umgebung (z. B. in einer systemd-Sandbox) eine harmlose EICAR-Testdatei, um zu bestätigen, dass ClamAV sie tatsächlich erkennt. Wird nur ausgewertet, wenn clamav_enabled in server.conf aktiviert ist
16Kernel und Integritätfanotify: verpasste Ereignisse (Warteschlangenüberlauf)Prüft, ob der Kernel FIM- und Container-Ausführungsereignisse verworfen hat, weil die fanotify-Ereigniswarteschlange übergelaufen ist. Dateischreibvorgänge und Ausführungen während eines Überlaufs entgehen der Echtzeitüberwachung; tritt dies häufig auf, erhöhen Sie fs.fanotify.max_queued_events
17Kernel und IntegritätBekannte Kernel-CVE-GefährdungGleicht die Version des laufenden Kernels mit der lokalen Karte bekannter CVEs ab (eingebettete Baseline oder signaturgeprüfte Aktualisierung). Die Prüfung selbst kommuniziert nicht nach außen; Aktualisierungen der Karte werden gemäß cve_kernel_map_updates_enabled abgerufen (Standard true, abschaltbar). Ein nicht bestimmbares Ergebnis gilt als „nicht abschließend“, nicht als Fehler
18IntegritätDateiintegrität kritischer Pfade (FIM)SHA-256-Integritätsprüfung von 23 festen kritischen Dateien, jeder Datei direkt in 12 Verzeichnissen und weiteren
19Kernel und IntegritätYama-ProzessschutzStellt sicher, dass kernel.yama.ptrace_scope 2 oder 3 ist (Schutz vor dem Mitlesen des Speichers)
20NetzwerkIP-Weiterleitung deaktiviertVerifiziert net.ipv4.ip_forward = 0
21NetzwerkTCP-SYN-Cookie-SchutzVerifiziert net.ipv4.tcp_syncookies = 1
22NetzwerkReverse-Path-Filterung (rp_filter)Stellt sicher, dass net.ipv4.conf.all.rp_filter 1 (strikt) oder 2 (gelockert, für Multihomed-Konfigurationen) ist, sodass gefälschte Pakete verworfen werden
23Kernel und IntegritätCore-Dump-BeschränkungVerhindert Prozessspeicherlecks über fs.suid_dumpable = 0
24OperationenAutomatische SicherheitsupdatesPrüft die Konfiguration der automatischen Patch-Installation, etwa über unattended-upgrades (Debian / Ubuntu) oder dnf-automatic (RHEL / Fedora)
25OperationenNTP-ZeitsynchronisierungÜberprüft die Synchronisierung über chrony oder systemd-timesyncd
26OperationenSSH Brute-Force-SchutzBesteht, solange RoamSwitchs eigener SSH-Schutz (ssh_guard) läuft und sperrt, oder prüft die aktive Überwachung über fail2ban oder crowdsec
27Kernel und IntegritätNicht privilegiertes eBPF deaktiviertPrüft, dass kernel.unprivileged_bpf_disabled 1 oder 2 ist (Schutz vor Spectre/LPE)
28NetzwerkICMP-Weiterleitungen werden ignoriertVerhindert Routenvergiftung über accept_redirects = 0
29NetzwerkICMP-Echo-Broadcasts werden ignoriertMildert Smurf-Verstärker-DoS-Angriffe
30Kernel und IntegritätGemeinsame SpeicherhärtungPrüft, dass /dev/shm mit mindestens einer der Mount-Optionen nodev, nosuid oder noexec eingehängt ist
31Authentifizierung und ZugriffEs fehlen veraltete unsichere ProtokolleÜberprüft, dass keine unverschlüsselten Dienste (telnetd, rshd, tftpd …) und keine unverschlüsselten Clients (telnet, rsh, tftp …) installiert sind (Dienste und Clients werden getrennt gemeldet).
32Kernel und IntegritätSUID-Prozess-Core-Dumps eingeschränktVerhindert Anmeldeinformationslecks bei SUID-Binärabstürzen
33Kernel und IntegritätHilfsprogramme (Köder und Beweissicherung) installiertDer Daemon startet das Köder-Programm (Honeytoken) und das Programm für Beweispakete über den Namen und tut nichts, wenn eines fehlt, ohne Meldung. Geprüft wird, ob beide installiert sind.
34NetzwerkSensible Dateien im Webverzeichnis erreichbarErmittelt die Dokumentenwurzeln aus der Apache-/nginx-/Caddy-Konfiguration und prüft mit Anfragen an den Server selbst, ob dort liegende .git, .env, .DS_Store, phpinfo, SQL-Dumps, Backups und private Schlüssel tatsächlich über den Webserver lesbar sind. Als offengelegt gilt eine Datei nur, wenn die Antwort dem Anfang der Datei auf der Platte entspricht; eine Site, die auf jeden Pfad mit 200 antwortet, oder eine bereits mit 403 gesperrte Datei löst daher keinen Fehlalarm aus. Dateiinhalte werden nie gemeldet, nur Pfade. Ohne Webserver nicht zutreffend; lässt sich etwas nicht prüfen, gilt das Ergebnis als „nicht ermittelbar“, und der Score sinkt nicht.

Jeder der 34 Punkte wird, sofern zutreffend, mit einer NIST-CSF-2.0-Funktions-/Kategorie-Kennung versehen (z. B. PR.DS-01, DE.CM-09), und nur dort, wo eine verlässliche Zuordnung besteht, zusätzlich mit einer CIS-Controls-v8-Kontrollnummer (z. B. 10.1, 4.1). Mehrdeutige Punkte werden nicht erzwungen zugeordnet, sondern bleiben unzugeordnet. Diese Zuordnung ist sowohl in der CLI-Ausgabe (roamswitch server status) als auch in der MCP-Ausgabe (get_security_report) enthalten und ermöglicht es Betreibern und Prüfern mit Compliance-Anforderungen, die Prüfpunkte von RoamSwitch mechanisch bestehenden Rahmenwerken zuzuordnen.

§6Selbsttest (reproduzierbare Verifikation in einer Docker-Umgebung)

Gegen das aus dem offiziellen APT-Repository installierte Paket roamswitch-server läuft ein Selbsttest, der interne und externe Angriffe nachstellt; separate Docker-Container dienen dabei als externer Angreifer. Die Messung vom 2026-09-07 mit v1.3.2 ergab alle 18 Punkte PASS. Am 2026-09-25 wurde die Suite erneut mit einem aus dem 1.10-Quellcode gebauten Paket (arm64, Docker Desktop) ausgeführt; 19 Prüfungen bestanden. Der erneute Lauf deckte sechs Produktfehler auf, die alle behoben sind (enthalten in 1.10.5): Das Paket enthielt zwei Hilfsprogramme nicht, die FIM meldete die Honeytoken-Köder als neue Dateien, eine Bestätigung (ack) wurde ignoriert, während der Isolation wurden die Antworten des erhaltenen administrativen SSH-Kanals verworfen, sodass der Administrator ausgesperrt war, Port 22 blieb auch mit preserve_ssh_on_isolation=false offen, und die Sandbox der systemd-Unit blockierte die Schreibzugriffe für die Köder. Sie können diese Prüfung auf Ihrem eigenen Rechner nachvollziehen. Vorgehen und Skripte finden Sie unten in 6.3.

# Szenario Angriffsvektor Ergebnis
PENT-S1 Nmap SYN Stealth Scan Prüfen Sie die Ports 22, 80, 443, 3306, 8080 Der Default Drop von nftables verwirft Datenverkehr zu nicht freigegebenen Ports wie 3306 (MySQL) und 8080 ohne jede Antwort (Filtered). 100 % blockiert
PENT-S2 Unzulässige Portprüfung Curl-Direktverbindungen zu Port 3306 und 8080 Durch Inbound Default Deny antwortet nur der freigegebene Port 80 normal; alle anderen laufen in ein Timeout (werden verworfen)
PENT-S3 Egress-/C2-Sperrliste Versuch einer ausgehenden Verbindung zu einer im Malicious-IP-Feed registrierten Adresse Über egress_ip_blocklist_enabled (Standard true, nftables) wird nur die registrierte Adresse blockiert; der Datenverkehr zu einem nicht gelisteten Host bleibt unberührt (keine pauschale Sperre)
PENT-S4 FIM-Manipulationsangriff Hintertür-Nutzlast in /bin/login einschleusen Die SHA-256-Critical-Path-FIM erkennt die Manipulation sofort. Nach einer legitimen Wiederherstellung synchronisiert sich die Basislinie korrekt neu
PENT-S5 Schweregradbasierte Eindämmung via guard.yaml Ein Falco-Critical-Ereignis eingespeist, das auf einen echten Prozess verweist Mit on_critical: isolate_process + kill_process wird der betroffene Prozess netzwerkseitig isoliert und anschließend mit SIGKILL beendet
PENT-S6 Schutzmechanismus für geschützte Prozesse Ein Ereignis gleicher Art eingespeist, das auf die echte sshd-PID verweist Dank der Liste geschützter Prozesse (sshd / systemd / Container-Runtimes usw.) läuft sshd weiter; es wird lediglich eine Ablehnung als Fehlalarm protokolliert
PENT-S7 Sicherheitstimer Einen Air-Gap-Vorfall unbestätigt gelassen (keine Bediener-ACK) Mit safety_timer_secs erfolgt bei ausbleibender Antwort eine automatische Wiederherstellung; nach einem ACK bleibt die Isolation bis zu emergency-restore bestehen
PENT-S8 Kernel-LPE-Fragmentlücke unshare -U -r als unprivilegierter Benutzer ausführen (auf einer echten VM geprüft) Das ohne das Produkt erlaubte unshare -U -r wird nach dem Start abgelehnt. user.max_user_namespaces und kernel.unprivileged_userns_clone standen auf 0, Yamas ptrace_scope auf 2 und unprivilegiertes eBPF war deaktiviert (2026-09-25, Ubuntu-24.04-VM, geprüft sowohl mit der veröffentlichten v1.10.4 als auch mit dem korrigierten Build)

Hinweis: Der Messwert zu PENT-S7 stammt von v1.3.2. In der aktuellen Version wird eine Isolation durch einen Trigger mit hoher Konfidenz aufgehoben, sobald die Ursache als beseitigt bestätigt ist, und eine vom Betreiber bestätigte (ack) Isolation bleibt bestehen, bis der Betreiber sie aufhebt (ein ignoriertes ack wurde beim erneuten Lauf am 2026-09-25 gefunden und behoben). Trigger mit niedriger Konfidenz erholen sich mit demselben Timer. Siehe §4.

Art der Prüfungen — PENT-S8 bestätigt, dass eine Kernel-Funktion (User-Namespaces verbieten) wirksam ist. PENT-S1 und S2 bestätigen die von RoamSwitch eingerichteten nftables-Regeln; die Pakete verwirft tatsächlich der Kernel. Die Punkte, die die eigene Logik von RoamSwitch prüfen, sind PENT-S3 (Anwendung des Feeds), S4 (FIM), S5 und S6 (Eindämmung und geschützte Prozesse) sowie S7 (Sicherheits-Timer).

SSH-Lockout-Prävention

preserve_ssh_on_isolation=true (Standard) soll den Admin-SSH-Kanal während eines Air-Gap (on_emergency) erhalten. Der erneute Lauf vom 2026-09-25 zeigte jedoch, dass die Isolationsregeln bis 1.10.4 die SSH-Antworten verwarfen und der Betreiber während der Isolation ausgesperrt war; die frühere Prüfung war erst nach Aufhebung der Isolation erfolgreich. In 1.10.5 wurde dies behoben; bei fortbestehender Ursache der Isolation wurde geprüft, dass SSH während der Isolation funktioniert.

Grenzen des Prüfumfangs (eine ehrliche Offenlegung)

Was hiermit nicht überprüft werden kann

Kernel-Härtung (Deaktivierung unprivilegierter User-Namespaces, Anheben von Yamas ptrace_scope) lässt sich nicht vollständig aus einem Container heraus verifizieren. Da diese Sysctls nicht pro Container in einem eigenen Namespace liegen, wirken sich Schreibvorgänge aus einem privilegierten Container (--privileged) nicht auf eine Sandbox, sondern auf die reale Maschine, auf der der Test läuft, aus. Diese Prüfung bestätigt daher nur, dass der Sysctl-Schreibvorgang bei einem schreibgeschützten Dateisystem sauber und ohne Absturz fehlschlägt; ob der Wert tatsächlich greift, muss auf einer echten Maschine oder VM überprüft werden, wie sie für den Betrieb des Produkts vorgesehen ist. Diese Bestätigung wurde am 2026-09-25 einmalig auf einer Ubuntu-24.04-VM durchgeführt (siehe die Zeile PENT-S8).

Selbst nachvollziehen

Alle oben genannten Ergebnisse lassen sich über die im offiziellen Support-Repository (roamswitch-support) veröffentlichte Docker-Testsuite allein mit dem offiziellen Verteilungspaket zu 100 % auf Ihrer eigenen Maschine nachvollziehen (kein Zugriff auf den Quellcode und kein Vertrauensvorschuss uns gegenüber erforderlich).

# Testsuite abrufen und reproduzieren (installiert roamswitch-server automatisch aus dem offiziellen APT-Repository)
git clone https://github.com/lafine1211/roamswitch-support.git
cd roamswitch-support/test/docker/server
./run.sh

Erstellt drei Wegwerf-Container (Target, Attacker und ein C2-Köder) im Standard-Bridge-Netzwerk von Docker und verifiziert automatisch alle 18 Punkte, wobei ein Bericht ausgegeben wird. Die vollständige Ausgabe des Laufs mit v1.3.2 ist veröffentlicht unter RESULTS-PENTEST-SERVER-2026-09-07.ja.md (einschließlich, aus Gründen der Transparenz, der beim Aufbau gefundenen und behobenen Probleme im Testaufbau selbst). Die Aufzeichnung des erneuten Laufs vom 2026-09-25 finden Sie in RESULTS-PENTEST-2026-09-25.ja.md.

§7Betrieb, Bereitstellung und Lebenszyklus

7.1 Headless CUI Tooling & Setup Wizard

Vollständige Fernverwaltung über CLI:

  • roamswitch server status: Vollständige 34-Check-Diagnoseausgabe (10 Sprachen, entsprechend der Einstellung des aufrufenden Benutzers oder der Locale des Betriebssystems).
  • roamswitch server setup: Interaktiver Terminal-Assistent für Ports und Benachrichtigungen.
  • roamswitch server config show / set <key> <val>: Skriptfähige Automatisierung für Ansible/Terraform.
  • roamswitch server test-notify [all|telegram|line|webhook]: End-to-End-Benachrichtigungssonde.
  • roamswitch server config set language <ja|en|zh-Hans|zh-Hant|ko|de|fr|es|it|pt|system>: die Sprache des periodischen Diagnoseberichts des Daemons (stündlich) und der Push-Benachrichtigungen (Telegram / LINE / Webhook, einschließlich der Testnachricht), eine Sprache pro Host. system folgt der Betriebssystem-Locale; eine nicht erkennbare Locale ergibt ja. Die Anzeigesprache von roamswitch server status folgt nicht dieser Einstellung, sondern der Einstellung des aufrufenden Benutzers oder der Locale des Betriebssystems.
  • roamswitch server bans [--json] / sudo roamswitch server unban <IP|IPv6-/64|--all>: Zustand des SSH-Brute-Force-Schutzes sowie Anzeigen und Aufheben seiner Sperren. Das MCP-Tool get_ssh_guard_incidents ist schreibgeschützt und kann keine Sperre aufheben.

Server-TUI (roamswitch server tui)

Eine Terminal-Oberfläche, mit der sich die gesamte Server Edition über SSH, in 80x24 und allein per Tastatur bedienen lässt (roamswitch server tui oder roamswitch-server-tui). Sie hat 11 Bildschirme: Dashboard, Schutz, Vorfälle, Benachrichtigungen und Weiterleitung, Sensor, Konfiguration, Dienst, Werkzeuge, Log-Audit, Info und Hilfe sowie Fleet. Der Konfigurationseditor wird aus den Schlüsseldefinitionen (dem Schema) von server.conf und guard.yaml erzeugt: Er prüft Typ, Bereich und Aufzählungswerte, zeigt an, ob ein Neustart nötig ist, zeigt vor dem Speichern einen Diff und speichert mit zeitgestempeltem Backup und atomarem Schreiben (geheime Werte wie Token werden maskiert und ohne Echo eingegeben). Folgenschwere Aktionen wie das Wiederherstellen einer Isolation, ACK, das Aktualisieren der FIM-Basislinie und das Stoppen des Dienstes zeigen einen Bestätigungsbildschirm mit der Wirkung; die folgenreichsten verlangen die Eingabe von yes (getippte Bestätigung). Ohne Root ist sie schreibgeschützt und nennt den benötigten sudo roamswitch ...-Befehl. Ein Neuladen der Konfiguration (Reload) gibt es nicht; für die Übernahme ist ein Neustart des Dienstes nötig. Die Anzeige unterstützt 10 Sprachen.

7.2 Verpackung

Wird über .deb-Pakete für Debian / Ubuntu sowie .rpm-Pakete für RHEL / Fedora und für openSUSE bereitgestellt.

§8Fazit

RoamSwitch Server Edition bietet Cloud- und Enterprise-Linux-Infrastrukturen in einem einzigen integrierten Paket „Zero Telemetry (die einzige standardmäßige externe Kommunikation ist der abschaltbare, rein empfangende Abruf signierter Daten)“, „starken Perimeterschutz durch eingehendes Default-Deny“, „sofortige Erkennung von Manipulationen an kritischen Pfaden“ und „präventive Blockierung von Kernel-Rechteausweitung“.

Eine Sicherheits-Suite für Linux-Server, die mehrstufige Erkennung mit autonomer Eindämmung (Air-Gap) für die wichtigsten Angriffsphasen kombiniert: Erstaufklärung, Eindringen, Rechteausweitung und Persistenz.

Dieses Dokument spiegelt den Implementierungsstand von RoamSwitch Server Edition v1.11.1 wider (eingehendes Default-Deny, Critical-Path-FIM, die guard.yaml-Richtlinien-Engine, Kernel-LPE-Härtung, eBPF-Laufzeitüberwachung, gestufte Air-Gap-Aufhebung, Ausführungsrekorder und Ereignisweiterleitung, die Server-TUI, DNS-Tunneling-Erkennung, Honeytokens, forensische Beweissicherung, NIST-CSF-/CIS-Controls-Zuordnung sowie signierte Aktualisierungen der Kernel-CVE-Map). Die Messwerte des Selbsttests in §6 stammen jedoch von v1.3.2 (2026-09-07) und von einem aus dem 1.10-Quellcode gebauten Paket (2026-09-25). Eine Änderungshistorie pro Eintrag finden Sie im CHANGELOG von roamswitch-support. Aktuelle Informationen finden Sie unter roamswitch.com/linux.