Nginx Rate Limiting: Schutz vor DDoS und Brute-Force
Nginx Rate Limiting schützt deinen Server vor DDoS-Angriffen und Brute-Force-Attacken. Lerne, wie du request limits, burst-Werte und Zonen richtig konfigurierst.
Wer einen Webserver betreibt, kennt das Problem: Automatisierte Bots, Brute-Force-Attacken auf Login-Seiten und DDoS-Angriffe können selbst leistungsstarke Server in die Knie zwingen. Nginx Rate Limiting ist eines der wirkungsvollsten Werkzeuge, um solche Bedrohungen direkt auf Webserver-Ebene abzufangen – noch bevor sie deine Anwendung erreichen. In diesem Artikel erfährst du, wie du Request Limits, Burst-Werte und Shared-Memory-Zonen richtig konfigurierst und damit deinen Server effektiv absicherst.
Wie funktioniert Nginx Rate Limiting?
Nginx Rate Limiting basiert auf dem Leaky-Bucket-Algorithmus. Stell dir einen Eimer mit einem kleinen Loch im Boden vor: Wasser (Anfragen) fließt oben hinein und unten mit konstanter Geschwindigkeit wieder heraus. Kommt mehr Wasser hinein als abfließen kann, läuft der Eimer irgendwann über – weitere Anfragen werden abgelehnt.
Technisch gesehen verfolgt Nginx die Anzahl eingehender Requests pro definiertem Schlüssel (z. B. IP-Adresse) und vergleicht sie mit einem festgelegten Limit. Wird das Limit überschritten, antwortet der Server standardmäßig mit einem HTTP 503 (Service Temporarily Unavailable).
Die beiden zentralen Direktiven sind:
limit_req_zone– Definiert die Shared-Memory-Zone, den Schlüssel und die Ratelimit_req– Aktiviert das Rate Limiting in einem bestimmten Kontext (server, location)
Grundkonfiguration einrichten
Die Zone definieren
Der erste Schritt ist die Definition einer Rate-Limiting-Zone im http-Block deiner Nginx-Konfiguration:
http {
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
server {
listen 80;
server_name example.com;
location / {
limit_req zone=general;
proxy_pass http://backend;
}
}
}
Hier die Erklärung der einzelnen Parameter:
$binary_remote_addr– Verwendet die Client-IP-Adresse als Schlüssel (binär gespeichert, spart Speicher)zone=general:10m– Erstellt eine Shared-Memory-Zone namens „general" mit 10 Megabyte Speicher (reicht für ca. 160.000 IP-Adressen)rate=10r/s– Erlaubt maximal 10 Requests pro Sekunde pro IP-Adresse
Burst und Nodelay verstehen
Eine strikte Limitierung ohne Puffer führt in der Praxis schnell zu Problemen. Normale Nutzer laden eine Seite auf und erzeugen dabei oft mehrere gleichzeitige Requests (HTML, CSS, JavaScript, Bilder). Genau hier kommt der burst-Parameter ins Spiel:
location / {
limit_req zone=general burst=20 nodelay;
proxy_pass http://backend;
}
burst=20– Erlaubt bis zu 20 Anfragen über dem Limit, die in eine Warteschlange gestellt werdennodelay– Verarbeitet die Burst-Anfragen sofort, anstatt sie künstlich zu verzögern
Ohne nodelay würde Nginx die überschüssigen Anfragen gleichmäßig verteilt abarbeiten, was zu spürbaren Latenzen führt. Für die meisten Webanwendungen ist burst in Kombination mit nodelay die empfohlene Konfiguration.
Schutz vor Brute-Force-Angriffen
Login-Seiten und API-Endpunkte zur Authentifizierung sind beliebte Ziele für Brute-Force-Attacken. Hier bietet sich ein deutlich strengeres Nginx Rate Limiting an:
http {
limit_req_zone $binary_remote_addr zone=login:10m rate=3r/m;
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
server {
listen 443 ssl;
server_name example.com;
# Allgemeines Rate Limiting
location / {
limit_req zone=general burst=20 nodelay;
proxy_pass http://backend;
}
# Strenges Limit für Login
location /login {
limit_req zone=login burst=5 nodelay;
limit_req_status 429;
proxy_pass http://backend;
}
# API-Endpunkte
location /api/ {
limit_req zone=api burst=10 nodelay;
limit_req_status 429;
proxy_pass http://backend;
}
}
}
Beachte die Direktive limit_req_status 429. Standardmäßig gibt Nginx den Statuscode 503 zurück. Der HTTP-Statuscode 429 (Too Many Requests) ist jedoch semantisch korrekt und wird von Clients und Monitoring-Tools besser erkannt.
Benutzerdefinierte Fehlerseite
Damit Nutzer, die das Limit erreichen, eine verständliche Meldung erhalten, kannst du eine eigene Fehlerseite definieren:
server {
error_page 429 /rate_limit.html;
location = /rate_limit.html {
root /usr/share/nginx/html;
internal;
}
}
DDoS-Schutz mit Verbindungslimits
Neben dem Request Rate Limiting bietet Nginx auch die Möglichkeit, die Anzahl gleichzeitiger Verbindungen pro IP zu begrenzen. Das ist besonders wirksam gegen DDoS-Angriffe, bei denen Angreifer massenhaft Verbindungen öffnen:
http {
limit_conn_zone $binary_remote_addr zone=connlimit:10m;
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
server {
listen 443 ssl;
server_name example.com;
# Max. 20 gleichzeitige Verbindungen pro IP
limit_conn connlimit 20;
limit_conn_status 429;
# Request Rate Limiting
limit_req zone=general burst=20 nodelay;
location / {
proxy_pass http://backend;
}
}
}
Die Kombination aus limit_req und limit_conn bietet einen mehrschichtigen Schutz: Selbst wenn ein Angreifer die Request-Rate einhält, kann er nicht unbegrenzt viele Verbindungen offen halten.
Bestimmte IPs vom Rate Limiting ausnehmen
In der Praxis gibt es IPs, die vom Nginx Rate Limiting ausgenommen werden sollen – etwa Monitoring-Systeme, Load Balancer oder interne Dienste. Das lässt sich elegant mit einer geo-Map lösen:
http {
geo $rate_limit_key {
default $binary_remote_addr;
10.0.0.0/8 "";
192.168.1.0/24 "";
203.0.113.50 ""; # Monitoring-Server
}
limit_req_zone $rate_limit_key zone=general:10m rate=10r/s;
}
Wenn der Schlüssel ein leerer String ist, wird die Anfrage nicht gezählt. Damit sind alle Requests aus den definierten IP-Bereichen vom Rate Limiting befreit.
Logging und Monitoring
Um die Wirksamkeit deiner Rate-Limiting-Konfiguration zu überwachen, solltest du das Logging entsprechend konfigurieren:
http {
log_format rate_limit '$remote_addr - [$time_local] '
'"$request" $status '
'limit_req_status=$limit_req_status';
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
server {
access_log /var/log/nginx/access.log rate_limit;
# Log-Level für Rate-Limiting-Events anpassen
limit_req_log_level warn;
location / {
limit_req zone=general burst=20 nodelay;
proxy_pass http://backend;
}
}
}
Geblockte Anfragen lassen sich dann einfach mit grep filtern:
# Alle Rate-Limited Requests anzeigen
grep " 429 " /var/log/nginx/access.log
# Top-10 geblockte IPs ermitteln
awk '$9 == 429 {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
Konfiguration testen und anwenden
Bevor du Änderungen aktivierst, solltest du die Konfiguration immer validieren:
# Konfiguration auf Syntaxfehler prüfen
sudo nginx -t
# Bei Erfolg: Konfiguration neu laden (ohne Downtime)
sudo nginx -s reload
Zum Testen des Rate Limitings eignet sich ein einfacher Lasttest mit curl oder ab (Apache Benchmark):
# 50 Requests schnell hintereinander senden
for i in $(seq 1 50); do
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/login
done
# Oder mit Apache Benchmark: 100 Requests, 10 gleichzeitig
ab -n 100 -c 10 https://example.com/
Du solltest sehen, dass nach Überschreiten des Limits 429-Statuscodes zurückkommen.
Best Practices für Nginx Rate Limiting
- Starte konservativ: Setze Limits zunächst großzügig und verschärfe sie schrittweise basierend auf deinen Log-Daten.
- Unterschiedliche Zonen für unterschiedliche Endpunkte: Login-Seiten brauchen strengere Limits als statische Assets.
- Kombiniere Rate Limiting mit Fail2Ban: Analysiere die Nginx-Logs und blockiere Wiederholungstäter automatisch auf Firewall-Ebene.
- Denke an CDNs und Reverse Proxies: Wenn dein Server hinter einem Proxy steht, verwende
$http_x_forwarded_forstatt$binary_remote_addr– aber nur, wenn du dem Proxy vertraust. - Überwache regelmäßig: Rate-Limiting-Regeln sind kein „Set and Forget". Analysiere deine Logs und passe die Werte an veränderte Traffic-Muster an.
Fazit
Nginx Rate Limiting ist ein unverzichtbares Werkzeug für die Server-Sicherheit. Mit wenigen Zeilen Konfiguration schützt du deinen Server effektiv vor DDoS-Angriffen, Brute-Force-Attacken und übermäßigem Bot-Traffic. Die Kombination aus limit_req für Request-Raten und limit_conn für Verbindungslimits bietet einen robusten, mehrschichtigen Schutz. Entscheidend ist, dass du die Limits auf deine spezifischen Anforderungen abstimmst, verschiedene Zonen für unterschiedliche Endpunkte definierst und das Verhalten kontinuierlich über Logs überwachst. Zusammen mit Maßnahmen wie Fail2Ban und einer vorgeschalteten Firewall wird dein Nginx-Server damit zu einer soliden ersten Verteidigungslinie gegen die häufigsten Angriffsszenarien im Web.