Block new requests from source IP if it exceeds defined request rate (URI)

Problem this snippet solves:

Simple irule to watch requests to a specific URI over time. If the rate of requests to that URI goes over a set threshold, the source IP address will be placed into a shun table and all connections hitting the irule will be rejected for a set period.

How to use this snippet:

Items you will need to define:

  1. URI to match on
  2. Timeoutvalue - this is this timeframe in seconds that will define the rate of good requests allowed
  3. maxattempts - the number of good requests allowed in the timeoutvalue before being shunned
  4. shuntimeout - the number of seconds a source IP must wait with no blocks before being allowed to make requests again

Code :

when HTTP_REQUEST {
 #timeoutvalue is how long requests stay in the auth attempts table
 set timeoutvalue 30
 #maxattempts is the number of requests that can happen within the timeoutvalue before being shunned
 set maxattempts 20
 #shuntimeout is the time that the source IP will be blocked once it gets shunned
 set shuntimeout 60

 #reset every request if in shun table
 if { [table lookup -subtable "shun" [IP::client_addr]] > 0 } {
  table incr -subtable "shun" [IP::client_addr]
  set totaldrops [table lookup -subtable "shun" [IP::client_addr]]
  reject
  #log local0. "SHUN - Reset connection from [IP::client_addr] - Total: $totaldrops"
  return
 }

 if { ( [string tolower [HTTP::uri]] equals "/auth/login" ) } {
  #placeholder- send back fake auth response if in shun table

  #create large random number to act as an approx unique key - key collisions are not too detrimental
  set randkey [expr { int(100000000 * rand()) } ]
  #log local0. "URI match: created random key $randkey, adding to subtable for [IP::client_addr]"
  table set -subtable [IP::client_addr] $randkey 1 $timeoutvalue

  if { [table keys -subtable [IP::client_addr] -count] > $maxattempts} {
    log local0. "auth rate exceeded for [IP::client_addr], adding IP to shun table. Will unblock if no new conns for $shuntimeout seconds"
    #add source IP to the shun table with value of 1
    #note, this specific request was not blocked, but new connections from same src IP will be blocked on next request
    table set -subtable "shun" [IP::client_addr] 1 $shuntimeout
  }
 }
}
Published Mar 09, 2018
Version 1.0
  • Ekel's avatar
    Ekel
    Icon for Nimbostratus rankNimbostratus

    Hi,

     

    I am new on this. This is great. Can I see the log local0 from the f5 frontend? or it´s only from ssh?

     

    Is it possible add a whitelist ip from the security policy?

     

    Regards