Webserver vor einfachen DoS-Angriffen schützen

2010-08-14 - josen 11 Kommentare »

Oft hat man lange Zeit Glück und betreibt eine Webseite, die keine kontroversen Inhalte enthält. Manchmal ist dem aber nicht so, dann geht es schnell heiß her und schneller als viele denken, ist man Opfer eines DoS-Angriffs. Seit Juni 2009 gibt es ein sehr leicht zu bedienendes und sehr erfolgreiches neues DoS-Tool: slowloris. An dessen Beispiel gebe ich hier eine kleine Einführung in die Erkennung und Prävention einfacher DoS- und DDoS-Angriffe. Was also tun, wenn der Webserver unter Debian zum Stillstand kommt, weil ein Angreifer hunderte Verbindungen offen hält, oder den Webserver mit Anfragen bombardiert?

Angriff erkennen!

Zuerst einmal bemerken, dass der Webserver nicht erreichbar ist (dafür gibt es eine Menge kostenloser Uptime-Dienste, die gern und häufig per E-Mail informieren). Nachdem also eine solche E-Mail eingetroffen ist, muss zuerst geprüft werden, ob es sich um einen DoS- oder einen DDoS-Angriff handelt. Das funktioniert am einfachsten, indem die zum Webserver bestehenden Verbindungen geprüft werden:

$ netstat -ant

Angezeigt wird auf einem nur halbwegs stark belasteten Webserver eine Liste von Verbindungen die in die hunderte geht. Einfacher geht es, wenn die Hosts absteigend nach gerade nicht aktiven Verbindungen sortiert werden. Dazu dient folgender Einzeiler:

$ netstat -ant | grep TIME_WAIT | awk '{ print $5}' | cut -d ":" -f 1 | sort | uniq -c
Für slowloris ist hier der Socket-Zustand TIME_WAIT interessant, da meinen Erfahrungswerten
mit einigen großen Webforen nach, die Sockets des Angreifers lange in diesem Zustand
verharren. Für andere DoS-Angriffe (z.B. den Klassiker mittels ApacheBench) kann auch das
aufsummieren der Sockets im Zustand SYN_RECV interessant sein. (man 8 netstat weiß mehr)

Jeder Host, der mehr als die zur Zeit übliche maximale Anzahl an Verbindungen (mit InternetExplorer 8 sind es bis zu acht gleichzeitig) weit übersteigt ist ein potenzieller Kandidat. Ab einer Größenordnung von 30 oder 40 Verbindungen lohnt sich eine genauere Betrachtung. Bei einem typischen slowloris Angriff wird man schnell einen Host finden, der mehr als 100 Verbindungen offen hält. Die Empfehlung für einen solchen Angriff durch den Autor liegt bei 500 bis 600 gleichzeitigen Verbindungen.

Und wie verhindert man den Angriff?

Nachdem der Host identifiziert ist, könnte man natürlich gerade diesen einen Host mit einer einfachen iptables-Regel vom Verkehr mit dem Webserver ausschließen:

$ iptables -A INPUT -p tcp -s $AngreiferIP --destination-port 80 -j DROP

Bei einem verteilen Angriff (DDoS) wird es dabei schnell schwer einen Überblick über die manuell hinzugefügten Regeln zu behalten. Nach einem halben Jahr Angriff und Verteidigung gegen slowloris und andere einfache verteilte DoS-Angriffe haben sich folgende Regeln für den angegriffenen Webserver bewährt, die ich nur jedem empfehlen kann:

# Set proofed limits for http 1.1 clients (1.0 does not use pipelining)
$ iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 8 -j DROP
$ iptables -I INPUT -p tcp -m state --state NEW --dport 80 -m recent \\
--name slowloris --set
$ iptables -I INPUT -p tcp -m state --state NEW --dport 80 -m recent \\
--name slowloris --update --seconds 15 --hitcount 15 -j DROP
$ iptables -A INPUT -p tcp --dport 80 -j ACCEPT
1. Sperrt jeden Host, der mehr als eine neue Verbindung pro Sekunde aufbauen will, wenn
bereits acht bestehen.
2. Versieht jede neue Verbindung zum Webserver mit dem Stempel "slowloris". 
3. Verwirft alle Pakete von einem Host für 15 Sekunden, wenn mehr als 15 neue
Verbindungen mit dem Stempel "slowloris" aufgebaut wurden.
4. Akzeptiert alle Verbindungen zum Webserver.

Was gibts zu beachten?

Die Regeln können So übernommen werden (sollten aber vorher getestet werden, Browser entwickeln sich weiter). Lauffähig sind sie mindestens ab Debian 5.0 "lenny". Einzig erwähnenswertes Problem sind große Arbeitsgruppen, die gleichzeitig von einer IP (hinter einem NAT) auf den Webserver zugreifen (wie z.B. Schulen).

Wer sich einem massiven Angriff gegenüber sieht, wird auch mit dieser Vorsichtsmaßnahme schnell an die Grenzen, des auf dem Server lokal einstellbaren stoßen. In dem Fall hilft nur der Provider und eine große Firewall weiter.

  1. 11 Kommentare

  2. süppchen
    schrieb am 15.08.2010 um 09:05 Uhr

    Auf den ersten Blick sollte man obige Regel mit Vorsicht genießen. Slurp (das Crawler von Yahoo) öffnet ca. 80 gleichzeitige Verbindungen und je nach Größe der Apache2’s MaxKeepAliveRequests wird er auch regelmaessig Neue aufbauen.

  3. josen
    schrieb am 15.08.2010 um 13:05 Uhr

    Hallo,

    ich konnte leider keine Quelle zu deiner Aussage finden. Vielleicht hast du einen Link oder Statistik dazu?

    Mit deinem Argument, dass besondere Dienste, die von einer IP-Adresse mehr als die angegebene Anzahl an gleichzeitigen Verbindungen aufbauen, hast du Recht.

    Meine Regeln hier sind auch nicht korrekt (beweisbar richtig), sondern das Ergebnis meiner Erfahrungswerte. Das sollte man nicht vergessen. Für kleine bis mittlere Webseiten funktionieren sie gut (bis ca. 60 Anfragen pro Sekunde getestet) und schließen einen sehr kleinen Anteil an legitimen Nutzern aus.

    Im Fall eines Angriffs muss man zwangsweise eine Grenze ziehen, die Sonderfälle ausschließt, um den Betrieb für den Großteil aufrecht zu erhalten.

    Das Problem, dass Methoden die aus vorherigem Anfrageverhalten entwickelt werden und daraus Schlüsse ziehen, immer auch false Positives erzeugen, bekommt man leider nur mit einer Menge höherer Mathematik in den Griff.

    Grüße

  4. süppchen
    schrieb am 16.08.2010 um 12:32 Uhr

    Hi,

    such mal bei Google nach “slurp delay”. Dort findest du viele Faelle, die mit der Aggressivität des Yahoo-Spiders kaempfen. Bei mir sehe ichs in den Statistiken, wenn taeglich gegen 4 Uhr morgens die Anzahl der offenen Verbindungen auf x+80 springt.

    Gruss süppchen

  5. Andreas
    schrieb am 12.10.2010 um 13:12 Uhr

    Moin moin,

    hatte vor ein paar Tagen über Apache Dos attacken etwas gelesen. Wenn ich es richtig verstanden habe gibt es sogar ein Apache2 Modul dafür bei huschi.

    –> http://www.huschi.net/14_182_de.html

    Gruß

  6. dirk
    schrieb am 31.10.2010 um 20:35 Uhr

    lighttpd bietet dafür “mod_evasive” an.

    gruß

  7. Fingers
    schrieb am 29.07.2012 um 17:03 Uhr

    Hi,

    betreffen diese Client-Limits auch den localhost (127.0.0.1)? Das wäre nämlich blöd, da dieser manchmal deutlich mehr als 8 Verbindungen aufbaut.

    Gruß

  8. josen
    schrieb am 29.07.2012 um 20:47 Uhr

    Hallo Finger,

    in der jetzigen Version des Artikels betreffen die Limits natürlich auch localhost. Um das zu ändern kannst du aber die Regeln anpassen. Zum Beispiel so:

    iptables -A INPUT -p tcp –syn -m limit –limit 1/s –limit-burst 8 -s !127.0.0.1/32 -j DROP

    Grüße

  9. Fingers
    schrieb am 29.07.2012 um 20:51 Uhr

    @josen

    danke, werde es gleich mal auspropieren.

    Gruß

  10. Fingers
    schrieb am 29.07.2012 um 21:31 Uhr

    geht leider nicht (iptables v1.4.8)

    die Halbgeviertstriche durch zwei Bindestriche ersetzen ist klar, beim localhost aber bricht iptables mit einer Fehlermeldung ab.

    “can’t initialize iptables table `un.0.0.1/32′: Table does not exist (do you need to insmod?)”

    Gruß

  11. Thomas
    schrieb am 08.11.2012 um 12:22 Uhr

    Wäre Reject nicht besser als Drop?

  1. Trackback(s)

  2. Sep 7, 2010:Linux: Webserver vor einfachen DoS-Angriffen schützen | Crazy little things to blog

Kommentar schreiben

*

*