Ufw Limit gegen Überlastung einstellen
Aus znilwiki
Changelog:
- 07.06.2026 erste Version
Vorwort
Neulich hatte ich das Problem das mein Webserver auf dem diese Webseite läuft ständig auf 100% CPU lief.
Mit htop konnte ich sehen das es die Prozesse für diese Webseite hier sind (jede meiner Webseiten / Subdomain läuft unter einem eigenen Benutzer).
Im acccess.log konnte ich viele Zugriffe von verschiedenen IP-Adressen sehen.
Per Einzeiler
tail -n 10000 /weg/zu/dem/access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -n 20
zeigt die Top-Adressen der letzten 10.000 Logzeilen.
Im Gegensatz zu früher war es diesmal aber ziemlich verteilt über die Welt. Die Aufrufe an mein Wiki waren dabei maximal Belastend - es wurde Änderungen für bestimmt Zeiträume abgefragt oder vorherige Versionen usw.
Das übliche Sperren von 1 bis 2 IP-Adressen wirkte hier also nicht.
Ich hatte diverse Dinge ausprobiert, was funktionierte war die Begrenzung der Anzahl der Verbindungen pro IP-Adresse.
Die ufw-Regel
sudo ufw limit proto tcp from any to any port 80 sudo ufw limit proto tcp from any to any port 443
Dadurch wird automatisch jede IP-Adresse blockiert die versucht, mehr als 6 Verbindungen innerhalb von 30 Sekunden aufzubauen.
Erfolgt mehr als 30 Sekunden kein Zugriff von der IP, wird diese wieder freigegeben.
Zuschauen kann man dabei im Log:
tail -n 100 -F /var/log/ufw.log
Adressen oder IP-Blöcke whitelisten
sudo ufw allow from 192.168.0.10
nimmt die 192.168.0.10 aus allen Regeln heraus, per
udo ufw allow from 192.168.0.0/24
auch ein ganzes Netzwerksegment.
Wer sicher gehen will das das auch immer rechtzeitig greift macht folgendes:
nano /etc/ufw/before.rules
und fügt oben unter
# allow all on loopback -A ufw-before-input -i lo -j ACCEPT -A ufw-before-output -o lo -j ACCEPT
direkt darunter die Regel ein:
# Erlaubt absolut alles aus dem internen Netz, bevor INVALID-Prüfungen greifen -A ufw-before-input -s 192.168.0.0/22 -j ACCEPT
Speichern und per
ufw reload
Firewall neu laden
ufw-Regel wieder löschen
sudo ufw delete limit proto tcp from any to any port 80 sudo ufw delete limit proto tcp from any to any port 443
Eigene Limits statt 6 Versuche in 30 Sekunden setzen
Einen direkten Befehl eigene Limits zu setzen als die 6 Versuche in 30 Sekunden gibt es nicht.
Man muss die Regel zunächst erstellen und dann die folgende Datei bearbeiten:
sudo nano /etc/ufw/user.rules
In der Datei müsste irgendwo ein Abschnitt ähnlich wie diesem hier stehen (2x einmal für Port 80 und einmal für Port 443):
### tuple ### limit tcp 80 0.0.0.0/0 any 0.0.0.0/0 in -A ufw-user-input -p tcp --dport 80 -m conntrack --ctstate NEW -m recent --set -A ufw-user-input -p tcp --dport 80 -m conntrack --ctstate NEW -m recent --update --seconds 30 --hitcount 6 -j ufw-user-limit -A ufw-user-input -p tcp --dport 80 -j ufw-user-limit-accept ### tuple ### limit tcp 443 0.0.0.0/0 any 0.0.0.0/0 in -A ufw-user-input -p tcp --dport 443 -m conntrack --ctstate NEW -m recent --set -A ufw-user-input -p tcp --dport 443 -m conntrack --ctstate NEW -m recent --update --seconds 30 --hitcount 6 -j ufw-user-limit -A ufw-user-input -p tcp --dport 443 -j ufw-user-limit-accept
Wonach Ihr suchen könnt ist --seconds 30 und/oder --hitcount 6, bei --dport sollte 80 oder 443 stehen.
Die beiden Werte passt Ihr einfach an, speichert die Datei und lasst diese per
sudo ufw reload
neu einlesen.
Brutalere Methode für ein Limit
nano /etc/ufw/before.rules
und direkt nach dem Abschnitt für das Loopback:
# allow all on loopback -A ufw-before-input -i lo -j ACCEPT -A ufw-before-output -o lo -j ACCEPT
folgendes Einfügen (ggf. nach einem Whitelisting lokaler Adressen)
# Blockiert IPs, die mehr als 15 gleichzeitige Verbindungen auf Port 80/443 halten -A ufw-before-input -p tcp --dport 80 -m connlimit --connlimit-above 15 -j REJECT --reject-with tcp-reset -A ufw-before-input -p tcp --dport 443 -m connlimit --connlimit-above 15 -j REJECT --reject-with tcp-reset
Das normale Limit bei Apache nicht umgehen lassen
Ich hatte gerade einen Bot wo das ufw limit nicht griff da er die weiteren Anfragen über die bestehenden Verbindungen gemacht hat.
Lösung: Ich habe im Apache für die Webseite folgendes konfiguriert (Apache Directives):
# Begrenzt die Anfragen pro Keep-Alive-Verbindung für diese Webseite MaxKeepAliveRequests 30 KeepAliveTimeout 2
Damit sind dann pro Verbindung nur 30 weitere Nachfragen erlaubt (Default war bei mir 500, vermutlich durch ISPConfig gesetzt)
Das KeepAliveTimeout 2 schließt eine Verbindung nach 2 Sekunden wenn keine weiteren Nachfragen kommen (Default war 5).
