Forum Discussion
Universal Persistence with X-forwarder
- Jul 20, 2016
A formatted version of the "Per VS" rate limiting. You can apply the same irule to all standard VS using UIE persistence.
when RULE_INIT { set static::maxReqs 3; set static::timeout 60; } when HTTP_REQUEST { set vs [URI::basename [virtual]] 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] } if { ([HTTP::method] eq "GET") and ([class match [string tolower [HTTP::uri]] ends_with $vs_URI_LIST_TO_LIMIT] ) } { whitelist if { [class match [IP::client_addr] equals $vs_ips_whitelist] }{ return } set getcount [table lookup -notouch "$vs_$client_IP_addr:[HTTP::uri]"] if { $getcount equals "" } { table set "$vs_$client_IP_addr:[HTTP::uri]" "1" $static::timeout $static::timeout } else { if { $getcount < $static::maxReqs } { table incr -notouch "$vs_$client_IP_addr:[HTTP::uri]" } else { reject } } } persist uie $clientip } when HTTP_RESPONSE { persist add uie $clientip }
Hi Yann
One more query is how to rate limit the connections per XFF IP address? Do we need to modify the rule or write something new?
Regards,
Sumanta.
- Yann_DesmarestJul 20, 2016Cirrus
Hi Sumanta,
Please find below a working irule for your need that I already answered here :
iRule - URI/Referer Rate limit per minute
The below iRule allow you to do rate limiting by Client IP per URI. You can change the if condition to match whatever you want :
when RULE_INIT { set static::maxReqs 3; set static::timeout 60; } when HTTP_REQUEST { 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] } if { ([HTTP::method] eq "GET") and ([class match [string tolower [HTTP::uri]] ends_with URI_LIST_TO_LIMIT] ) } { whitelist if { [class match [IP::client_addr] equals ips_whitelist] }{ return } set getcount [table lookup -notouch "$client_IP_addr:[HTTP::uri]"] if { $getcount equals "" } { table set "$client_IP_addr:[HTTP::uri]" "1" $static::timeout $static::timeout } else { if { $getcount < $static::maxReqs } { table incr -notouch "$client_IP_addr:[HTTP::uri]" } else { reject } } } persist uie $clientip } when HTTP_RESPONSE { persist add uie $clientip }
- Sumanta_88744Jul 20, 2016Cirrus
Hi Yann
Thanks a lot. I actually have two virtual servers, one standard http type with persistence and the other Fast L4 type without persistence. Will the above iRule you wrote, go into the persistence profile of the first vs? And how do I write the second rule for the other vs? Just apply directly to vs and remove the "persist uie $clientip" and "persist add uie $clientip" ?
Regards,
Sumanta.
- Sumanta_88744Jul 20, 2016Cirrus
Actually I was wondering whether or not modifying the existing persistence iRule is needed or not? Maybe it is easier to just add a new single iRule and apply it to both virtual servers as needed.
- Yann_DesmarestJul 20, 2016Cirrus
You can add another irule but you will need again to retrieve the XFF header.
You can define two irules, one with UIE and one another without UIE. and apply the corresponding irule depending on the Virtual Server settings.
Please note, that you need to have a standard VS to retrieve the XFF. On Perf L4 VS, you cannot use those irules.
The interesting thing using table and subtables is that those tables are shared among all VS using the same irule. So, If you want to apply a Per VS rate limiting, you will need to change a little bit the irule code.
- Sumanta_88744Jul 22, 2016Cirrus
Hi Yann
Thanks again. I think I'll try to use XFF based rate limit irule on the standard vs only. And for the performance L4 vs, maybe I'll stick to "Per Virtual Server and Source Address" as per sol01155812.
- Sumanta_88744Jul 22, 2016Cirrus
Hi Yann
In the above irule, can I do a concurrent http session limit on the vs, based on single source IP? I followed sol01155812 but I don't think I could achieve per source IP based, it only no. of connections per sec.
What do I need to change here in order to say limit 20K per source IP?
when RULE_INIT {
set static::maxReqs 3; set static::timeout 60;
Also, how do I apply limit to all IPs instead of whitelist? Can "ips_whitelist" have no value and still work? Later, if needed, I can insert a data group named "ips_whitelist" and add IPs. Now I need to apply this i-rule to all source IP.
whitelist
if { [class match [IP::client_addr] equals ips_whitelist] }{ return
- Yann_DesmarestJul 22, 2016Cirrus
Hi,
The whitelist is used to define IP addresses that should not have rate limit activated. If you d'ont use it, you can remove this part from the irule.
maxReqs and timeout variables allow you to define the number of allowed concurrent connections (maxReqs) for a specific windows (timeout).
You should check the timeout value configured on your TCP profile and adapt the timeout accordingly. Then you can configure for example :
when RULE_INIT { set static::maxReqs 20000; set static::timeout 1800; }
- Sumanta_88744Jul 24, 2016Cirrus
This is what I get after commenting out XFF and persistence.
when RULE_INIT { set static::maxReqs 20000; set static::timeout 1800; } when HTTP_REQUEST {
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] } if { ([HTTP::method] eq "GET") and ([class match [string tolower [HTTP::uri]] ends_with URI_LIST_TO_LIMIT] ) } {
whitelist to be inserted for exception
if { [class match [IP::client_addr] equals ips_whitelist] }{
return
} set getcount [table lookup -notouch "$client_IP_addr:[HTTP::uri]"] if { $getcount equals "" } { table set "$client_IP_addr:[HTTP::uri]" "1" $static::timeout $static::timeout } else { if { $getcount < $static::maxReqs } { table incr -notouch "$client_IP_addr:[HTTP::uri]" } else { reject } } }
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