Forum Discussion
Limiting Duplicate HTTP GETs
Hi folks. I'm new to DevCentral so I apologize if I'm posting in the wrong place. I've been running a couple of old v4 BIG-IPs for years and just recently made the jump to a couple of LTM-1600's with 10.0.1. That said, we occasionally receive duplicate GETs to one of our IIS/ColdFusion-based sites, from a single user. When this flood of GETs occurs, the requests come through at such a high rate (upwards of 50 requests per second) that it's causing us some headaches. Therefore, I need to develop an iRule that will handle the duplicates and discard them before they make it to the site.
To provide some additional information, we typically have many users NAT'd behind the same IP, but the floods originate from only one unique workstation. So it's really not feasible to block or discard requests based on IP. The good news is that our app sets a cookie which contains a number unique to each workstation. This cookie is passed back to our servers with each GET, so if we can leverage a rule which uses this cookie to identify the duplicates, that would be great. Ideally, I'd like to have a rule which would look for duplicate GETs (containing the same URL and unique string in our custom cookie) and reject subsequent requests which surpass a predetermined threshold.
I know this isn’t a lot of information to go off of and I can certainly provide more information as needed. After some poking around, I suspect there may be an existing rule which would do what we want to do. I stumbled across the following rule which appears to limit the number of POSTs: http://devcentral.f5.com/Wiki/iRules.RateLimit_HTTPRequest.ashx
It’s possible that rule could be adapted to help us out here. I’ve also seen this rule: http://devcentral.f5.com/wiki/iRules.HTTPRequestThrottle.ashx
The first rule seems to filter based on an authorization header, while the latter rule seems to filter on IP. Both rules would need to be adapted to our scenario, but being completely new to iRules, I’m not sure which would work better for us. I’m certainly able to provide more details, as needed, but I’d love to hear any ideas you guys might have. Thanks much for the help.
-Ryan
- ryan_111816
Nimbostratus
Sorry to bump this, but does anyone have any thoughts on this? - ryan_111816
Nimbostratus
Aaron - since you seem to be responding to most of the posts in here, maybe you can point me in the right direction. Since I'm not getting any help, would you recommend that I contact F5 support? The funny thing is that we just recently purchased the LTM-1600's over a competitor's product, specifically for the flexibility of iRules. It was explained to F5 sales that I'm new to iRules, even though I had a few v4 BIG-IPs already. DevCentral was then used as an additional selling point. I understand that DevCentral is a "community driven innovation", as the fancy logo states, but where should a customer turn when no help is provided? Am I on my own here? - hoolio
Cirrostratus
Hi Ryan, - hoolio
Cirrostratus
Hi Ryan, - ryan_111816
Nimbostratus
Thanks for the response Aaron. Here are some answers: - L4L7_53191
Nimbostratus
For this particular use case 10.0.1 may come to the rescue. - L4L7_53191
Nimbostratus
FWIW, here is a link to Colin's post on the after command, with sample code. This one is obviously all l4 stuff, but conceptually it's very similar.
-Matt
- ryan_111816
Nimbostratus
Matt, - hoolio
Cirrostratus
Hi Matt / Ryan,when RULE_INIT { Log debug messages to /var/log/ltm? 1=yes, 0=no set static::get_debug 1 Name of the session cookie that the application sets set static::session_cookie "workstationid" Datagroup name containing the paths to limit GET requests to The requested path is checked to see if it starts with any path string in this class set static::get_class "get_limit_paths_class" Timeout to track requests for (in seconds) set static::timeout 10 Max number of requests to a restricted path per the timeout period set static::max_requests 1 HTML content to send to clients who exceed the max number of requests You shouldn't need to escape any characters in between the curly braces (except curly braces). set static::reject_html [subst -nocommands {Give it a restYou're making too many requests}] } when HTTP_REQUEST { if {$static::get_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: [HTTP::method] to [HTTP::host][HTTP::uri]"} Exit this event in this rule, if request is not a GET if {not ([HTTP::method] eq "GET")}{ if {$static::get_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: Exiting for method [HTTP::method]"} return } Exit this event in this rule if request is not to a restricted path if {[class search $static::get_class starts_with [HTTP::path]]}{ if {$static::get_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: Exiting for path [HTTP::path]"} return } Exit this event in this rule if request does not include the session cookie if {[HTTP::cookie $static::session_cookie] eq ""}{ if {$static::get_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: Exiting for no session cookie"} return } If we're still executing here, it's a GET request to a restricted URI with a session cookie Check if the cookie / path combo has a request count set count [session lookup uie "[HTTP::cookie $static::session_cookie][HTTP::path]"] if {$static::get_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: count: $count"} Check if session table entry exists if {$count eq ""}{ No session table entry for this cookie/path, so add one session add uie "[HTTP::cookie $static::session_cookie][HTTP::path]" 1 $static::timeout if {$static::get_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: Initialized count for\ [HTTP::cookie $static::session_cookie][HTTP::path]"} } else { Check if count is less than max allowed if {$count < $static::max_requests}{ Increment the session table entry count for this cookie / path session add uie "[HTTP::cookie $static::session_cookie][HTTP::path]" [incr count] $static::timeout if {$static::get_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: Incremented count to $count\ for [HTTP::cookie $static::session_cookie][HTTP::path]"} } else { Client is over maximum allowed number of requests to this URI HTTP::respond 503 content $static::reject_html if {$static::get_debug}{log local0. "[IP::client_addr]:[TCP::client_port]: $count over limit $static::max_requests\ for [HTTP::cookie $static::session_cookie][HTTP::path]"} } } }
- hoolio
Cirrostratus
Another thing to keep in mind is that using a global array to track the requests would break CMP compatibility (Click here) for the VIP the iRule is enabled on.
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com