Kommentarspam – mal wieder
Über Kommentarspam hatte ich mich ja schon mal geärgert und eine Browsererkennung implementiert. In den letzten Tagen waren aber wieder viele hundert Spamkommentare im Blog.
Haben meine Methoden versagt? Ein Blick in die Logfiles zeigen, daß von der betreffenden IP tatsächlich komplette Webseiten geholt werden. Offenbar ist da ein voll qualifizierter Browser am Werk.
Natürlich – das ist ja der Sinn dieses Tests – soll in einem Browser die Kommentarfunktion anstandslos funktionieren. Unglücklicherweise tut es das auch für den Spammer.
Die dümmsten Spammer haben die größten Erfolge
Was unterscheidet nun also den Spammer von einem normalen Nutzer? Auffällig ist die Schnelligkeit, mit der Kommentare versendet werden. Es liegen kaum zwei Sekunden zwischen zwei abgesendeten Kommentaren. Direkt nach dem Laden der Seite wird der Kommentar abgeschickt.
Ganz offensichtlich benutzt der Spammer einen gescripteten Browser. Allerdings waren die ersten Versuche noch sehr langsam. Vielleicht ist das ja die neue Generation von Spammern, die nicht einmal mehr programmieren kann, sondern mit einem Makrorekorder die Bedienung aufzeichnet, um sie dann tausendfach abzurollen.
Eine Möglichkeit besteht darin, den per Javascript nachgeladenen Code nicht direkt auszuführen, sondern per erste einige Sekunden verzögert zu aktivieren. Aber wo legt man da die Grenze? Und was ist mit Nutzern, die reloaden, bevor sie den Kommentar eintippen. Ich mache das öfter, um zu sehen, welche Kommentare noch zuletzt hinzu gekommen sind.
Eine andere Möglichkeit besteht darin, die Anzahl der Kommentare pro Zeiteinheit, also die Rate, auszuwerten. Dies geht nicht mehr im Formular, sondern benötigt einen Blick auf die Historie.
Diese Historie findet sich in der Datenbank. Also kann die Datenbank auch selbst das Rate-Limiting machen.
CREATE OR REPLACE RULE lutz_prevent_spam AS ON INSERT TO ezcomment WHERE 5 < (SELECT Count(ip) FROM ezcomment WHERE ip = NEW.ip AND created > NEW.created - 60) DO INSTEAD DELETE FROM ezcomment WHERE ip = NEW.ip AND created > NEW.created - 60*10;
Es wird also geschaut, ob von dieser IP in den letzten 60 Sekunden mehr als fünf Kommentare abgesendet wurden. Ist das der Fall, werden alle Kommentare von dieser IP gelöscht, die in den letzten 10 Minuten geschrieben wurden.
Das scheint aktuell zu halten. Drückt mir die Daumen.
Einen Tag später
Wie in den Kommentaren zu sehen, hat es nicht gehalten. Jedenfalls nicht ganz richtig.
Die neue Lösung besteht darin eine neue Tabelle zu haben, die die blockierten IPs aufzählt:
Table "public.ezcomment_block" Column | Type | Modifiers --------+------------------------+----------- ip | character varying(100) | not null seen | integer | not null Indexes: "ezcomment_block_pkey" PRIMARY KEY, btree (ip) Rules: update_if_necessary AS ON INSERT TO ezcomment_block WHERE new.ip IN (SELECT b.ip FROM ezcomment_block b) DO INSTEAD UPDATE ezcomment_block c SET seen = new.seen WHERE c.ip = new.ip
Mit der Regel, die die Inserts bei Bedarf in Updates umschreibt, kann man dauerhaft Inserts benutzen. Das vereinfacht die neue Regel für die Kommentare.
CREATE OR REPLACE RULE lutz_prevent_spam AS ON INSERT TO ezcomment WHERE 5 < (SELECT count(1) FROM ezcomment WHERE ip = new.ip AND created > new.created - 60) OR new.ip IN (SELECT ip FROM ezcomment_block WHERE seen > new.created - 24 * 60 * 60) DO INSTEAD ( DELETE FROM ezcomment WHERE ip = new.ip AND created > new.created - 10 * 60; INSERT INTO ezcomment_block (ip, seen) VALUES (new.ip, new.created); )
Mal sehen, wie lange das nun hält.
Ich muß also auch in die Zukunft löschen.
5.79.73.142 - - [02/Jun/2014:11:56:36 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:56:36 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:56:36 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:56:39 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:56:40 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:56:40 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:56:43 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:56:44 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:56:57 +0200] "POST /ger/comment/add HTTP/1.1"
5.79.73.142 - - [02/Jun/2014:11:56:59 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:56:59 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:01 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:09 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:10 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:10 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:12 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:14 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:32 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:33 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:37 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:38 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:39 +0200] "POST /ger/comment/add HTTP/1.1"
5.79.73.142 - - [02/Jun/2014:11:57:42 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:43 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:55 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:56 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:57:57 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:58:02 +0200] "POST /ger/comment/add HTTP/1.1"
5.79.73.142 - - [02/Jun/2014:11:58:06 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:58:06 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:58:08 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:58:10 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:58:17 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:58:21 +0200] "POST /comment/add HTTP/1.1" 302
5.79.73.142 - - [02/Jun/2014:11:58:33 +0200] "POST /comment/add HTTP/1.1" 302
Total 5 comments