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:
You now have to use that information into constructing this single-row command:
mysql -f -p --user=DB_USERDB_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=myextrastrongpasswordmywordpress <<<"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}
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:
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.
You can find my own daily increasing script here.