Forum Discussion

Baqar_Husain_81's avatar
Baqar_Husain_81
Icon for Nimbostratus rankNimbostratus
Apr 11, 2006

Redirect an http request based on number of queries

Is there any way in v9 irules to restrict (i.e. redirect to another page) a specific client IP access if they've made say > 20 requests on a specific page in a 10 second timespan?

 

 

Thanks.

3 Replies

  • There are several examples of this in the forum that you can search for. Here's one:

     

     

    http://devcentral.f5.com/Default.aspx?tabid=28&view=topic&forumid=5&postid=7071

     

     

    Write back if you have questions!
  • actually the requirements have changed a bit ... it's not the source ip, but an http header value. if there is a string match say 30 times every minute i would need to redirect that connection someplace else.

     

     

    the difficulty i'm having is understanding how the irule can track (global variable?) the number of times such a request is made.

     

     

    if i read the link you provided correctly, there's no way to track it.
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Your problem is a bit different than Zape's.

    He wanted to limit concurrent sessions.

    You're looking for a request rate limit.

    There is now a timeout function in the session table, and I've requested a way to count session table entries by filter, so once we have that, both his request and yours will be considerably easier to address.

    In the meantime, I recently created this rule for a customer who needed to limit the number of POSTs by the same client within a specified time window. You'll probably want to change the 401 and 503 responses to redirects, but it just so happens we also used a header to differentiate clients. This was developed for a low volume application, so I can make no representations as to performance under load, but this should be very close to what you're looking for:

    
    when RULE_INIT {
      set ::maxRate 10
      set ::windowSecs 10
      init array if non-existent
      array set ::postHistory { }
      wipe array if it already existed
      array unset ::postHistory
    }
    when HTTP_REQUEST {
      if { [HTTP::method] eq "POST" } {
        if {[HTTP::header exists User]} {
          set myUserID [HTTP::header User]
        } else {
          HTTP::respond 401
          return
        }
        set currentTime [clock seconds]
        set windowStart [expr {$currentTime - $::windowSecs}]
        find POSTs for this userID
        set postCount 0
        foreach { requestID requestTime } [array get ::postHistory ${myUserID}*] {
          count POSTs with start time > $windowStart, delete the rest
          if { $requestTime > $windowStart } {
            incr postCount 1
          } else {
            unset ::postHistory($requestID)
          }
        }
        if { $postCount < $::maxRate } {
          add new record to array w/myUserID.uniquekey + currentTime
          set requestID "${myUserID}.[substr [AES::key 128] 10 16]"
          set ::postHistory($requestID) $currentTime
        } else {
          otherwise rate is exceeded, respond with 503 (temp unavail)
          HTTP::respond 503
          return
        }
      }
    }

    HTH

    /deb