Denial-of-Service mit Gästebuch

Auf dem Server eines Kunden gab es seit längerem höchst merkwürdige Phänomene: Obwohl die Maschine an sich nur minimal ausgelastet war, hat sie – mit steigender Frequenz – plötzlich Lastspitzen, die die Maschine geradezu unbenutzbar werden ließen. Schnell war ein extrem hoher iowait-Wert identifiziert. Mittels iostat war auch schnell festgestellt, dass der iowait nicht auf eine defekte Festplatte o.ä. zurückzuführen war, sondern zu den Zeiten der Lastspitzen wirklich astronomisch viele Daten auf die Platte geschrieben wurden.

Nun gibt es unter Linux ja einen ganzen Haufen Tools, mit denen man Systemressourcen wie CPU-Zeit oder RAM-Nutzung einschränken oder wenigstens protokollieren lassen kann (Stichworte psacct). Wieviel HDD-Last eine Anwendung erzeugt, kann hingegen meines Wissens nach nicht ausgewertet werden. Sowas könnte ja auch ganz andere Gründe haben, z.B. wenn eine Anwendung unkontrolliert soviel RAM verbraucht, dass die Maschine in den Swap geht. Soll heißen: Die Diagnose eines solchen Problems ist zu einem gewissen Grad einfach Glückssache.

Einigermaßen schnell war geklärt, dass das Problem „irgendwie mit dem Webserver zusammenhängen“ müsse, denn immer, wenn der gestoppt war (was angesichts der Art von Sites und dem mit jenen verbundenen Servicelevel durchaus für einige Minuten tolerierbar war), trat das Problem nicht mehr auf.

Mit Hilfe des server-status-Handlers des Apache schrieb ich einen kleinen Job, der alle paar Sekunden die derzeit abgearbeiteten HTTP-Aufrufe protokollierte. Ziel war, dieses Logfile mit dem Logfile der Lastspitzen abzugleichen, um mit etwas Glück einen Zusammenhang zu einer aufgerufenen Site oder gar einer bestimmten URL herzustellen, um zumindest mal einen Anfang für eine konkretere Analyse zu finden.

Ich gebe gerne zu: Den Aufruf einer Gästebuch-URL habe ich beim Durchsehen des Logfiles unterschwellig ausgeblendet. Ein Gästebuch kann’s ja nun irgendwie nicht sein.

War es aber doch.

Das Gästebuchscript, das sich einer der Kunden installiert (oder vermutlich sogar selbst geschrieben) hatte, speicherte alle Einträge in einer Textdatei, aus der dann schließlich statische HTML-Seiten generiert wurden, durch die man seitenweise blättern konnte. Pferdefuß Nummer 1: Immer wenn vorne ein neuer Eintrag dazu kam, musste hinten der letzte der entsprechenden Seite auf die jeweils folgende Seite rutschen. Das heißt konkret, dass alle HTML-Seiten neu geschrieben werden müssen. Das Problem konkretisiert sich langsam vor dem inneren Auge.

Bisher erschien lediglich die Programmierung ein wenig, ähem, ineffizient. Aber der endgültige Kollaps wurde von der Datenmenge selbst verursacht: Das Gästebuch fasste inzwischen über 16.000 Einträge. Bei 10 Einträgen pro HTML-Seite ergibt das 1600 HTML-Dateien, die im Falle eines neuen Eintrags neu geschrieben werden müssen. Und wenn das noch nicht spannend genug klingt: Die 10 Einträge ergeben mit HTML-Overhead immerhin rund 30 KB. Nun kommen aber, noch ein Pferdefuß, auf jede Seite Links zu den anderen Seiten. Nicht zur davor- und dahinterliegenden, sondern zu allen 1599 anderen Seiten. Mit HTML-Overhead werden daraus rund 120 KB nur für die Links – also rund 150 KB pro HTML-Seite. Multipliziert mit 1600 ergibt das ein Datenvolumen von rund 250 MB, und immer, wenn jemand einen Eintrag hinzufügt, werden diese 250 MB – um einen Eintrag erweitert – auf die Festplatte geknallt.

Das Problem sind nicht die Besucher der Website. Das Problem sind die Spammer. Die bespammen das Gästebuch nämlich durchschnittlich rund 200 Mal pro Tag, mit steigender Tendenz. Das ergibt rund 50 GB Schreibzugriffe pro Tag. Und wir wundern uns über Peaks …

Übrigens: Klickt man auf der betreffenden Website den Link „Gästebuch“ an, kommt man auf eine hübsche Seite, die verkündet: „Das Gästebuch wurde wegen zuviel Spam abgeschaltet“ – die Spammer kannten aber auch ohne Verlinkung von der Website selbst immer noch den ursprünglichen Link, denn vorhanden war das Script nun mal immer noch. Ein besseres Beispiel für den Begriff „Altlast“ habe ich bisher nicht finden können.

Und nochmal übrigens: Solche Analysen gehören bei uns zum üblichen Support, solange sie sich noch „irgendwie im Rahmen“ halten. Der Kunde hat von uns keine Rechnung dafür bekommen.