Einleitung
DDoS ist das wohl meist verbreitetste Problem für Webseiten. Und eigentlich gibt es auch keine wirklichen Lösungen. Aber es gibt Ansätze!
Im heutigem Post geht es um die Probleme von DDoS-Angriffen und was man ohne einem monatlichen Kapital von mehreren tausend Euro dagegen tun kann. Was DDoS ist und wie lässt sich im Artikel DDoS von einem PC? nachlesen.
Die Probleme
Bei DDoS-Angriffe gibt es zwei Probleme. Zum einen wäre hier das ursprüngliche Ziel eines solchen Angriffes. Und zwar die Überlastung des Servers. So werden so viele Verbindungen aufgebaut, dass der Server überlastet ist oder so viel Leistung gezogen, dass selbiges geschieht. Da die Internetleistung aber immer mehr steigt und bereits eine billige Internetleitung um die 800kbit/s durchlässt, kommt als zweites Problem die Anbindung. Ein normaler Webserver hat eine Anbindung von 100mbit/s. So braucht es also nur noch 125 Zombies um solch eine Bandbreite voll auszunutzen.
Diese zwei Probleme will ich beide am Schopf packen und eine möglichst leistbare Lösung bieten.
Die Struktur
Um das Problem der Bandbreite zu lösen setze ich auf eine verteilte Serverstruktur. Das klingt zwar sehr kostspielig, allerdings bieten hier die VPSs eine kostengünstige Möglichkeit. Da VPSs allerdings meist bzw. immer eine so genannte shared, also geteilte, Internetleitung haben, ist es von keinerlei Vorteil für die Bandbreite wenn man mehrere VPSs vom selben Hoster kauft. Die Wahrscheinlichkeit, dass man auf dem selben Server liegt ist hier zu hoch. So sollte man zu möglichst vielen Hostern gehen und auch die Rechenzentren beachten.
Um die Last zu verteilen, werde ich auf das Round Robin Prinzip zurück greifen. Hier wird einfach geschaut welcher Server gerade den Request bearbeiten kann und sendet ihn dann zu diesem. Und um diese Lastverteilung immer am Laufen zu halten, mache ich das über die DNS-Einträge. Der DNS-Server kann zwar im eigenen Besitz sein, steht bei mir allerdings bei meinen Domainanbieter und betrifft mich somit nicht.
Hinter der Wand von VPSs, die eine hohe Bandbreite liefern und den Traffic soweit als möglich filtern, steht dann ein Rootserver. Das ist der Hauptserver, der dann als Webserver fungiert.
In Gimp, das ich als Paint missbraucht habe, sieht das nun so aus:
Die Anzahl der VPSs variiert natürlich. Dann lasset uns zur Tat schreiten. Zu sagen ist auch, dass Round Robin DNS den Nachteil hat, dass es möglich ist, dass der Klient einen überlasteten Server nimmt, während andere frei sind. Doch ist mir das noch nicht passiert.
DNS einrichten
Hierbei ist es ganz einfach. Je nachdem wie man seine DNS-Einträge nun setzt geht man da hin. Dann werden einfach mehrere gleiche A-Records angelegt, welche sich nur in der Ziel-IP unterschieden. Das hat den Effekt, dass alle angegebenen IPs zurück gegeben werden und das in einer wechselnden Reihenfolge. Ein moderner Klient pickt sich dann die erste erreichbare Adresse heraus und kann bedient werden.
Ja so einfahc ist das.
Hauptserver einrichten
Natürlich braucht man einen Hauptserver, der all die gesäuberten Requests bedient. Als Software werde ich Lighttpd verwenden. Warum Lighttpd? Warum man Lighttpd Apache vorzieht liegt auf der Hand, aber warum ich nicht NGinx verwende ist eine andere Sache. Das liegt nämlich daran, dass ich mit Lighttpd sehr gute Erfahrung als Dynamic Content Handler gemacht habe. Die Leistung zusammen mit FastCGI ist super und bis jetzt konnte mich noch niemand dazu bewegen zu NGinx zu wechseln. Abgesehen davon, bietet das System mehr Sicherheit. Ggf. es gibt eine Lücke in NGinx. Dann wird der Angreifer auf die Proxy-Server kommen, aber den Lighttpd kann er nicht so einfach mit dem NGinx-Exploit bezwingen.
Das von mir verwendete System ist Ubuntu. Das liegt zum einen daran, dass es von bezhalten Entwicklern weiterentwickelt wird und zum anderen dass es den selben Packetemanager wie Debian verwendet und auf Debian basiert. So decke ich auch die Debian-User ab. Als Installation kommt Lighttpd mit PHP5 und MySQL. Weiters sind wir sozusagen Dauerroot. Also schön brav “sudo -s” eingeben .
Die Installation
MySQL ist schönerweise in Repositories von Ubuntu und Debian dabei. So können wir MySQL ganz einfach mit folgendem Befehl installieren.
apt-get install mysql-server mysql-client
Während der Installation wird man aufgefordert das Passwort für den MySQL-User “root” einzugeben. Dieses merken und geheim halten.
Das war der erste Streich und der Zweite folgt zu gleich. Und dieser ist Lighttpd. Lighttpd ist fast noch einfacher als MySQL installiert:
apt-get install lighttpd
Und nun kommt der letzte beschwerliche Schritt der Installation. Nein mal im Ernst. Wer das bis jetzt schwer gefunden hat, sollte aufhören und den Server stornieren.
Aber ich will hier keine Ratschläge geben, sondern mein Tutorial fortführen. Also installieren wir nun PHP-FPM, das ein FastCGI-Daemon ist.
apt-get install php5-fpm php5
Das war nun die Installation. Schaut sie euch noch einmal an. Ihr werdet diese einfachen Schritte vermissen.
Die Konfiguration
Zuerst werden wir FastGGI in der PHP-Konfiguration aktiveren. Keine Sorge im Grunde ist alles ganz leicht. Es ist nur etwas anstrengend, wenn man die ganz Befehle nicht kennt.
Wir öffnen nun die php.ini. Ich verwende hier Nano als Editor. Wer ihn noch nicht hat, kann ihn mit “apt-get install nano” installieren. Die php.ini ist bei PHP-FPM in /etc/php5/fpm/php.ini gespeichert. Also öffnen wir sie:
nano /etc/php5/fpm/php.ini
Nun suchen wir mit Ctrl+W die Zeile
;cgi.fix_pathinfo=1
Am einfachsten geht das indem man einfach “cgi.fix_pathinfo=1″ sucht. Wenn dir diese Zeile gefunden habe, dann kommentieren wir sie einfach aus. Das heißt wir entfernen den “;”. Danach schließen wir die Datei mit Ctrl+X und bestätigen, dass wir sie speichern wollen mit Y. Evntl. ist es auch Strg+Y. Ich habe derzeit leider keine Linux-Maschine an und schreibe das mehr oder weniger aus dem Kopf.
Als nächstes konfigurieren wir Lighttpd für FastCGI. Dazu öffnen wir die Datei /etc/lighttpd/conf-available/15-fastcgi-php.conf:
nano /etc/lighttpd/conf-available/15-fastcgi-php.conf
In diese schreiben wir nun:
fastcgi.server += ( ".php" => (( "host" => "127.0.0.1", "port" => "9000", "broken-scriptfilename" => "enable" )) )
Wieder schließen und speichern und fertig. Das konfiguriert das FastCGI-Modul für die Dateierweitern “.php”. Es werden also alle *.php-Dateien über den FastCGI-Server verarbeitet.
Als nächstes müssen wir das Fast-CGI-Modul in Lighttpd aktivieren. Dazu werden die zwei Module “fastcgi” und “fastcgi-php” wie folgt aktiviert:
lighttpd-enable-mod fastcgi lighttpd-enable-mod fastcgi-php
Nun zwingen wir Lighttpd die Konfiguration neu zu laden:
/etc/init.d/lighttpd force-reload
Fertig sind wir. Wir können nun in /var/www unsere erste PHP-Datei testen.
echo "< ?php echo phpinfo(); ?>" > /var/www/info.php
Wenn man nun den Webserver mit http://deineIP/info.php aufruft kommt folgendes Bild:
Nun kommt der letzte Streich. Und zwar installieren wir diverse PHP-Module wie MCrypt oder die MySQL-API. Wer nicht alle haben will, sortiert sie einfach raus:
apt-get install php5-mysql php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl
Danach laden wir noch PHP-FPM neu und unser Hauptserver ist eingerichtet.
/etc/init.d/php5-fpm reload
Die Reverse-Proxies/VPSs
Nun haben wir einen Leistungsstarken Hauptserver. Allein dieser Server würde schon mehr DDoS-Angriffe als Apache handeln. Und mit einem einfach IP-Blocking-Script gäbe es auch keine Überlastung mehr. Das kann ich sagen, da ich selber in solch einer Situation war. Der Server hatte einen Load von 0 0 0, doch ich konnte nur vereinzelnd zu SSH verbinden. Das lag daran, dass die Bandbreite voll ausgeschöpft wurde. Und genau deswegen kommen die ReverseProxies ins Spiel.
Die Installation
Als Software verwenden wir wie schon gesagt Ubuntu und NGinx. Ubuntu und ich bin mir sicher Debian auch bietet bereits ein Paket namens nginx. Und genau das ist das Paket das wir installieren wollen. Natürlich wieder als Dauerroot.
apt-get install nginx
Und das war die Installation. Mehr nicht. Ein Aufruf zeigt bereits, dass der Server funktioniert:
Mail-Server und Co wurden absichtlich nicht installiert. Das hat den Hintergrund, dass man so durch empfangene Mails die direkte IP herausfinden kann.
Die Konfiguration
An der Konfiguration von NGinx müssen wir nicht wirklich herumschrauben, allerdings müssen wir die Seiten konfigurieren. Hierzu öffnen wirdie Datei /etc/nginx/sites-available/default. In /etc/nginx/sites-available werden alle Konfigurationsdateien für die Seiten gespeichert. Diese werden übrigens in der /etc/nginx/nginx.conf per Befehl inkludiert.
nano /etc/nginx/sites-available/default
Diese wird durch folgenden Inhalt ersetzt.
http { server { listen 80; server_name www.domain.com domain.com; access_log off; location / { proxy_pass http://IpOfMainServer; proxy_redirect off; proxy_set_header Host IpOfMainServer; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; } } }
Wer mehr darüber wissen will, kann sich hierzu gerne auf HttpProxyModule informieren. Nun nehmen wir unseren Hauptserver noch etwas Arbeit ab und stellen das Caching für den Reverse Proxy ein. Hierzu muss man ein bestimmtes Verzeichniss das gecacht wird und die darin enthaltenen Dateitypen (Bider, CSS, usw).
proxy_cache_key $host$request_uri; proxy_cache_path /var/www/cache/images levels=1:2 keys_zone=images:500m; location /images { proxy_cache images; proxy_cache_valid 24h; proxy_pass http://IpOfMainServer; }
Zu guter letzt kommt noch ein kleiner Trick um automatische Requests zu filtern. Und zwar unterstützen nur die wenigsten dieser Zombies Weiterleitungen per 301. Und genau hier setzen wir ein. Es wird ein Cookie gesetzt, der den Browser indentifiziert. Die Bots erhalten einen 301 (also eine Weiterleitung), wenn dieser nicht gesetzt wurde Allerdings erkennen sie diese nicht und daher erhalten sie nie den Cookie. Und so erhalten sie einfach nur einen 301-Error. Dies betrifft allerdings auch Suchmaschinen und stellt genau das Gegenteil von SEO dar.
if ($cookie_antiflood !~* "randomValue") { rewrite ^(.*)$ /set_cookie$1 permanent; break ; } location ~ ^/set_cookie/ { add_header Set-Cookie "antiflood=randomValue; path=/"; rewrite ^/set_cookie/(.*)$ /$1 permanent; break ; }
Das war die grobe Konfiguration. Es fehlen noch die Feinkonfiguration und andere individuele Einstellungen.
Zusatz: NGinx als Loadballancer
Wer sich nun wirklich gegen den Round Robin DNS entschieden hat, hat wohl ein großes Inventar für eine starke Anbindung. Doch auch die reichen Leute sollten nicht leer ausgehen.
Die Installation ist wieder mit einem Befehl getan:
apt-get install nginx
Die Konfigurationsdatei (/etc/nginx/sites-available/default) beinhaltet nun nur noch folgende Zeilen:
http { upstream loadbalancer { server IpOfVPS1; server IpOfVPS2; server IpOfVPS3; } server { listen 80; server_name www.domain.com domain.com; access_log off; location / { proxy_pass http://loadbalancer; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } }
proxy_pass und Co hatten wir ja bereits und im upstream-Block werden einfach die VPSs definiert. Außerdem wird der access_log ausgeschaltet, um die Last zu reduzieren.
Schlusswort
Ich hoffe das Tutorial ist trotz meiner AbneigungKonfigurationen zu erklären brauchbar und verständlich. Zudem sei gesagt, dass das kein 100%iger Schutz sein kann, sondern nur ein Ansatz ist. Außerdem benötigen die Server auch eine kleine Optimierung.
Außerdem sind VPSs zwar eine kostengünstige Alternative sind, allerdings nicht die beste. Besser wäre hier ein Root-Cluster, was allerdings auch schon sehr teuer wäre.
Ein Kommentar
such_dir_was_aus
Ich verdiene unter anderem mit einer, wie du sagst „mehreren tausend Euro“ teuren DDoS Protection. Das eigentliche Problem ist einfach. Der Traffic verstopft die Leitung. Du filterst, wenn wir uns das OSI Modell anschauen erst sehr sehr weit oben. Der Traffic ist dann bereits über den Core Router von deinem Hoster, über den Switch an die entsprechenden Nodes / Server geflossen. Dort angekommen hast du nun deine 100 Mbit / 1 Gbit Uplink Anbindung. Sobald diese „voll“ sind ist für dich bereits Ende im Gelände. Das Problem ist einfach das Verstopfen der Leitung. In meinen Augen ist ein DDoS Schutz so spät einfach nur sinnlos. Die Zeit kann man sich sparen. Effektiver DDoS Schutz erfolgt entweder direkt vor oder direkt nach dem Core Router.