pf » Battling Comment Spam
Battling Comment Spam

Fighting comment spam seams like a never ending battle. I've done a lot over the last few years to try and squash it on my blog.
I started out by implementing a list of words that would trigger the comment to be blocked. I found myself updating this list on a weekly basis, never staying on top of it.
I solved that problem by implementing the Bayesian Filter CFC from fusionKit. The bayes filter has worked really well, and produced a suprisingly low number of false positives.
Now just over the weekend I was flodded with a ton of comment spams that were written well enough to get past the bayes filter. They were also all submitted within a few minutes, so there was no time to train my bayes filter.
I'm not a big fan of statically blocking IP addresses, since the owners of IP addresses can change over time. However I think temporary blocks on IP's are OK, so I wrote a little rate limiter that will block IP's that try to post more than 1 comment within a 5 minute time span or IP's that have attempted to post a large number of comments.
I'm sure some of you have probably experienced the same problem, so here you go:
<cfif IsDefined("application.rate_limiter")>
<cfif StructKeyExists(application.rate_limiter, CGI.REMOTE_ADDR)>
<cfif application.rate_limiter[CGI.REMOTE_ADDR].attemps GT 1 AND DateDiff("n", application.rate_limiter[CGI.REMOTE_ADDR].last_attempt, Now()) LT 5>
<p>You are posting too many comments too fast, please slow down and wait 5 min.</p>
<cfset application.rate_limiter[CGI.REMOTE_ADDR].attemps = application.rate_limiter[CGI.REMOTE_ADDR].attemps + 1>
<cfset application.rate_limiter[CGI.REMOTE_ADDR].last_attempt = Now()>
<cfabort>
<cfelseif application.rate_limiter[CGI.REMOTE_ADDR].attemps GT 20>
<p>You have made too many attempts to post a comment. Please try back in a few days.</p>
<cfset application.rate_limiter[CGI.REMOTE_ADDR].attemps = application.rate_limiter[CGI.REMOTE_ADDR].attemps + 1>
<cfset application.rate_limiter[CGI.REMOTE_ADDR].last_attempt = Now()>
<cfabort>
<cfelse>
<cfset application.rate_limiter[CGI.REMOTE_ADDR].attemps = application.rate_limiter[CGI.REMOTE_ADDR].attemps + 1>
<cfset application.rate_limiter[CGI.REMOTE_ADDR].last_attempt = Now()>
</cfif>
<cfelse>
<cfset application.rate_limiter[CGI.REMOTE_ADDR] = StructNew()>
<cfset application.rate_limiter[CGI.REMOTE_ADDR].attemps = 1>
<cfset application.rate_limiter[CGI.REMOTE_ADDR].last_attempt = Now()>
</cfif>
<cfelse>
<cfset application.rate_limiter = StructNew()>
<cfset application.rate_limiter[CGI.REMOTE_ADDR] = StructNew()>
<cfset application.rate_limiter[CGI.REMOTE_ADDR].attemps = 1>
<cfset application.rate_limiter[CGI.REMOTE_ADDR].last_attempt = Now()>
</cfif>
Related Entries
- Trick or Treat - Web 2.0 Goodies for ColdFusion - October 31, 2006
- Analyzing Words in Spam Emails - August 3, 2005
- How I block comment spam - July 19, 2005
http://devnulled.com/cfakismet
We put it on our blog (http://blog.d-p.com) and love it.
You might want to adjust the 1 comment per 5 minutes to at least 2 commments. 1 seems a little to strict--especially in the case where someone wants to post an addendum to what they typed.
Actually it does allow for two comments since it says GT 1 and the attempts are incremented after that point. I wasn't clear about that in my post however. Thanks for pointing that out.
- CFSCRIPT Cheatsheet
- 3 New Image Effects for ColdFusion 8
- Googlebot to Submit Web Forms
- ColdFusion 8 Update 1 Fixes some Image Processing Quirks
- 10 Most Useful Image Functions in ColdFusion 8
- Speaking at NYC CFUG This Week
- Adobe AIR Tutorial for HTML / JavaScript Developers
- INFORMATION_SCHEMA Support in MySQL, PostgreSQL
RSS
add to del.icio.us
Pete Freitag is a software engineer, and web developer located in









