26-Mar-2021 14:44
I am trying to create an iRule that will rate limit connections to an exchange autodiscover.xml file. We are coming from a netscaler that will keep the session open if the limit is reached, and allow it to start passing traffic once the rate limiting has timed out. I have almost been able to get this to work with an iRule. I can get the rate limiting to work, but if the threshold has been exceeded the connection closes with an HTTP 403 error (by design). Here is what I have for the iRule:
## 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.
##
## This rule requires:
## A default pool so that the session table can be used and to forward requests.
##
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 1000;
# 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 1;
}
when HTTP_REQUEST {
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 {
<html>
<head>
<title>HTTP Request denied</title>
</head>
<body>Your HTTP requests are being throttled.</body>
</html>
}
}
}
}
}
}
I was looking at using something with the after command, but am still not sure how to go about implementing it. I was thinking of doing something like this in that last else statement:
}else {
while {$getcount > $static::maxReqs} {
after 1000
incr $getcount -1
}
}
Would something like this work? I don't have access to implement this at this moment, but would be something that I put into place probably in the next week or so.
27-Mar-2021 01:29
Did you try using a rate limiting rate class?
https://techdocs.f5.com/kb/en-us/products/big-ip-aam/manuals/product/aam-concepts-11-6-0/4.html
https://clouddocs.f5.com/api/irules/rateclass.html
You may also attach a traffic class under the VIP that matches the destination IP address is the one hosting autodiscover.xml
https://techdocs.f5.com/en-us/bigip-14-1-0/big-ip-local-traffic-management-basics-14-1-0/about-traffic-classes.html
31-Mar-2021 15:37
I've looked into those, and it appears that rate limiting classes and traffic classes are applied from a VS context and affects the amount of traffic going through the entire VS. I am trying to get this narrowed down to a per user basis.
I'm still a little new to creating my own iRules, but there's got to be something that will let a session stay open until a table count threshold has been met.
31-Mar-2021 23:57
About rate class it should be applied only to packets matching the iRule if statement not every packet for the VIP will be affected.
Try looking into https://support.f5.com/csp/article/K14813 and "Understanding iRule mitigation" that has a SIP example that you may try to modify for your needs.