Blocking DOS attacks
April 21, 2009
A member of Devon CFUG recently had a problem where one of his sites was being heavily hit by a bot that didn't comply with the crawl-delay setting in robots.txt, which was causing performance issues. After pondering this for a bit a I thought I'd have a go at creating a script to detect and block rogue bots (or something more mailicous). This is what I came up with. It needs to be placed in the onRequestStart method of Application.cfc and you'll need to create the application.remoteIP struct in onApplicationStart.
<cfset var hitsPerSecond = 0 />
<cfset var durationInSeconds = 0 />
<cfset var banrequest = False />
<!---
trap potential DOS attack. Check for:
- multiple requests within a short period of time.
- unknown user-agent
- agent doesn't support http sessions
--->
<!---
First we need to look for suspicious activity before checking requests per second
so that we don't actually create a performance issue by checking!
--->
<cfif CGI.HTTP_CONNECTION EQ "Close">
<!--- compare against a whitelist of allowed bots that comply with the crawl-delay setting in robots.txt--->
<cfif ReFindNoCase( "(Slurp|msnbot|googlebot)", CGI.HTTP_USER_AGENT ) EQ 0>
<!--- unknown agent treat as suspicious --->
<cflock scope="application" timeout="15">
<cfif !StructKeyExists( application.remoteIP, CGI.REMOTE_ADDR )>
<cfset application.remoteIP[ CGI.REMOTE_ADDR ] = { firsthit=Now(), hitcount=1 } />
<cfelse>
<!--- increment hitcount --->
<cfset application.remoteIP[ CGI.REMOTE_ADDR ].hitcount = application.remoteIP[ CGI.REMOTE_ADDR ].hitcount + 1 />
</cfif>
<!--- let the agent have 10 requests before we start checking --->
<cfif application.remoteIP[ CGI.REMOTE_ADDR ].hitcount GT 10>
<!--- agent has exceed 10 hits so need to see how many hits per second --->
<cfset durationInSeconds = DateDiff( 's', application.remoteIP[ CGI.REMOTE_ADDR ].firsthit, Now() ) />
<cfif durationInSeconds GT 0>
<cfset hitsPerSecond = application.remoteIP[ CGI.REMOTE_ADDR ].hitcount / durationInSeconds />
<cfif hitsPerSecond GT 2>
<!--- agent is making multiple requests per second, time to block! --->
<cfset banrequest = True />
</cfif>
</cfif>
</cfif>
</cflock>
</cfif>
</cfif>
<cfif banrequest>
<!--- could add to an array of banned IP addresses instead --->
<cfabort showerror="Our server is current experiencing a high number of connections. Please try again later." />
</cfif>
I should stress that this is just my initial attempt and has not been tested in the wild, but hopefully it might prove interesting.
- Posted in:
- ColdFusion
3 comments
Leave a comment
If you found this post useful, interesting or just plain wrong, let me know - I like feedback :)





>> <cfset durationInSeconds = DateDiff( 's', application.remoteIP[ CGI.REMOTE_ADDR ].firsthit, Now() ) />
>> <cfif durationInSeconds GT 0>
isn't it possible for a bot/hacker to send 10+ requests per second?
>> <cfif !StructKeyExists ...
interesting! does that actually work? in a <cfset>? i am going to go and try it now!
Azadi
Comment by Azadi Saryev – April 21, 2009
have you had any other feedback on this?
Comment by Sebastiaan – May 13, 2009
If those options aren't available, then the code above should work, although I think it would need to clear the application.remoteIP struct if it becomes too large so that it doesn't have an adverse affect on the application.
Comment by John Whish – May 14, 2009