TODO forever when life runs faster than you can afford

1Feb/100

Dodging Wordpress comment spammers

I admit: Allowing anyone to post comments is bad practice. Though, I've got my reasons to stand my ground. I've many times read something on a blog and to some of them I even had something to add. Could potentially help blog's author or future visitors by sharing my own experience, or request a solution to one of my problems by posting a question. Guess what? I am so lazy that I rarely go through registration procedure, just to enable me posting a comment.

I am one of those that insist dialog and discussion is always constructive as long as both ends feel like establishing it. I do not want to loose the opinion and comments of stopping-by visitors, just because I want a "safe" thing that runs on its own. But, "buts" exist. My blog is currently one month old, still it manages to receive 300+, in average, spam-oriented comments per day, while I've even witnessed a 1k/day.

Thank god, Wordpress provides blacklist features based both on IP addresses and comment content. And it really does a good job: After messing around with your recent "spam" you can easily end up with a list that accurately detect a non constructive comment. However, you've not solved all your problems this way:

  • New comments still come. They are just automatically rated as spam.
  • Your database fills with garbage.
  • Your web traffic statistics are spoiled.
  • You waste bandwidth.
  • You waste CPU time.
  • If your spammer ever stop selling drugs and starts advertising flesh, all your content matching rules go away.
  • If your spammer loose interest into being a blog spammer and switch to a port-scanner, you will receive that too.

How about you refuse them a spare TCP socket? Besides, you don't even wanna know them. All their connection attempts will end-up to void. Time for some iptables magic.

Wordpress has already stored their IP addresses within its database. Consult that wp-config.php file you lately edit when you firstly installed Wordpress, and refresh your memory on what your database name, username and password is. Mine are:


$ grep "DB_" wp-config.php
define('DB_NAME', 'mywordpress');
define('DB_USER', 'sakis');
define('DB_PASSWORD', 'myextrastrongpassword');
define('DB_HOST', 'localhost');
define('DB_CHARSET', 'utf8');

You now have to use that information into constructing this single-row command:

mysql -f -p --user=DB_USER DB_NAME <<<"select distinct CONCAT('iptables -A INPUT -s ',comment_author_IP,'/32 -j DROP') from wp_comments where comment_approved='spam' order by 1 asc" | grep -v "^CONCAT" >> THEY_BOTHER_ME

Check my example:

$ mysql -f -p --user=sakis mywordpress <<<"select distinct CONCAT('iptables -A INPUT -s ',comment_author_IP,'/32 -j DROP') from wp_comments where comment_approved='spam' order by 1 asc" | grep -v "^CONCAT" >> THEY_BOTHER_ME
Enter password:
$ head THEY_BOTHER_ME
iptables -A INPUT -s 113.161.128.232/32 -j DROP
iptables -A INPUT -s 117.121.208.254/32 -j DROP
iptables -A INPUT -s 118.141.141.7/32 -j DROP
iptables -A INPUT -s 118.194.1.157/32 -j DROP
iptables -A INPUT -s 119.235.27.100/32 -j DROP
...

You now have a simple recipe, named "THEY_BOTHER_ME", ready to be executed (as root):

$ su
# . ./THEY_BOTHER_ME

Make sure you hook "THEY_BOTHER_ME" at your system's start-up procedure and construct a cron/at job to periodically refresh it.

I've created a file named /etc/cron.daily/update_spammers.sh, with the following contents:

#!/bin/sh

fileloc="/etc/THEY_BOTHER_ME"

before=`cat "${fileloc}" | wc -l`
before=`echo ${before}`

cp "${fileloc}" /tmp/BOTHERS.$$

mysql -f --user=sakis --password=myextrastrongpassword mywordpress <<<"select distinct CONCAT('iptables -A INPUT -s ',comment_author_IP,'/32 -j DROP') from wp_comments where comment_approved='spam' order by 1 asc" | grep -v "^CONCAT" >> /tmp/BOTHERS.$$

sort /tmp/BOTHERS.$$ | uniq > "${fileloc}"
rm -f "/tmp/BOTHERS.$$"

. "${fileloc}"

after=`cat "${fileloc}" | wc -l`
after=`echo ${after}`

di=`expr ${after} - ${before}`
di=`echo ${di}`

printf "[%s] Spammers updated. Added %d new spammer(s) (Before: %d, After: %d)\n" "`date`" ${di} ${before} ${after}

You can find my own daily increasing script here.

Comments (0) Trackbacks (0)

No comments yet.


Leave a comment


No trackbacks yet.