HTTP Request Throttle
Problem this snippet solves:
iRule to limit the number of requests clients can make within a certain amount of time. Units used are requests/minute but this could be changed to requests/sec pretty easily. Once users hit a predefined limit of requests per minute they are throttled. Clients can also be blacklisted (automatically restricted to a very low rate) or whitelisted. This rule as it is shown here has a very low limit as it only applies to certain URLs. If you remove those 'if' statements then you will need to allow many more requests as most web pages have a number of objects per page. This has not been tested against production traffic so the impact on the BIG-IP is not known.
Code :
# This is a complete rewrite that is CMP-friendly, see older TMOS v9 code below. ## HTTP Request Throttling ## ## This I-Rule allows only "maxReqs" HTTP requests within "timeout" interval. ## This version throttles by URI and allows IP address whitelists. IP address can be in ## the IP header or the X-Forwarded-For HTTP header. ## ## CMP compatible: Yes ## ## This rule requires: ## A default pool so that the session table can be used and to forward requests. ## ## 09/14/2014, Irule revised to use CMP compatible commands. ## - "static" is added to global variable names. ## - arrays replaced with subtables. ## ## This rule tested on: ## TMOS v11.6.0, should work on an 11.x version ## LTM ## when RULE_INIT { # This defines the maximum requests to be served within the timing interval defined by the static::timeout variable below. set static::maxReqs 4; # Timer Interval in seconds within which only static::maxReqs Requests are allowed. # (i.e: 10 req per 2 sec == 5 req per sec) # If this timer expires, it means that the limit was not reached for this interval and the request # counting starts over. # Making this timeout large increases memory usage. Making it too small negatively affects performance. set static::timeout 2; } when HTTP_REQUEST { # The iRule allows throttling for only sepecific URIs. You list the URIs_to_throttle # in a datagroup. URIs_to_throttle or Methods_to_throttle. # if you need to throttle by Method use an statement like this: # if { [class match [HTTP::uri] equals URIs_to_throttle] } # Note: a URI is everything after the hostname: e.g. /path1/login.aspx?name=user1 # if { [class match [HTTP::uri] equals URIs_to_throttle] } { # The following expects the IP addresses in multiple X-forwarded-for headers. It picks the first one. if { [HTTP::header exists X-forwarded-for] } { set client_IP_addr [getfield [lindex [HTTP::header values X-Forwarded-For] 0] "," 1] } else { set client_IP_addr [IP::client_addr] } # The matching below expects a datagroup named: Throttling_Whitelist_IPs # The Condition of the if statement is true if the IP address is NOT in the whitelist. if { not ([class match $client_IP_addr equals Throttling_Whitelist_IPs ] )} { set getcount [table lookup -notouch $client_IP_addr] if { $getcount equals "" } { table set $client_IP_addr "1" $static::timeout $static::timeout # record of this session does not exist, starting new record, request is allowed. } else { if { $getcount < $static::maxReqs } { # log local0. "Request Count for $client_IP_addr is $getcount" table incr -notouch $client_IP_addr # record of this session exists but request is allowed. } else { HTTP::respond 403 content {HTTP Request denied Your HTTP requests are being throttled. } } } } } }
- MohanadCirrostratus
Thanks for the irule, i managed to limit 1 request per minute for specific URL
- oedo808_68685Altostratus
Oh hey, sorry I missed the other notifications. I will post the modified version and link back here.
Once again, sorry I missed these requests, here is a link to it: https://devcentral.f5.com/s/articles/http-request-throttle-by-ip-and-useragent-1032
- AlexDeMarcoNimbostratus
I would be interested in the code mentioned as well. Thank you in advance.
- John_HNimbostratus
Hi oedo808,
I would also like the code you mentioned, specifically to address "The static variables needed to be tuned quite a bit, I don't recall what the final values were and I no longer have access to the production rule but I can get it if anyone is interested."
Thanks!
Hi oedo808
Thanks for the update. Can I have the code you mentioned? I have to apply in production with high traffic.
- MrVJTod_64267Nimbostratus@oedo808 : interested in your modified code.
- oedo808_68685AltostratusI made a variation of this rule for rate limiting individual IP addresses and UserAgents, not to specific URIs but to all virtual servers covered by the rule, testing for x-forwarded-for, etc.. My tests performed very well so we tried it during a load test. The static variables needed to be tuned quite a bit, I don't recall what the final values were and I no longer have access to the production rule but I can get it if anyone is interested. We used it last night in production and it was very effective against rule breaking bots that are causing performance impact.