Forum Discussion

____177053's avatar
Sep 20, 2017

How to limit http request rate

I wants to limit http request rate for some of URIs such as "/a" "/b" "/c",and I wrote one but it didn't work:

 

when HTTP_REQUEST { set start_time [clock seconds] set reqs_sec 0 if { [HTTP::request_num] > 3 } { log local0. "num:[HTTP::request_num]" if { [clock seconds] == $start_time } { log local0. "time:$start_time" if { $reqs_sec > 3 } { reject log local0. "reject from [IP::client_addr]" } incr reqs_sec return } } }

 

How to modify this one and make it limit 3-times http requests in 3 seconds?

 

Thanks a lot!

 

  • This one works! when HTTP_REQUEST {

    set lrqst 10
    set ltime 10
    set rtime 5
    if {[table lookup -notouch -subtable "blacklist" [HTTP::uri]] != "" }{
        reject
        log local0.warn "reject"
    }
    elseif { [table lookup -notouch -subtable "clientxdlist" [HTTP::uri]] == "" }{
        table set -subtable "clientxdlist" [HTTP::uri] 1 indefinite $ltime
    }
    elseif { [table lookup -notouch -subtable "clientxdlist" [HTTP::uri]] < $lrqst}{
        table incr -subtable "clientxdlist" [HTTP::uri]
    }
    else {
        table set -subtable "blacklist" [HTTP::uri] 1 indefinite $rtime
    }
    

    }

  • Hi,

    I think the following confition in your irule never match

        if { [clock seconds] == $start_time } { 
            log local0. "time:$start_time" 
            if { $reqs_sec > 3 } { 
            reject 
            log local0. "reject from [IP::client_addr]" 
            } 
            incr reqs_sec 
            return 
        } 
    

    Review this one. Indead "[clock seconds]" will return the clock in second at the time execute and your variable $start_time was set before, so it will never match...

  • This one works! when HTTP_REQUEST {

    set lrqst 10
    set ltime 10
    set rtime 5
    if {[table lookup -notouch -subtable "blacklist" [HTTP::uri]] != "" }{
        reject
        log local0.warn "reject"
    }
    elseif { [table lookup -notouch -subtable "clientxdlist" [HTTP::uri]] == "" }{
        table set -subtable "clientxdlist" [HTTP::uri] 1 indefinite $ltime
    }
    elseif { [table lookup -notouch -subtable "clientxdlist" [HTTP::uri]] < $lrqst}{
        table incr -subtable "clientxdlist" [HTTP::uri]
    }
    else {
        table set -subtable "blacklist" [HTTP::uri] 1 indefinite $rtime
    }
    

    }

  • I have modified the irule give by Bhanu to fit your need .

     This iRule limits the number of HTTP Requests from a specified client IP address to 3 HTTP Requests for 3 seconds
     A Data Group IP_Throttle_List will contain the IP addresses that require throttling
    
    when HTTP_REQUEST {
    
     Check if the IP address is within the defined list of addresses to throttle
    if { [class match [IP::client_addr] equals IP_Throttle_List ] } {
    
             Check if there is an entry for the client_addr in the table
            if { [ table lookup -notouch [IP::client_addr] ] != "" } {
             If the value is less than 3 increment it by one
                log local0. "Client Throttle: Value present for [IP::client_addr]"
                            if { [ table lookup -notouch [client_addr] ] < 3 } {
                            log local0. "Client Throttle: Number of requests from client = [ table lookup -notouch [client_addr] ]"
                            table incr -notouch [IP::client_addr] 1
                            } else {
                                log local0. "Client Throttle: Client has exceeded the number of allowed requests of [ table lookup -notouch [client_addr] ]"
                                 This else statement is invoked when the table key value for the client IP address is more than 3. That is, the client has reached the 3f request limit
                                        HTTP::respond 200 content {
                                            
                                            
                                            Information Page
                                            
                                            
                                              We are sorry, but the site has received too many requests. Please try again later.
                                            
                                            
                                        }
                           }
                } else {
                         If there is no entry for the client_addr create a new table to track number of HTTP_REQUEST. Lifetime is set to 3 seconds 
                        log local0. "Client Throttle: Table created for [IP::client_addr]"
                        table set [IP::client_addr] 1 3
                        }
    
    } else {
        return
    }
    
    }
    

    Hope it helps

    😉