Initial commit - Hetzner SecMon

This commit is contained in:
jhummel committed 2026-10-31 14:25:27 +00:00
commit b313c3c2b6
3 files changed
+559

No files matched your search

+159
View File
@@ -0,0 +1,159 @@
# Hetzner Secmon – Projektbezogenes Security-Monitoring mit n8n
> Überwachung sicherheitsrelevanter Änderungen in Hetzner-Cloud-Projekten, mit Zustandsvergleich und Gotify-Alarmierung.
![Hetzner SecMon – Security-Monitoring mit n8n](pictures/Hetzner-SecMon.webp)
## Warum ich dieses Projekt gebaut habe
Ausgangspunkt war ein konkreter Sicherheitsvorfall in meiner Hetzner-Cloud-Umgebung: Ein Angreifer hatte Zugriff auf einen API-Token erlangt. In der anschließenden Untersuchung musste ich Aktivitäten nachvollziehen und betroffene Server absichern. Dabei wurde deutlich, dass die reine nachträgliche Kontrolle über die Hetzner-Konsole für meine Anforderungen nicht ausreicht.
Ich wollte insbesondere wissen, **wann in einem Projekt ein Server neu gestartet, abgeschaltet, neu installiert oder in den Rescue-Modus versetzt wird**, ob **Firewall-Regeln beziehungsweise Zuweisungen verändert** werden und ob jemand **SSH-Schlüssel hinzufügt, entfernt oder modifiziert**. Diese Ereignisse können legitime Administrationsarbeiten sein – aber auch Indikatoren für einen unberechtigten Zugriff.
Deshalb habe ich einen eigenständigen Monitor mit **n8n**, der über die Hetzner Cloud API regelmäßig den aktuellen Zustand abfragt, Veränderungen erkennt und mir über **Gotify** meldet. Die Überwachung wird je Hetzner-Projekt beziehungsweise Umgebung mit entsprechendem API-Zugang betrieben. Wichtig war mir dabei nicht nur die Erkennung, sondern auch, dass Benachrichtigungen bei vorübergehenden Zustellproblemen nicht sofort verloren gehen.
**Grundgedanke:** Sicherheitsrelevante Änderungen sollen mir zeitnah auffallen, statt erst bei einer späteren manuellen Kontrolle.
## Funktionsübersicht
| Bereich | Erkennung / Verhalten |
|---|---|
| Serveraktionen | Neustart, Reset, Ein-/Ausschalten, Herunterfahren, Rescue-Modus, Remote-Konsole, Rebuild, Root-Passwort-Reset, Schutzänderung, Image-Erstellung und ISO-Mount/-Unmount |
| Firewalls | Neue/gelöschte Firewalls, geänderte Regeln, Server-/Label-Zuweisungen und Umbenennungen |
| SSH-Schlüssel | Neue/gelöschte Keys, Änderungen an Namen, Fingerprint, Public Key oder Labels |
| Benachrichtigungen | Gotify-Nachrichten mit Ereignisdetails und Priorität |
| Zustellung | Outbox mit erneutem Versand bis zur Bestätigung, innerhalb definierter Grenzen |
| Fehler | Separater Pfad zur Gotify-Fehlermeldung, sofern korrekt als Error Workflow konfiguriert |
## Architektur
```text
Schedule Trigger
|
v
Hetzner API: Serveraktionen
|
v
Hetzner API: Serverliste
|
v
Hetzner API: Firewalls
|
v
Hetzner API: SSH-Keys
|
v
Änderungen erkennen
| (n8n Workflow Static Data:
| Snapshots + gesehene Aktionen + Outbox)
v
Gotify Warnung
|
v
Zustellung bestätigen
Error Trigger -> Fehler formatieren -> Gotify Fehler
```
Der Workflow ist im exportierten Zustand **aktiv**. Die API-Aufrufe laufen nacheinander und verwenden HTTP Bearer Authentication über n8n-Credentials. HTTP-Timeout: jeweils 10 Sekunden; für die API-Abfragen sind zwei Versuche konfiguriert. Die Gotify-Requests haben maximal drei Versuche.
## So funktioniert die Erkennung
### 1. Serveraktionen
Der Workflow fragt `GET /v1/servers/actions` mit `per_page=50` und absteigender Action-ID ab. IDs bereits bekannter Aktionen werden in `state.seen` gehalten (maximal 1.000). Neue Aktionen mit einem im Code bekannten Kommando erzeugen einen Alarm. Die Serverliste dient dabei zur Zuordnung von IDs zu Servernamen.
Besonders hoch priorisiert sind Aktionen im Zusammenhang mit Rescue, Konsole, Passwort, Rebuild, Image-Erstellung und ISO-Einhängen.
**Hinweis:** Beim ersten Lauf werden vorhandene Action-IDs nur als Ausgangszustand gespeichert. Es werden dafür keine rückwirkenden Benachrichtigungen erstellt. Wenn alle 50 eingelesenen Aktionen neu sind, gibt es einen zusätzlichen Warnhinweis auf mögliche Lücken.
### 2. Firewall-Überwachung
Die aktuelle Firewall-Konfiguration wird normalisiert und als Snapshot gespeichert. Hierbei werden Regeln und Zuweisungen unabhängig von ihrer Listenreihenfolge verglichen. Daraus lassen sich unter anderem folgende Änderungen erkennen:
- Neue oder gelöschte Firewall
- Hinzugefügte oder entfernte Firewall-Regel
- Geänderte Regelparameter wie Richtung, Protokoll, Port, Quell-/Ziel-IP oder Beschreibung
- Geänderte Zuordnung zu Servern oder Label-Selektoren
- Umbenennung einer Firewall
Änderungen werden in einer Alarmmeldung mit den jeweils erkannten Differenzen ausgegeben. Der erste Lauf erstellt nur die Vergleichsbasis.
### 3. SSH-Key-Überwachung
Der Workflow speichert je SSH-Key-ID Name, Fingerprint, öffentlichen Schlüssel, Labels und Erstellungszeitpunkt. Er meldet neu angelegte, gelöschte oder veränderte Keys. Auch hier erzeugt der Initiallauf zunächst einen Snapshot ohne Änderungsalarm.
### 4. Outbox und Zustellbestätigung
Neue Alarme werden zunächst in `state.outbox` gespeichert. Bei jedem Lauf werden die noch ausstehenden Alarme erneut an Gotify übergeben. Erst der Node **„Zustellung bestätigen“** entfernt Einträge, die über den erfolgreichen Gotify-Ausgang gelaufen sind.
Dieses Muster nähert eine *At-least-once-Zustellung* an: Bei zeitweiligen Übertragungsfehlern können Meldungen wiederholt werden. Eine garantierte einmalige Zustellung gibt es nicht; Duplikate sind möglich. Außerdem gelten ausdrücklich Grenzen: maximal 200 Outbox-Einträge und maximal 1.440 Ausgabeversuche pro Eintrag. Danach können Alarme verworfen werden.
### 5. Workflow-Fehler
Der separate Pfad `Error Trigger -> Fehler formatieren -> Gotify Fehler` erstellt Fehlermeldungen mit Node, Fehlermeldung und Ausführungsreferenz. Identische Fehler werden anhand von Workflow, Node und Meldung für 15 Minuten gedrosselt.
**Wichtig:** Ein Error Trigger allein stellt noch nicht sicher, dass Fehler dieses Workflows an diesen Pfad gelangen. Die n8n-Error-Workflow-Konfiguration und die tatsächliche Funktion müssen separat überprüft werden.
## Installation und Konfiguration
1. Die Workflow-JSON in n8n importieren.
2. Ein Hetzner Cloud API-Credential vom Typ **HTTP Bearer Auth** für das zu überwachende Projekt hinterlegen und den vier Hetzner-HTTP-Nodes zuweisen. Der Token benötigt Lesezugriff auf die betroffenen Ressourcen; die konkret passenden Berechtigungen sind in Hetzner zu prüfen.
3. Ein Gotify-Credential für die beiden Benachrichtigungs-Nodes konfigurieren und die Gotify-Server-URL auf die eigene Umgebung anpassen.
4. Den Schedule prüfen und das gewünschte Intervall festlegen.
5. Den Workflow einmal ausführen, damit die Ausgangssnapshots erstellt werden.
6. Danach kontrollierte Teständerungen in Hetzner auslösen: beispielsweise eine Firewall-Regel ändern, einen Test-SSH-Key anlegen und eine Serveraktion durchführen. Prüfen, ob die Meldungen tatsächlich ankommen.
7. Fehlerpfad und Verhalten bei vorübergehend unerreichbarem Gotify gezielt testen.
**Mehrere Projekte:** Die Hetzner Cloud API liefert projektbezogene Daten. Für eine getrennte Überwachung verschiedener Umgebungen können separate Workflow-Instanzen mit jeweils passendem Projekt-Credential betrieben werden. Credentials und Zustände dürfen dabei nicht versehentlich zwischen Projekten vermischt werden.
## Datenhaltung
Die Implementierung verwendet **n8n Workflow Static Data** (`$getWorkflowStaticData('global')`). Darin werden unter anderem gespeichert:
- Bereits bekannte Server-Action-IDs
- Firewall-Snapshot
- SSH-Key-Snapshot
- Outbox mit Alarm-ID, Titel, Nachricht, Priorität, Erstellungszeitpunkt und Anzahl der Versuche
- Zeitpunkte für die Drosselung wiederholter Workflow-Fehler
Eine externe Datenbank oder n8n Data Table wird im bereitgestellten Export **nicht** verwendet. Die gespeicherten Werte dienen zum Vergleich zwischen Workflow-Ausführungen. Ein verlässlicher Betrieb setzt voraus, dass Static Data erhalten bleibt und Workflow-Ausführungen nicht unkontrolliert parallel laufen.
## Aktuelle Grenzen und wichtige Prüfungen
Diese Punkte sind keine theoretische Funktionsbeschreibung, sondern ergeben sich aus dem vorliegenden Workflow-Export:
1. **Intervall:** Der Trigger heißt „Alle 5 Minuten“, seine Regel lautet aber lediglich `field: minutes` ohne expliziten Wert `5`. In n8n ist damit typischerweise ein einminütiger Rhythmus gemeint. Das tatsächliche Intervall muss im Editor geprüft werden. Auch die Code-Kommentare gehen von einer Minute aus.
2. **API-Paginierung:** Serveraktionen werden mit maximal 50 Ergebnissen pro Abruf eingelesen; weitere Seiten werden nicht nachgeladen. Bei hoher Aktivität können Ereignisse außerhalb dieses Fensters fehlen. Für Firewalls und SSH-Keys wird bei erkennbar unvollständiger Paginierung abgebrochen; Serverlisten werden nicht vollständigkeitsgeprüft.
3. **Zeitverzögerung:** Das Verfahren ist Polling, keine Echtzeit-Eventübertragung. Änderungen zwischen zwei Abfragen können unentdeckt bleiben, insbesondere wenn sie vor der nächsten Abfrage wieder rückgängig gemacht wurden.
4. **Outbox-Begrenzung:** Die maximale Länge von 200 Alarmen und die Grenze von 1.440 Versuchen können bei längerem Ausfall zu Verlust führen. „At least once“ ist deshalb keine uneingeschränkte Garantie.
5. **Keine revisionssichere Historie:** Die Static Data stellen keine manipulationssicheren Audit-Logs dar. Es gibt im Export auch keine dauerhaft gespeicherte Ereignishistorie außerhalb der aktuellen Zustände.
6. **Kein Nachweis der Ursache:** Eine API-Aktion belegt nicht automatisch einen Angriff. Die Auswertung identifiziert weder sicher die handelnde Person noch eindeutig, ob eine Aktion legitim war.
7. **Fehlerüberwachung:** Ein Ausfall von n8n selbst oder seiner Infrastruktur kann auch den Alarmweg verhindern. Der separate Error-Trigger-Pfad ist entsprechend zu prüfen.
8. **Zustelllogik:** Zu testen ist, ob die Zuordnung der erfolgreichen Gotify-Items zu ihren ursprünglichen `alertId`-Werten bei Teilfehlern und mehreren gleichzeitigen Alarmen zuverlässig funktioniert.
## Sicherheitsmaßnahmen
- Hetzner-Token **niemals im README oder in Git hinterlegen**; nur n8n-Credentials verwenden.
- Token möglichst mit minimal notwendigen Rechten und getrennt pro Projekt führen.
- n8n, Gotify und ihre Zugangsdaten gegen unberechtigten Zugriff absichern.
- Änderungen durch kontrollierte Tests regelmäßig verifizieren; besonders Firewall- und SSH-Key-Änderungen.
- Für höhere Verlässlichkeit einen dauerhaften Ereignisspeicher, Monitoring der letzten erfolgreichen Ausführung und einen unabhängigen Alarmweg ergänzen.
- Bei Verdacht auf Token-Kompromittierung die betroffenen Zugangsdaten widerrufen/rotieren und die Hetzner-Aktivitäten unabhängig untersuchen.
## Geplanter Ausbau
- Vollständige API-Paginierung für alle relevanten Ressourcen
- Dauerhafte Historie und differenzierter Zustandsvergleich in einer Datenbank beziehungsweise n8n Data Tables
- Überwachung des letzten erfolgreichen Pollings (Heartbeat/Dead-Man-Switch)
- Tests für Zustellfehler, gleichzeitige Änderungen und Wiederanlauf
- Optional zweiter Alarmkanal unabhängig von Gotify
- Vereinheitlichte Auswertung mehrerer Projekte in einer zentralen Übersicht
## Einordnung
**Hetzner Secmon ist eine zusätzliche Detektions- und Alarmierungsschicht, kein Ersatz für Hetzners eigene Protokolle, restriktive Berechtigungen, Backups oder Incident Response.** Das Projekt entstand aus einem realen Sicherheitsbedarf und verfolgt einen pragmatischen Ansatz: vorhandene APIs und selbst betriebene Infrastruktur nutzen, Änderungen sichtbar machen und den manuellen Kontrollaufwand reduzieren.
## Technischer Stand
Dokumentiert anhand des bereitgestellten n8n-Exports `Hetzner-Secmon-Produktion.json` vom 31. Oktober 2026. Die README beschreibt die implementierten Funktionen sowie die aus dem Code erkennbaren Grenzen; sie bestätigt keine erfolgreich durchgeführten End-to-End-Tests.