first commit

This commit is contained in:
duffyduck
2026-10-07 10:47:30 +02:00
commit 117bb582de
18 changed files with 2060 additions and 0 deletions
+162
View File
@@ -0,0 +1,162 @@
# Wazuh in Docker – Daten per SSH abholen
Wazuh 4.14 (Manager, Indexer, Dashboard) als Single-Node in Docker. Die überwachten Hosts brauchen
**keinen Agent und keine eingehende Verbindung zum Server**. Alles läuft über SSH, das der Server
zu den Hosts aufbaut.
```
┌──────────────────────── Docker ───────────────────────────┐
Host web01 ◄──ssh──┐ │ sshpull.collector ──► /remote-logs/<host>/*.log ──┐ │
Host db01 ◄──ssh──┼─┤ (journalctl -f / tail -F, Reconnect + Resume) │ │
Host ... ◄──ssh──┤ │ ▼ │
│ │ wazuh.manager ◄── <localfile> (Decoder/Regeln) │
└─┤ wazuh-agentlessd: FIM + Befehls-Diffs per ssh │
│ │ filebeat │
│ ▼ │
│ wazuh.indexer ◄── wazuh.dashboard :443 │
└───────────────────────────────────────────────────────────┘
```
## Was pro Host abgeholt wird
| Baustein | Wie | Ergebnis in Wazuh |
|---|---|---|
| `logs: journal` | `journalctl -o json -f` über eine dauerhafte SSH-Verbindung. Nach einem Abbruch geht es per Journal-Cursor lückenlos weiter. | Alle Standard-Decoder/-Regeln (sshd, sudo, PAM, Kernel, …), z. B. Brute-Force-Erkennung |
| `logs: file` | `tail -F` auf eine Datei. Nach einem Abbruch geht es über Inode und Byte-Offset weiter. | Wie oben, `format` wählbar (`syslog`, `apache`, `json`, `audit`, …) |
| `integrity` | Agentless: Größe, Rechte, Besitzer und SHA256 aller Dateien unter den Pfaden, periodisch. Der Vergleich läuft gegen eine eigene Baseline pro Host. | Alarme bei neuen, geänderten oder gelöschten Dateien (siehe Regeln unten) |
| `commands` | Agentless: Befehle ausführen und die Ausgabe mit dem letzten Lauf vergleichen. | Alarm „agentless: Change detected“ mit Diff (z. B. neuer offener Port, neuer Benutzer) |
| `agent_tunnel` | Optional: Reverse-Tunnel `ssh -R 1514/1515`. Ein echter Wazuh-Agent auf dem Host verbindet sich mit `127.0.0.1`. | Voller Agent-Umfang (SCA, Schwachstellen, Inventar, Echtzeit-FIM) |
Die Agentless-Skripte (`manager/agentless/sshpull_*`) sind eigene Versionen ohne `expect`. Sie
nutzen Schlüssel-Login und optional `sudo -n`. Bei den mitgelieferten Wazuh-Skripten wirkt die
`use_sudo`-Option nicht.
Der Integritätscheck nutzt bewusst **nicht** das FIM-Protokoll von Wazuh. Damit landen alle
Agentless-Hosts in der FIM-Datenbank des Managers, nur nach Pfad geordnet. `/etc/passwd` von
Host A, Host B und vom Manager würde sich gegenseitig überschreiben, und der erste Lauf erzeugt
pro Datei einen „File added“-Alarm. Hier gilt stattdessen: Der erste Lauf legt nur die Baseline
an (ein Alarm), danach werden nur echte Änderungen gemeldet.
### Eigene Regeln (`manager/rules/sshpull_rules.xml`)
| ID | Level | Bedeutung |
|---|---|---|
| 100501 | 3 | FIM-Baseline für einen Host angelegt |
| 100502 | 5 | Datei hinzugefügt |
| 100503 | 7 | Datei geändert (Inhalt, Größe, Rechte oder Besitzer) |
| 100504 | 7 | Datei gelöscht |
| 100505 | 10 | Mehr als 200 Änderungen in einem Lauf: nur eine Zusammenfassung (Update oder Kompromittierung?) |
| 100506 | 10 | Sicherheitskritische Datei (passwd, shadow, sudoers, sshd_config, pam.d, cron, authorized_keys, ld.so.preload) |
| 100507 | 10 | Neue oder geänderte Datei mit SUID/SGID-Bit |
| 100511 | 7 | SSH-Abholung gestört (Log-Stream, Tunnel oder Agentless-Check). Wird nur beim Zustandswechsel gemeldet. |
| 100512 | 3 | SSH-Abholung wieder verbunden |
Befehls-Diffs kommen über die Wazuh-Standardregel 555 („Integrity checksum for agentless
device changed“), mit dem Diff im Alarmtext.
## Installation
Voraussetzungen: Docker und docker-compose, ca. 8 GB RAM frei, ca. 10 GB Platz für Images und
Daten. Für den Indexer:
```bash
echo 'vm.max_map_count=262144' | sudo tee /etc/sysctl.d/99-wazuh.conf && sudo sysctl --system
```
```bash
./setup.sh # Passwörter (.env), TLS-Zertifikate, SSH-Key ssh/id_ed25519, Images bauen
nano hosts.yml # Hosts eintragen (siehe hosts.yml.example)
```
### Zielhosts vorbereiten
Auf jedem Host wird ein Benutzer `wazuh-pull` angelegt. Er bekommt die Gruppen
`systemd-journal` und `adm` (Leserechte auf Logs) und den öffentlichen Schlüssel mit
`restrict` (kein PTY, keine Weiterleitungen):
```bash
./setup.sh host-script | ssh admin@web01 sudo sh
# Optionen: --sudo NOPASSWD-sudo (nur nötig für root-only Dateien, z.B. /etc/shadow im FIM)
# --tunnel erlaubt Reverse-Forwarding auf 127.0.0.1:1514/1515 (für agent_tunnel)
```
Das Skript erst ansehen, dann ausführen: `./setup.sh host-script`
### Host-Keys, Test, Start
```bash
./setup.sh keyscan # Host-Keys -> ssh/known_hosts, Fingerprints mit den Hosts vergleichen!
./setup.sh test # prüft Login, Gruppen, Journal-/Datei-Leserechte
docker-compose up -d
./setup.sh passwords # Login fürs Dashboard: https://<server>/ (admin / ...)
```
Der erste Start dauert 1–3 Minuten, bis der Indexer bereit ist.
### Hosts ändern
`hosts.yml` bearbeiten, dann `./setup.sh apply`. Damit werden Manager und Collector neu
erzeugt. Der Manager schreibt seine Agentless- und Localfile-Konfiguration beim Start aus
`hosts.yml` neu (`manager/generate.py`).
## Wo finde ich die Daten im Dashboard?
Per SSH geholte Logs und Agentless-Ergebnisse laufen **über den Manager**. Im Dashboard
erscheinen sie deshalb beim Agent `000` (`wazuh.manager`). Unterscheiden lassen sich die Hosts
so:
- Logs: `location: /remote-logs/web01/journal.log` oder `predecoder.hostname: web01`
- FIM: `data.sshpull_fim.host: web01`, Befehls-Diffs: `location` enthält `wazuh-pull@web01`
- Verbindungsstatus: `rule.groups: sshpull_status`
Beispiel-Filter in *Threat Hunting*: `rule.groups: sshpull` oder `location:*web01*`
Hinweis: Rohlogs ohne Regeltreffer werden (wie bei Wazuh üblich) nicht indexiert, nur Alerts.
Alles archivieren: in `config/wazuh_cluster/wazuh_manager.conf` `<logall_json>yes</logall_json>`
setzen und in Filebeat das Archiv aktivieren (siehe Wazuh-Doku „archives“).
## Optional: voller Agent über SSH-Tunnel
Wenn auf einem Host ein Wazuh-Agent installiert werden darf, er aber den Server nicht erreicht:
1. In `hosts.yml` beim Host `agent_tunnel: true` setzen. Host mit `--tunnel` vorbereiten.
2. Agent auf dem Host installieren (Paket von packages.wazuh.com, gleiche Version wie der
Manager) mit `WAZUH_MANAGER=127.0.0.1`, bzw. in `ossec.conf` `<address>127.0.0.1</address>`.
3. `./setup.sh apply`. Der Collector hält den Tunnel offen, der Agent registriert sich über
`127.0.0.1:1515` und erscheint als eigener Agent im Dashboard.
Ports 1514 und 1515 sind nicht nach außen veröffentlicht. Nur der Collector erreicht sie.
## Dateien
| Pfad | Zweck |
|---|---|
| `hosts.yml` | Die einzige Stelle für Hosts und Optionen |
| `docker-compose.yml` | Stack. Nach außen geht nur das Dashboard (`DASHBOARD_PORT`) |
| `.env` | Version, Zeitzone, Passwörter (von `setup.sh` erzeugt, nicht committen) |
| `ssh/` | `id_ed25519` (privater Schlüssel, nicht committen), `known_hosts` |
| `common/sshpull_hosts.py` | Laden und Prüfen von `hosts.yml`, SSH-Config erzeugen (Manager und Collector) |
| `collector/` | Log-Streaming-Dienst |
| `manager/` | Manager-Image: openssh-client, Agentless-Skripte, Config-Generator |
| `config/` | Wazuh-Konfiguration (Basis: wazuh/wazuh-docker single-node) |
## Fehlersuche
```bash
docker-compose logs -f sshpull.collector # Verbindungen/Reconnects pro Host
docker-compose exec wazuh.manager grep -i agentless /var/ossec/logs/ossec.log
docker-compose exec wazuh.manager ls -la /remote-logs/web01/ # kommen Logs an?
```
- `journal=WARNUNG:nur-eigene-Logs…` bei `./setup.sh test`: Der Benutzer ist nicht in der
Gruppe `systemd-journal`. Danach neu einloggen bzw. den Collector neu starten.
- `Host key verification failed`: `./setup.sh keyscan` ausführen, oder in `hosts.yml`
`ssh.host_key_checking: accept-new` setzen.
- Agentless-Checks laufen das erste Mal kurz nach dem Start, danach alle `interval` Sekunden.
Der erste Lauf legt nur die Baseline an, Alarme gibt es erst bei Änderungen. Die Checks
laufen nacheinander. Bei vielen Hosts mit großen Pfaden (`/usr`) das `interval` großzügig
wählen.
- Baseline eines Hosts neu anlegen (z. B. nach einem gewollten Update):
`docker-compose exec wazuh.manager rm /var/ossec/agentless/.sshpull/web01.json`
- Ohne `sudo` sind root-only Dateien (z. B. `/etc/shadow`, Host-Keys) nur über Größe, Rechte
und Besitzer überwacht, nicht über den Inhalt.