README and all guides under docs/ are now in German, with German anchors for the cross references. Code and configuration blocks are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
152 lines
6.6 KiB
Markdown
152 lines
6.6 KiB
Markdown
# Betrieb
|
||
|
||
Alle Befehle im Verzeichnis mit der `docker-compose.yaml` ausführen (z. B. `/opt/fail2ban-webui`).
|
||
|
||
## Status und Logs
|
||
|
||
```bash
|
||
docker compose ps # Up … (healthy)
|
||
docker compose logs --tail 100 fail2ban-webui
|
||
docker compose logs -f fail2ban-webui | grep -E 'AUDIT|LOGIN|ERROR|WARNING'
|
||
docker compose run --rm fail2ban-webui check # jeder Agent erreichbar?
|
||
```
|
||
|
||
Wichtige Logzeilen:
|
||
|
||
| Zeile | Bedeutung |
|
||
|---|---|
|
||
| `fail2ban-webui 1.0.0 – hosts: … – auth: … – loki: … – geoip: …` | Zusammenfassung beim Start |
|
||
| `AUDIT {…}` | Sperren/Entsperren mit Benutzer, Client-IP, Hosts und Ergebnis |
|
||
| `LOGIN_OK` / `LOGIN_FAILED` / `LOGIN_LOCKED` / `LOGOUT` | Anmeldeereignisse |
|
||
| `OIDC_FAILED` / `OIDC_DENIED` | SSO-Fehler / Konto nicht zugelassen |
|
||
|
||
Das Protokoll liegt zusätzlich in `data/audit.log` (ein JSON-Objekt pro Zeile):
|
||
|
||
```bash
|
||
tail -n 20 data/audit.log | python3 -m json.tool --json-lines
|
||
```
|
||
|
||
Auf den Hosts steht jede Agent-Aktion im Syslog:
|
||
|
||
```bash
|
||
journalctl -t f2b-webctl --since today
|
||
```
|
||
|
||
## Update
|
||
|
||
```bash
|
||
cp -a .env docker-compose.yaml config /backups/fail2ban-webui_$(date +%F)/ # oder dein Backup-Ort
|
||
docker compose pull
|
||
docker compose up -d
|
||
docker compose ps
|
||
docker compose run --rm fail2ban-webui check
|
||
```
|
||
|
||
Vorher das [Changelog](../CHANGELOG.md) lesen – nennt es eine neue Agent-Version, auch die
|
||
Agenten aktualisieren (`install.sh` mit denselben Optionen erneut ausführen, siehe
|
||
[agent.md](agent.md#aktualisieren)). Der Tag `1` bewegt sich nur innerhalb von 1.x;
|
||
inkompatible Änderungen bekommen eine neue Hauptversion.
|
||
|
||
Auch ohne neue Funktionen regelmäßig neu ziehen bzw. bauen: Das Image wird mit aktuellen
|
||
Debian-Sicherheitsupdates neu gebaut.
|
||
|
||
## Backup
|
||
|
||
| Was | Warum |
|
||
|---|---|
|
||
| `.env` | Einstellungen, Passwort-Hash, OIDC-Secret |
|
||
| `config/hosts.yaml` | Hostliste |
|
||
| `data/ssh/` | privater Schlüssel und festgelegte Host-Schlüssel – ohne sie braucht jeder Agent den neuen Schlüssel |
|
||
| `data/audit.log` | Protokoll |
|
||
| `data/secret_key` | hält nur Sitzungen gültig; geht er verloren, werden alle abgemeldet |
|
||
|
||
`data/geoip/` wird automatisch neu heruntergeladen.
|
||
|
||
```bash
|
||
tar -cpzf /backups/fail2ban-webui_$(date +%F_%H-%M).tar.gz .env docker-compose.yaml config data
|
||
sha256sum /backups/fail2ban-webui_*.tar.gz | tail -n1
|
||
```
|
||
|
||
Das Archiv enthält den privaten SSH-Schlüssel – entsprechend sicher aufbewahren.
|
||
|
||
## Umzug auf einen anderen Host
|
||
|
||
1. Auf dem alten Host `docker compose stop`, Archiv wie oben erstellen.
|
||
2. Kopieren, mit `tar -xpzf` entpacken (behält Besitzer 10050 und Rechte).
|
||
3. Auf **jedem Agenten** die neue Adresse in `from=` aufnehmen – am einfachsten
|
||
`install.sh … --from <neue Adresse>` erneut ausführen.
|
||
4. `docker compose up -d`, danach `check`.
|
||
|
||
## SSH-Schlüssel tauschen
|
||
|
||
```bash
|
||
docker compose run --rm fail2ban-webui keygen --force
|
||
# auf jedem Host:
|
||
bash install.sh --key-file new.pub --from … (dieselben Optionen wie zuvor)
|
||
```
|
||
|
||
Der Installer ersetzt nur Einträge mit demselben Schlüssel; den alten vorher mit
|
||
`uninstall.sh` entfernen oder seine Zeile aus `authorized_keys` löschen (sie enthält
|
||
`command="…f2b-webctl"`).
|
||
|
||
## Login mit fail2ban absichern
|
||
|
||
Die Oberfläche sperrt einen Client nach 5 Fehlversuchen selbst. Um hartnäckige Angreifer an
|
||
der Firewall zu sperren, liest fail2ban auf dem **Proxy-Host** das Container-Log.
|
||
|
||
`/etc/fail2ban/filter.d/fail2ban-webui.conf`
|
||
|
||
```ini
|
||
[Definition]
|
||
# Docker json-file log: {"log":"… WARNING webui: LOGIN_FAILED user=x ip=203.0.113.7\n",…}
|
||
# user names never contain spaces (they are sanitised), so only the real " ip=" matches
|
||
failregex = LOGIN_FAILED user=\S* ip=<HOST>
|
||
LOGIN_LOCKED ip=<HOST>
|
||
ignoreregex =
|
||
```
|
||
|
||
`/etc/fail2ban/jail.d/fail2ban-webui.local`
|
||
|
||
```ini
|
||
[fail2ban-webui]
|
||
enabled = true
|
||
filter = fail2ban-webui
|
||
backend = polling
|
||
logpath = /var/lib/docker/containers/*/*-json.log
|
||
maxretry = 5
|
||
findtime = 1h
|
||
bantime = 1d
|
||
# the proxy runs in Docker? Then ban in the DOCKER-USER chain:
|
||
# banaction = iptables-allports[chain=DOCKER-USER]
|
||
```
|
||
|
||
```bash
|
||
fail2ban-client reload
|
||
fail2ban-regex /var/lib/docker/containers/*/*-json.log /etc/fail2ban/filter.d/fail2ban-webui.conf
|
||
```
|
||
|
||
Das funktioniert nur, wenn der Container die echte Client-Adresse sieht (`TRUSTED_PROXY_HOPS`
|
||
richtig gesetzt). Benutzernamen werden mit ersetzten Leer- und Steuerzeichen protokolliert;
|
||
ein präparierter Benutzername kann also keine zweite Logzeile einschleusen.
|
||
|
||
## Fehlersuche
|
||
|
||
| Symptom | Ursache / Lösung |
|
||
|---|---|
|
||
| Container beendet sich: `… is not writable for UID 10050` | `chown -R 10050:10050 data` |
|
||
| Container beendet sich: `AUTH_MODE=local needs AUTH_PASSWORD_HASH` | `hash-password` ausführen, Zeile mit einfachen Anführungszeichen einfügen |
|
||
| Container beendet sich: `No hosts configured` | `config/hosts.yaml` fehlt oder ist leer; unter Windows/Docker Desktop: das Laufwerk lässt sich nicht einbinden |
|
||
| Anmeldung scheitert immer, nachdem der Hash eingefügt wurde | einfache Anführungszeichen in der `.env` fehlen – Compose hat die `$`-Teile verschluckt |
|
||
| Alle werden gemeinsam gesperrt / Protokoll zeigt die Proxy-IP | `TRUSTED_PROXY_HOPS` nicht gesetzt |
|
||
| `Host key verification failed` | Host nicht in `known_hosts` oder sein Schlüssel hat sich geändert → `keyscan`, Fingerprints vergleichen |
|
||
| `Permission denied (publickey)` | Schlüssel für diesen Benutzer nicht installiert, falsches `user:` in `hosts.yaml`, falsches `from=` (die Adresse, die der Host sieht!) oder sshd liest diese `authorized_keys`-Datei nicht |
|
||
| `sudo: a password is required` | sudo-Regel fehlt → `install.sh` erneut ausführen |
|
||
| `The agent does not run as root` | Forced-Command ohne `sudo -n` für einen Nicht-root-Benutzer → `install.sh` erneut ausführen |
|
||
| `Timeout talking to …` | Firewall/Port, oder der Host ist langsam – `SSH_TIMEOUT` erhöhen |
|
||
| `The jail manual-block does not exist on this host` | mit `--no-jail` oder einem anderen `--manual-jail` installiert; `MANUAL_JAIL` in `/etc/f2b-webctl.conf` prüfen |
|
||
| Sperren haben keine Start-/Endzeit | fail2ban älter als 0.11 (kein `--with-time`) |
|
||
| Gesperrte IP erreicht trotzdem einen Docker-Dienst | Banaction sperrt nur `INPUT` – siehe [Docker-Hosts](agent.md#docker-hosts) |
|
||
| OIDC: `redirect_uri` passt nicht | Provider muss genau `<PUBLIC_URL>/auth/callback` erlauben |
|
||
| OIDC: `mismatching_state` | Sitzungs-Cookie zwischen Weiterleitung und Callback verloren: Host in `PUBLIC_URL` weicht vom Browser ab, oder `https` ohne `Secure`/Proxy-Header |
|
||
| OIDC: „Konto … darf diese Anwendung nicht verwenden" | Benutzer nicht in `OIDC_ALLOWED_GROUPS`; prüfen, ob der Provider den Claim `groups` mitschickt |
|