Zum Inhalt springen

CrowdSec vs. Fail2ban: Botnetze bekämpft man nicht im Alleingang

CrowdSec als moderner Ersatz für Fail2ban — verteilte Server-Abwehr mit Community-Blocklisten.

Wer einen Server mit öffentlicher IP betreibt, kennt das Schauspiel: Innerhalb von Minuten nach dem ersten Hochfahren tauchen die ersten SSH-Versuche in den Logs auf. Fail2ban war jahrelang die Standardantwort darauf, und für einfache Setups ist es das immer noch. Aber sobald man mehr als einen Server hat, einen Reverse-Proxy vorschaltet oder Container betreibt, beginnt das Tool seine Grenzen zu zeigen. Dieser Artikel erklärt, warum das so ist, wie CrowdSec das Problem löst — und worauf man im Betrieb achten muss, was in keinem offiziellen Quickstart steht.

Das Problem mit reaktiver Abwehr

Fail2ban funktioniert nach einem einfachen Prinzip: Log lesen, Schwellwert zählen, IP sperren. Das war lange gut genug. Heute nicht mehr — zumindest nicht alleine.

Moderne Botnetze verteilen ihre Angriffe über hunderte oder tausende IPs. Jede einzelne IP macht vielleicht zwei, drei Loginversuche und ist damit weit unter jedem sinnvollen Schwellwert. Der Bot dreht gemütlich seine Runden, und Fail2ban schaut zu. Dazu kommt: Fail2ban kennt nur, was auf dem eigenen Server passiert ist. Was auf allen anderen Servern weltweit gesehen wird, interessiert ihn nicht.

Parallel dazu hat sich die Infrastruktur verändert. Wer heute mehrere Hosts betreibt (ein paar Docker-Maschinen, ein Proxmox-Hypervisor, Reverse-Proxies), hat schnell ein Dutzend Systeme, die alle einzeln konfiguriert werden müssten. Decisions teilen sie nicht. Sieht einer einen Angreifer, wissen die anderen nichts davon.

Wie CrowdSec das Problem angeht

CrowdSec denkt das ganze Konzept anders. Statt ein Tool zu sein, das Log liest und bannt, ist es eine Plattform mit drei klar getrennten Schichten.

Engine, Parser, Szenarien

Die Engine liest Logquellen (journald, Dateien, Docker-Logs) und schickt die Events durch Parser, die aus Rohtext strukturierte Felder machen. Aus diesen Feldern werden Events, und Events laufen gegen Szenarien: YAML-Regeln, die definieren, was ein Angriffsmuster ist. SSH-Brute-Force, HTTP-Probing, CVE-Scan-Fingerprints — alles als YAML, versioniert, community-gepflegt.

Wird ein Szenario ausgelöst, entsteht eine Decision. Die Decision ist zunächst nur ein Datenbankeintrag. Was damit passiert, entscheidet der Bouncer.

Bouncer — die Durchsetzungsschicht

Bouncer sind eigenständige kleine Prozesse, die die Entscheidungsliste konsumieren und sie in ihrem Kontext durchsetzen. Ein Firewall-Bouncer schreibt iptables- oder nftables-Regeln. Ein Traefik-Plugin-Bouncer antwortet mit 403, Captcha oder einer Ban-Page. Ein nginx-Modul macht das Gleiche auf HTTP-Ebene.

Die Trennung von Detektion und Enforcement ist der Schlüsselpunkt: Dieselbe Decision kann gleichzeitig auf Layer 3 und Layer 7 durchgesetzt werden, von zwei verschiedenen Bouncern, ohne dass die Engine das wissen muss.

LAPI und CAPI

Jede CrowdSec-Instanz hat eine Local API (LAPI) — die ist zunächst nur für den lokalen Bouncer relevant. Für viele Setups reicht das auch schon: Jede Engine meldet sich eigenständig bei der Central API (CAPI) an und pullt ihre Blockliste von dort. Hosts teilen dann zwar keine eigenen Decisions miteinander, bekommen aber die komplette Community-Blockliste — und die deckt den größten Teil der realen Angriffe ab.

Wer zusätzlich will, dass ein lokal erkannter Angreifer sofort auf allen anderen Hosts geblockt wird (ohne auf den nächsten CAPI-Sync zu warten), richtet eine zentrale LAPI ein. Dabei übernimmt eine Maschine den LAPI-Server, alle anderen Engines registrieren sich dort als Clients. Decisions sind dann infrastrukturweit sofort verfügbar. Das lohnt sich, sobald mehrere Hosts dieselbe Angriffsfläche teilen.

Die CAPI ist in beiden Varianten dabei: Sie destilliert aus Millionen weltweit gemeldeter Signale eine gemeinsame Blockliste — mehrere zehntausend aktiv geführte IPs. Eine IP, die irgendwo beim Credential Stuffing erwischt wurde, ist bereits gebannt, bevor sie auf dem eigenen Server den ersten Request stellt.

Fail2ban vs. CrowdSec im Vergleich

DimensionFail2banCrowdSec
Ansatzreaktiv, lokalreaktiv + proaktiv, verteilt
Erkennungregex auf LogdateienParser + Szenarien (YAML)
Enforcementfest verdrahtet (iptables, hosts.deny)separater Bouncer pro Layer
Multi-Hostnicht vorgesehenzentrale LAPI, native Koordination
Global Threat IntelneinCAPI Community-Blocklisten
HTTP-Reaktionennur TCP-DropCaptcha, 403, Ban-Page
ObservabilityLogdateiPrometheus, Web-Konsole, Webhooks

Migration: Fail2ban raus — und zwar richtig

Beide Systeme arbeiten mit iptables. Wenn man sie parallel betreibt, greifen beide in dieselben Chains ein. Das Ergebnis ist schwer vorhersagbares Verhalten und Debugging-Sessions, die keiner braucht. Also: Fail2ban erst komplett entfernen, dann CrowdSec ausrollen.

Wichtig: Fail2ban hinterlässt beim Deinstallieren oft noch seine eigenen iptables-Chains (f2b-*). Die muss man manuell flushen:

systemctl stop fail2ban.service
systemctl disable fail2ban.service
apt purge fail2ban -y

# f2b-Chains prüfen und entfernen
iptables -S | grep -i f2b
iptables -F f2b-sshd 2>/dev/null || true
iptables -X f2b-sshd 2>/dev/null || true

Wer Ansible nutzt: Eine dedizierte Rolle mit crowdsec_remove_fail2ban: true und einem anschließenden Chain-Cleanup-Task ist der sauberste Weg. Den Zwischenzustand ohne Abwehr für ein paar Minuten kann man verschmerzen. Den Zustand mit zwei konkurrierenden Systemen nicht.

Installation: der erste Host

CrowdSec selbst installiert sich über ein offizielles Script, das das passende Debian/Ubuntu-Repo einrichtet:

curl -s https://install.crowdsec.net | sudo sh
sudo apt install crowdsec
sudo systemctl enable --now crowdsec.service

Dann kommt der Firewall-Bouncer — das ist der Teil, der tatsächlich blockt:

sudo apt install crowdsec-firewall-bouncer-iptables

Für Produktivbetrieb lohnt sich Write-Ahead-Logging für die SQLite-Datenbank. Ohne WAL gibt es unter Last Schreibsperren, was sich in Verzögerungen beim Blocken bemerkbar macht. Die offizielle Doku rät dazu explizit:

# /etc/crowdsec/config.yaml
db_config:
  log_level: info
  type: sqlite
  db_path: /var/lib/crowdsec/data/crowdsec.db
  use_wal: true
sudo systemctl restart crowdsec

Zentrale LAPI für mehrere Hosts

Der Standardbetrieb mit LAPI auf Loopback (127.0.0.1:8080) funktioniert für einen einzelnen Host. Sobald man mehrere Maschinen koordinieren will, muss die LAPI auf einem erreichbaren Interface lauschen — und HTTPS sollte dabei Pflicht sein, auch im internen Netz.

Auf dem LAPI-Master in /etc/crowdsec/config.yaml:

api:
  server:
    listen_uri: 0.0.0.0:8443
    tls:
      cert_file: /etc/crowdsec/tls/lapi.pem
      key_file:  /etc/crowdsec/tls/lapi.key

Für die Konsolen-Registrierung (Enrollment) generiert man den Key im eigenen Account unter app.crowdsec.net und führt ihn auf dem Host aus:

CrowdSec-Konsole zeigt den generierten Enrollment-Befehl für eine Security Engine.
Den Enrollment-Key holt man aus der CrowdSec-Konsole — jede Engine bekommt ihren eigenen.
sudo cscli console enroll <ENROLLMENT_KEY>
sudo systemctl restart crowdsec

Nach kurzer Zeit erscheint der Host in der Web-Konsole und muss dort einmalig bestätigt werden:

Bestätigungsdialog für eine neu eingeschriebene CrowdSec Security Engine in der Web-Konsole.
Neuer Host muss in der Konsole einmalig bestätigt oder abgelehnt werden.

Weitere Hosts anbinden

Auf jedem Client-Host registriert man zuerst die Engine beim Master:

# Auf dem Client
sudo cscli lapi register -u https://<LAPI_HOST>:8443 --machine web-01

# Auf dem Master: ausstehende Registrierung bestätigen
sudo cscli machines list
sudo cscli machines validate web-01

Damit der Client nicht mehr seine eigene lokale LAPI nutzt, deaktiviert man den API-Server-Teil in /etc/crowdsec/config.yaml:

api:
  server:
    enable: false

Für den Bouncer auf dem Client muss ein eigener API-Key erstellt und eingetragen werden — Bouncer sprechen direkt mit der LAPI, nicht mit der Engine:

# Auf dem Master
sudo cscli bouncers add web-01-iptables
# /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml auf dem Client
mode: iptables
update_frequency: 10s
api_url: https://<LAPI_HOST>:8443/
api_key: <GENERATED_KEY>
insecure_skip_verify: true   # bei selbstsigniertem Zertifikat
iptables_chains:
  - INPUT
  - DOCKER-USER

Die Konsole zeigt dann alle verbundenen Engines auf einen Blick:

Übersicht mehrerer registrierter CrowdSec Security Engines in der Web-Konsole.
Alle Hosts tauschen Decisions über die zentrale LAPI aus und pullen die CAPI-Blockliste.

Praxis: Was die Docs weglassen

Docker: DOCKER-USER-Chain ist Pflicht

Das ist der häufigste Fehler, den wir bei Docker-Hosts sehen. Ein Firewall-Bouncer, der nur die INPUT-Chain befüllt, schützt Container-Traffic nicht. Docker baut seine eigene Chain DOCKER-USER in die FORWARD-Kette ein — Pakete, die per -p 443:443 in Container weitergeleitet werden, laufen an INPUT vorbei.

Wer das vergisst, hat CrowdSec installiert, sieht, wie Bans angelegt werden — und merkt irgendwann, dass Traffic zu seinen Container-Ports trotzdem durchkommt. Die Konfiguration muss explizit beide Chains einschließen:

iptables_chains:
  - INPUT
  - DOCKER-USER

Layer-3-Drop reicht oft nicht — Reverse-Proxy-Bouncer

Ein iptables-Bouncer kann ein Paket nur verwerfen. Für HTTP-Traffic ist das manchmal zu grob. Hinter einer einzelnen IP kann ein ganzes Firmen-NAT stecken — wenn man die komplett blockt, erwischt man vielleicht auch legitime Nutzer.

Reverse-Proxy-Bouncer (Traefik, nginx, Caddy) können differenzierter reagieren: Captcha einblenden, 403 zurückgeben, in einen Tarpit umleiten. In der Praxis laufen beide parallel: Der Firewall-Bouncer blockt alles, was nie HTTP-Traffic sein sollte (Port-Scanner, SSH-Brute-Force, CVE-Probes auf anderen Ports). Der Proxy-Bouncer übernimmt HTTP-Szenarien wie http-probing oder http-cve.

Whitelist für interne Netze — bevor es jemanden schmerzt

Ohne eine explizite Allowlist für interne Netze ist es eine Frage der Zeit, bis ein aggressiver Monitoring-Job, ein interner Scanner oder ein Deployment-Tool in die Ban-Liste fliegt. Das macht sich meistens zu einem ungünstigen Moment bemerkbar.

# /etc/crowdsec/parsers/s02-enrich/internal-whitelist.yaml
name: my/internal-whitelist
description: "Whitelist interner Netze"
whitelist:
  reason: "internal networks"
  cidrs:
    - 10.0.0.0/8
    - 172.16.0.0/12
    - 192.168.0.0/16
    - 100.64.0.0/10   # Tailscale CG-NAT
sudo systemctl reload crowdsec

Alerting: nicht auf die Konsole verlassen

Die Web-Konsole ist praktisch für einen Überblick, aber man schaut nicht permanent rein. Sinnvoller ist ein Webhook, der Ban-Events in einen Chat-Kanal oder ein Ticketsystem weiterleitet. CrowdSec bringt ein HTTP-Notification-Plugin mit:

# /etc/crowdsec/notifications/http.yaml
type: http
name: chat-webhook
format: |
  { "text": "Ban: {{ .Source.IP }} | {{ .Scenario }} | {{ .Machine }}" }
url: https://chat.example.com/hooks/<TOKEN>
method: POST
group_wait: 30s
group_threshold: 10

Das group_threshold ist wichtig — wenn die CAPI-Blockliste initial synchronisiert wird, können das tausende Events auf einmal sein. Ohne Batching wird jedes einzelne gemeldet.

Prometheus-Metriken gibt es out of the box unter 127.0.0.1:6060 — gut genug, um in ein bestehendes Grafana-Dashboard einzubinden.

Was CrowdSec erkennt

Die Standard-Collections sind umfangreicher als man anfangs vermutet. Relevant für die meisten Setups:

  • crowdsecurity/sshd — SSH-Brute-Force, auch „low and slow"-Varianten über große Zeitfenster
  • crowdsecurity/http-cve — Aufrufe bekannter Exploit-URLs, CVE-Fingerprints in HTTP-Requests
  • crowdsecurity/base-http-scenarios — generisches HTTP-Probing, Scanner-Verhalten
  • crowdsecurity/postfix — SASL-Brute-Force, Relay-Checks
  • fulljackz/proxmox — für Hypervisoren mit Proxmox-Web-UI

Collections sind versioniert und kommen vom Hub. Updates zieht man mit cscli hub upgrade — das ist kein einmaliger Akt, sondern laufende Pflege, ähnlich wie apt upgrade für die Detection-Logik.

Wann Fail2ban noch die richtige Wahl ist

Fail2ban ist nicht tot. Für einen einzelnen, wenig exponierten Server (etwa einen privaten Mailserver oder ein Homelab-System hinter VPN) ist Fail2ban schneller aufgesetzt, hat weniger bewegliche Teile und braucht keine externe Anbindung. Der Community-Effekt spielt bei einem einzigen Host kaum eine Rolle.

Der Punkt, an dem CrowdSec mehr Sinn ergibt, ist klar: Sobald man mehrere Hosts koordinieren will, einen Reverse-Proxy betreibt oder HTTP-Endpunkte öffentlich macht. Ab da wird CrowdSec nicht komplizierter — es wird einfacher, weil man Decisions nur noch an einer Stelle pflegen muss.

Fazit

Die Bedrohungslage ist verteilt, die Abwehr muss nachziehen. CrowdSec liefert dafür eine Architektur, die das Problem nicht mit mehr Regeln, sondern mit einem anderen Ansatz löst: getrennte Detektion und Enforcement, eine zentrale LAPI als Koordinationspunkt, Community-Blocklisten als Netzwerk-Effekt.

Wer eine Flotte aus mehreren Hosts, Container-Maschinen und Reverse-Proxies betreibt, bekommt damit heute eine Abwehr, die sich skaliert und laufend aktuell hält — ohne dass man für jeden neuen Host die Konfiguration von Hand replizieren muss.

Häufige Fragen

Migration von Fail2ban auf CrowdSec, Multi-Host-Setup, Ansible-Integration, Alerting — professionell aufgesetzt, ohne sich durch alle Fallstricke selbst durchzubeißen.

Jetzt anfragen

Vereinbaren Sie direkt einen Termin

In 30 Minuten zeigen wir Ihnen unverbindlich, was wir für Ihre IT, Ihre Webseite oder Ihre Praxis-Infrastruktur tun können — Telefon, Videocall oder direkt bei uns in Herne.

Besser digital. Einfach hisys.
RECHTLICHE HINWEISE & RICHTLINIEN
Impressum
Datenschutzerklärung
Barrierefreiheitserklärung
AGB
ADRESSE
HomeIT-System
Thusinthan Kajendran
Schichtmeisterweg 2
44625 Herne
KONTAKT
© 2024 - 2026 HomeIT-System.