Recent weeks have brought a pile of new comment spam on this site. I’ve explored a few ways of mitigating the amount of crap I receive, and hpoefully wasting some spammer bandwidth. This includes various lookups that are built into the code that runs the site, dodgy posts get timed out for a few seconds.
A slightly simpler approach is to use mod_security in combination with one of the well knon spam blocklists — the spamhaus zen list is pretty good — to shield my comment submission queue a little.
Here’s the idea. When someone tries to submit a comment, first grab their IP address. Now look it up on some blocklists. If it is sketchy then return a 403, and set a flag that will deny that IP address access to the site for 5 days. Otherwise pass the comment on to the other antispam measures. If they do not flag it then accept the comment and say thanks.
The setup
The setup is as basic as can be, I installed mod_security from the debian repo thus $ sudo aptitude install libapache2-modsecurity
$ sudo a2enmod mod security
$ Enabling module mod-security.
To activate the new configuration, you need to run:
service apache2 restart
$ sudo apachectl graceful
Next, I had to do a very basic config for modsecurity, this is configured in /etc/modsecurity (surprisingly). I created a file called 10_basic.conf and added the folllowing to it SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess On
SecResponseBodyMimeType text/html text/plain text/xml
SecResponseBodyLimit 2621440
SecServerSignature Apache
SecComponentSignature 200911012341
SecUploadDir /var/asl/data/suspicious
SecUploadKeepFiles Off
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogType Concurrent
SecAuditLog /var/log/apache2/modsec_audit.log
SecAuditLogParts ABIFHZ
SecArgumentSeparator "&"
SecCookieFormat 0
SecRequestBodyInMemoryLimit 131072
SecDataDir /var/asl/data/msa
SecTmpDir /tmp
SecAuditLogStorageDir /var/asl/data/audit
SecResponseBodyLimitAction ProcessPartial
SecPcreMatchLimit 1000
SecPcreMatchLimitRecursion 1000
SecDebugLog /var/log/apache2/modsec_debug.log
SecDebugLogLevel 3
SecDefaultAction "phase:1,pass"
Next, I needed to add the logic for dealing with blocking spammy IPs and de-listing them after 5 days. Adjust as required. # Initialize collection and drop 3 points/day
SecAction "id:99999,phase:1,initcol:IP=%{REMOTE_ADDR},deprecatevar:IP.spam=3/86400,nolog"
# If there are >15 spam points for this IP, drop
# the connection and add 1 point (instead of 3, as below).
SecRule IP:spam "@gt 15" "id:99998,phase:1,setvar:IP.spam=+1,drop,setenv:spam=spam"
# Clear the default action for any later rules.
SecDefaultAction "phase:1,pass"
Finally in my vhost config I can add the actual RBL lookups and spam tagging logic. Note that these are chained rules. The first rule checks that we are using my comment creation URL, then next does the RBL lookup. Adding more rules is now a simple matter. Note that we normalise the path to avoid spammer submitting to URLs with multiple /s in them and that sort of thing. SecRule REQUEST_URI "^comment/create" "chain,id:300056,log,t:normalisePath,deny,msg:'Spam: Comment From user on RBL: zen.spamhaus.org'"
SecRule REMOTE_ADDR "@rbl zen.spamhaus.org" "setvar:IP.spam=15"
SecRule REQUEST_URI "^comment/create" "chain,id:300058,log,deny,t:normalisePath,msg:'Spam: Comment From user on RBL: bl.spamcop.net'"
SecRule REMOTE_ADDR "@rbl bl.spamcop.net" "setvar:IP.spam=15"
A quick restart of Apache and I saw a large reduction in spam comments getting through, for very little extra overhead.