Three-Layer Brute-Force Protection System
Three-Layer Brute-Force Protection System für matzka.cloud
Inhaltsverzeichnis
Einführung
Sicherheit ist ein kritischer Aspekt jeder modernen Cloud-Infrastruktur. Bei matzka.cloud betreiben wir elf verschiedene Dienste mit Authentifizierungsendpunkten, die potentiell anfällig für Brute-Force-Angriffe sind.
Die Anforderung war klar: Ein umfassendes Schutzsystem implementieren, das Angreifer erkennt und blockiert, ohne legitime Benutzer zu behindern.
Die Herausforderung
Ausgangslage
Vor dieser Implementierung hatten wir:
- ✅ Fail2ban für SSH-Schutz
- ✅ Wazuh SIEM für Sicherheitsüberwachung
- ✅ Traefik als Reverse Proxy
- ❌ Keine Web-Service Brute-Force Protection
- ❌ Keine Koordination zwischen Systemen
- ❌ Keine automatische IP-Blockierung für Web-Services
Anforderungen
- Multi-Layer Defence: Angreifer auf mehreren Ebenen blockieren
- Automatisierung: Keine manuellen Eingriffe nötig
- Transparenz: Email-Benachrichtigungen für alle Blöcke
- Keine False Positives: Legitime Benutzer nicht behindern
- SSO-Kompatibilität: OAuth/OIDC-Flows müssen funktionieren
Architektur: Drei Schichten
Das System arbeitet auf drei verschiedenen Ebenen:
Wie es funktioniert
- Request kommt an → Traefik Rate Limiter überprüft
- Rate Limit überschritten? → HTTP 429 (zu viele Anfragen)
- Failed Login Attempt → Traefik loggt in access.log (JSON)
- Fail2ban liest Log → Erkennt fehlgeschlagene Logins
- 5 Versuche in 10 Min? → IP wird blockiert (iptables)
- Wazuh erkennt Muster → Zusätzliches firewall-drop Command
- IP-Blockade → 1-2 Stunden (je nach Service)
- Email-Alert → Admin wird benachrichtigt
Schicht 1: Fail2ban
JSON-basierte Log-Analyse
Traefik gibt Logs im JSON-Format aus. Dies erforderte eine spezielle Regex:
# Filter: /etc/fail2ban/filter.d/matzka-bruteforce.conf
[Definition]
failregex = "ClientAddr":"(<HOST>[^"]+)".+?"DownstreamStatus":(401|403)
ignoreregex = "/api/live|/ping|/metrics|/health"
10 Aktive Jails
| Jail | Service | Max Retries | Ban Time |
|---|---|---|---|
| authentik-login | Authentik SSO | 5 in 10min | 1h |
| nextcloud-login | Nextcloud | 5 in 10min | 1h |
| directus-login | Directus CMS | 5 in 10min | 1h |
| n8n-login | n8n Automation | 5 in 10min | 1h |
| grafana-login | Grafana | 3 in 10min | 2h |
| wazuh-login | Wazuh SIEM | 3 in 10min | 2h |
Schicht 2: Wazuh IPS
Automatische Firewall-Blockierung
<!-- In /var/ossec/etc/ossec.conf -->
<command>
<name>firewall-drop</name>
<executable>firewall-drop</executable>
<timeout_allowed>yes</timeout_allowed>
</command>
<active-response>
<disabled>no</disabled>
<command>firewall-drop</command>
<location>local</location>
<rules_id>80702,5503,5504,5505</rules_id>
<timeout>3600</timeout>
</active-response>
Schicht 3: Traefik Rate Limiting
Rate-Limiting Policies
ratelimit-sso: 30 req/min # OAuth/OIDC Flows
ratelimit-login: 5 req/min # Standard Login
ratelimit-admin: 3 req/min # Admin Interfaces
ratelimit-api: 20 req/min # API Endpoints
Kritisches Learning: SSO-Kompatibilität
OAuth/OIDC-Flows benötigen deutlich mehr Requests als normales "POST login":
- Initial auth request
- Redirect zu Authentik
- Token request
- Token validation
- Cookie/Session management
Probleme & Lösungen
Problem 1: SSO funktioniert nicht mehr
Route /auth/login/authentik doesn't exist HTTP/2 404 Not Found
Diagnose
- Directus hat keine Authentik-Umgebungsvariablen
.envfile war unvollständigAUTH_AUTHENTIK_DRIVER=war leer
Lösung
- Alle
AUTH_AUTHENTIK_*Variablen zur.envhinzufügen - Echte CLIENT_SECRET aus Authentik-DB abrufen:
docker exec postgres-authentik psql -U authentik -d authentik -c \ "SELECT client_secret FROM authentik_providers_oauth2_oauth2provider \ WHERE name ILIKE '%directus%';" - Directus neu starten mit korrekten Credentials
Problem 2: Rate-Limiting zu restriktiv für SSO
Ursache
5 req/min für `auth-login` ist zu restriktiv. OIDC Authorization Flow mit PKCE benötigt 8-12 Anfragen in schneller Folge.
Lösung
# Neue Policy für SSO
ratelimit-sso:
rateLimit:
average: 30 req/min
burst: 60
# Verwendung in auth-login Chain
auth-login:
chain:
middlewares:
- ratelimit-sso # 30 req/min statt 5
Problem 3: Traefik Middleware YAML Syntax
Fehler
middleware "mailcow-headers,auth-login@file" does not exist
Ursache
# ❌ Falsch: Comma-separated String
middlewares: mailcow-headers,auth-login@file
# ✅ Richtig: YAML Liste
middlewares:
- mailcow-headers
- auth-login@file
Finale Konfiguration
Alle 11 geschützten Services
| # | Service | Fail2ban | Rate Limit | Wazuh IPS |
|---|---|---|---|---|
| 1 | Authentik (auth.matzka.cloud) | ✅ | 30 req/min | ✅ |
| 2 | Nextcloud (next.matzka.cloud) | ✅ | 5 req/min | ✅ |
| 3 | Directus (cms.matzka.cloud) | ✅ | 5 req/min | ✅ |
| 4 | n8n (n8n.matzka.cloud) | ✅ | 5 req/min | ✅ |
| 5 | Mailcow (mail.matzka.cloud) | ✅ | 5 req/min | ✅ |
| 6 | Grafana (monitor.matzka.cloud) | ✅ | 3 req/min | ✅ |
| 7 | Wazuh (siem.matzka.cloud) | ✅ | 3 req/min | ✅ |
| 8 | Umami (analytics.matzka.cloud) | ✅ | 5 req/min | ✅ |
| 9 | Portal (portal.matzka.cloud) | - | 5 req/min | ✅ |
| 10 | WebApp (matzka.cloud) | - | 10 req/min | ✅ |
| 11 | n8n Webhook (/webhook/chat) | ✅ | 25 req/min | ✅ |
Lessons Learned
Technische Erkenntnisse
1. Layered Security funktioniert
- Eine Schicht allein reicht nicht
- Mehrere Schichten erschweren Angriffe exponentiell
- Redundanz ist wichtig: Bei Fehler in einer Schicht funktionieren andere noch
2. Network Isolation ist Double-Edged
- ✅ Gut für Sicherheit (Services können sich nicht beeinflussen)
- ❌ Schlecht für Konfiguration (komplexe DNS/Network-Setup)
- 💡 Zentrale Koordination (Prometheus) ist besser als dezentral
3. Log Format ist kritisch
- JSON-Logs sind strukturiert, aber komplexer zum Parsen
- Alte regex-based Tools brauchen Anpassungen
- Investition in JSON-aware Tools lohnt sich
4. OAuth/OIDC ist komplex
- Viel mehr Requests als normales "POST login"
- PKCE, State, Nonce, Token Refresh
- Rate Limits müssen "großzügig" für SSO sein
Prozess Erkenntnisse
- Monitoring first, dann sperren: Zuerst Fail2ban mit Email, ohne zu blockieren
- Dokumentation während Implementierung: Was funktioniert nicht? Warum? Wie gelöst?
- Schritt für Schritt: Nicht alles auf einmal ändern. Eine Schicht nach der anderen.
- Testing ist essential: Jede Konfigurationsänderung mit echten Clients testen
Empfehlungen für zukünftige Projekte
- Layered Defense von Anfang an planen
- Logs strukturiert (JSON) speichern
- Zentrale Alerting-Komponente (Prometheus + Alertmanager) nutzen
- Rate Limits nicht zu restriktiv für SSO/OAuth
- Monitoring ohne Blocking starten, dann progressiv verschärfen
Fazit
Das Three-Layer Brute-Force Protection System für matzka.cloud ist nun produktiv im Betrieb:
✅ 10 Fail2ban Jails überwachen alle Login-Endpunkte
✅ Wazuh IPS blockiert verdächtige IPs auf Firewall-Ebene
✅ Traefik Rate Limiting drosselt schnelle Anfragen
✅ Alertmanager benachrichtigt Admin über Vorfälle
✅ Alle 11 Web-Services sind geschützt
✅ SSO/OAuth Flows funktionieren korrekt
✅ Keine False Positives für legitime Benutzer
Das System wurde unter realen Bedingungen getestet und alle identifizierten Probleme wurden gelöst. Die Infrastruktur ist nun deutlich resistenter gegen Brute-Force-Angriffe, während gleichzeitig Benutzerfreundlichkeit und SSO-Funktionalität erhalten bleiben.