Excessive_404_Blacklist

Problem this snippet solves:

This iRule will block ALL further site access to source IP addresses that exceed a certain number of HTTP requests to server resources that results in a 404 not found error. This script is useful for scenarioes where you have a system that contains fixed paths with files and want to keep people from brute-forcing those filenames.

By default, this will apply when a source IP gets 100 errors in a 10 minute period - and will block site access for another 10 minutes. This will slow down a brute force attack significantly and provide you with some log details you can use to troubleshoot.

This rule bases its logic on the incoming source IP, so if you have a large number of users coming through proxies you may want to consider setting a relatively high threshold. If you don't like using this with a source IP, it's possible to rewrite this logic to use a cookie instead, but most brute-force tools don't honor cookies -- source IP is still the most logical choice, even if not the most precise.

Code :

when RULE_INIT {

# excessive_404_blacklist
# v1.0 - Joel Moses
#
# Block all site access to source IP addresses that exceed a
# certain number of HTTP requests to non-existant objects within
# a fixed period of time. Useful for blocking harvesting 
# activities (or at least slowing them down significantly).
#
# Use this iRule at your own risk. If your site has a propensity
# to throw off lots of 404 errors in normal operation, you may
# inadvertently find valid users blocked.

# Set the maximum number of 404 errors for a client IP in a
# certain period of time. The default setings are one hundred
# 404 errors in ten minutes. Following this, the client IP
# address will be blacklisted and an error page displayed for
# the next ten minutes.

        set static::maxerrors 100
set static::maxperiod 600
set static::holdtime 600

# If for any reason you need to rid yourself of a 
# blacklist, you can send the VIP running this iRule
# a query string parameter in the format:
#   http(s)://sitename.com/?DeleteKey=
# where the case-sensitive key is defined below. Consider
# this a "get out of jail free" card in case something 
# goes totally wrong.

set static::deletekey "DeleteAllBlacklistData"

# If set to true, log all blacklisted source IP addresses
# to the LTM log.

set static::log_offender 1

# If set to true, this will create unique tables per VS
# for blacklisting activities.
# This is good if you wish to apply the iRule across multiple
# virtuals but want blocking tables to be created for each
# individual virtual and not shared across multiple ones.

set static::unique_tables_per_virtual 1

# Display this block page for all attempts that hit the blacklist.

set static::blockpage {

Error

403 - Forbidden

Too many requests for invalid objects. Your access is denied. } } when CLIENT_ACCEPTED { # Collect the remote IP address. set srcip [IP::remote_addr] if { ($static::unique_tables_per_virtual ) } { set blacklist_name "blacklist_[virtual]" set countlist_name "[IP::remote_addr]_[virtual]" } else { set blacklist_name "blacklist" set countlist_name "[IP::remote_addr]" } } when HTTP_REQUEST { # If the request has a DeleteKey parameter that matches # the setting supplied in RULE_INIT for static::deletekey, # delete the blacklist subtable (values and keys). if { [URI::query [HTTP::uri] DeleteKey] equals "$static::deletekey" } { log local0. "BLACKLIST: Table manually cleared by [IP::remote_addr]." table delete -subtable $blacklist_name -all } } when HTTP_RESPONSE { # If the source IP is already in the blacklist table, # respond with the block page. if { [table lookup -subtable $blacklist_name $srcip] != "" } { HTTP::respond 403 content "[subst $static::blockpage]" return # If the source IP has gotten a 404 but does not currently # have a unique subtable entry, create a new offender. } elseif { ([table lookup -subtable $countlist_name "count"] == "") && ([HTTP::status] equals "404") } { set count 1 table add -subtable $countlist_name "count" $count indef $static::maxperiod # If the source IP has a 404 and is a repeat offender, # increment the count within the table. } elseif { ([table lookup -notouch -subtable $countlist_name "count"] != "") && ([HTTP::status] equals "404") } { set count [table incr -notouch -subtable $countlist_name "count"] # If the maximum number of errors has been reached, # add the source IP to the blacklist and get rid of the # offender's unique table (he'll get a new one after his holdtime # is over). Respond with the error page. if { $count >= $static::maxerrors } { table add -subtable $blacklist_name $srcip "blocked" indef $static::holdtime table delete -subtable $countlist_name -all HTTP::respond 403 content "[subst $static::blockpage]" if { ($static::log_offender) } { log local0. "BLACKLIST: [IP::remote_addr] is blacklisted on [virtual] for $static::holdtime seconds." } return } } }
Published Mar 17, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment