Anyone with a WordPress blog will no doubt have experienced that once Google indexes it at all, lots of comments start appearing. Often the comments look like they could be genuine and are often complimentary of your blog or writing style. Sometimes they offer what appears to be constructive feedback on your site not functioning in a particular browser. The one thing that they usually have in common is that they tend to have a link or email address that points to something spammy. The links usually want you to buy or view something that you do not want to.

The good news is that if your blog is self-hosted, there are some simple techniques for reducing comment spam. The following instructions are for Linux users who have root access to their server.

If you have comment approvals turned on, you'll have to manually approve comments before they are displayed. This gives you the added advantage that when you see comments that appear to be spam, you can mark them as such. WordPress actually records the IP address of all commenters as well as whether or not they are spam in its database. This means that once there are more than a couple of spammy comments from the same IP, it is relatively straightforward to blacklist them. A simple method to do this is to add them to a firewall rule chain which causes all packets from the specified IP to be dropped. This not only stops them from adding comment spam, it also stops them from viewing your site altogether.

To set this up on Linux, you need to create a chain in iptables (as root):

$ /sbin/iptables -N BLACKLIST

Then you can schedule the following script to run every couple of hours.

#!/bin/sh

# database credentials
username='wordpress_user'
details='wordpress_pwd'
db_name='wordpress_dbname'

# tune this to your preference: will blacklist an IP address after n comments marked as spam
spam_count=2

query="select comment_author_IP, comment_approved, count(*) from wp_comments group by comment_author_IP, comment_approved having count(*) > $spam_count order by count(*) desc"

blacklist=`mysql -D ${db_name} -u ${username} -p${details} << --EOF-- | grep spam | awk '{print $1}'
$query
--EOF--`

blacklisted=`iptables -L BLACKLIST -vn | awk '$3 ~ /DROP/ { print $8 }'`
for addr in $blacklist; do
echo $blacklisted | grep $addr > /dev/null 2>&1
if [ $? -ne 0 ]; then
logger -t wp-blacklister "Blacklisting $addr for > $spam_count WP spammed comments"
iptables -A BLACKLIST -s $addr -j DROP
fi
done

This technique has one disadvantage in that you can occasionally block some users that you don't want to. This is rare but could occur if a spammer comes from the same IP address as a genuine user: for example if they are both using the same proxy server or gateway. As a result, it is necessary to flush the BLACKLIST firewall chain periodically - removing all items from it. This usually works ok because once persistent spammers realise that they are no longer able to connect to your site, they give up and try someone else's site instead.

You can flush the BLACKLIST chain by setting up a scheduled job to execute the following command:

iptables -F BLACKLIST

Hopefully, this should start to reduce your WordPress spam fairly quickly.