Forum Discussion
Greenberg
Nimbostratus
Mar 08, 2012iRule to Limit Connections from Source IP to Destination IP
Guys,
Novice to iRules brings himself before you.
I've been given a requirement to Limit the number of Connections from a number of Source Hosts to a Destination.
This is where I've gotten to:-
bigpipe class 'conn_limit_Pi {
host <> {"<>"}
}'
bigpipe rule '_Pi_throttle_tcp_connections {
when CLIENT_ACCEPT {
set limit [class match [IP:client_addr] equals conn_limit_Pi]
set tbl "connlimit:[IP:client_addr]"
set key "[IP::client_addr][TCP::client_port]"
if { [table keys -subtable $tbl -count] >= $limit } {
reject
} else {
table set -subtable $tbl $key "ignored" <>
}
}
when CLIENT_CLOSED {
table delete -subtable $tbl $key
}'
Unfortunately I am unable to find how to target the Destination. Would another "Class" Statement do the Trick? And if so, how would I introduce this into the iRule to Target the Destination if ir Orginates from the Specific Source.
Thanks in Advance.
Chris.
14 Replies
- hoolio
Cirrostratus
Hi Chris,
It looks like you're limiting concurrent client connections. Do you have one destination IP to check? If so, you could add this check first in CLIENT_ACCEPTED:when CLIENT_ACCEPTED { if { not [IP::addr [IP::local_addr] equals 1.1.1.1] }{ return } ...
If you have more than one destination IP to check you could use a data group:when CLIENT_ACCEPTED { if { not [class match [IP:local_addr] equals conn_limit_destinations_dg] }{ return } ...
Either way, if you're not creating a subtable entry on every connection, you'd want to check if $key had been defined for that connection before trying to remove the key:when CLIENT_CLOSED { if {[info exists key]}{ table delete -subtable $tbl $key } }
Aaron - Greenberg
Nimbostratus
Hi Aaron,
Thanks for your Assistance with this. Not my strongest Subject 😞
The Requirement has changed alittle.
They want to limit the maximum number of connections to a Virtual to 100.
If it's below 100 then allow but if it's above 100, only allow the Connection if an existing cookie is detected.
Here is the Rule I've created Offlinebigpipe rule '_Pi_throttle_tcp_connections { when RULE_INIT { set ::max_connections 100 set static ::active_connections 0 } when HTTP_REQUEST { if {$::active_connections > $::max_connections} then { HTTP::respond 302 Location "Webpage.html" "Connection" "Close" "Cache-Control" "no-cache" "Pragma" "no-cache" TCP::close incr ::active_connections 1 elseif { [HTTP::cookie exists ] } then { persist uie [HTTP::cookie ] } } } when CLIENT_CLOSED { incr ::active_connections -1 }' - Greenberg
Nimbostratus
Guys,
I think I've solved it, subject to testing of course:-when RULE_INIT { set ::max_connections 100 set static::active_connections 0 } when HTTP_REQUEST { if { not [HTTP::cookie exists ] and $::active_connections > $::max_connections} { HTTP::respond 302 Location "" "Connection" "Close" "Cache-Control" "no-cache" "Pragma" "no-cache" TCP::close } { incr ::active_connections 1 } } when CLIENT_CLOSED { incr ::active_connections -1 } - hoolio
Cirrostratus
... - hoolio
Cirrostratus
What are you actually trying to accomplish? Do you want to limit the number of connections per client per second (a rate)? Or do you want to limit the number of concurrent connections per client over a time interval? Do you want/need to send an HTTP response if a client makes an HTTP request while over the limit? Do you want to allow clients who already have established a "session" with the virtual server to be able to exceed the limit and track this with a session cookie?
You'll want to avoid using global variables as they're not CMP compatible. You'll also want to not use a static variable to track a value that changes as static variables aren't synchronized across TMMs.
https://devcentral.f5.com/wiki/iRules.CMPCompatibility.ashx
https://devcentral.f5.com/wiki/iRules.static.ashx
Aaron - Greenberg
Nimbostratus
Hi Aaron,
I want to limit the number of concurrent connections to a maximum of 100 and if 100 is reached then a HTTP 302 is sent to the 101st Connection.
Basically it's a Connection Limiting exercise to reduce load on the Internal Web Servers.
But, we want to allow connections if a specific cookie is detected in the HTTP Header.
Logically look at the rule we would want.
* When a Connection is attempted the to the Virtual Server the Rule will Apply
* Maximum Number of Connections 100
* If the Specific Cookie exists in the Header and the Maximum Connections is Greater than the Active Connections the Respond with a HTTP 302 Message which is called from a Specific Webpage and the TCP Connection is Closed.
* If the Maximum Connections are below 100 then carry on as normal.
Hope this makes sense. Like I've stated earlier, I'm not an iRule Guru in any way, shape or form.
Thanks for your Time.
Chris. - hoolio
Cirrostratus
Thanks, that's a bit clearer. Is the app setting the cookie or do you want the iRule to do it?
Aaron - Greenberg
Nimbostratus
Hi Aaron,
The App is setting the Cookie.
Added Speed Bump to the situation is, it can't be applied Globally to the Virtual Server. It has to limit connections to the uri or http path.
My head is burnt out :(
Any assistance will be much appreciated Aaron.
Regards,
Chris. - hoolio
Cirrostratus
This might be my last question... :) Is the application built on IIS? If so, it's not very secure to implement HTTP URI based security in iRules as the validation can be bypassed fairly easily:
http://devcentral.f5.com/Community/GroupDetails/tabid/1082223/asg/50/aft/30900/showtab/groupforums/Default.aspx31026
Aaron - Greenberg
Nimbostratus
Hi Aaron,
It's Apache on a Linux Based Web Server.
This is another blast I had at the iRule:-
when RULE_INIT {
set static::max_connections_pi 2
set ::Inpicall =0
set static::active_connections_pi 0
}
when HTTP_REQUEST {
if { [HTTP::uri] contains "URI" } {
set inpicall=1;
incr ::active_connections_pi 1
if { not [HTTP::cookie exists "inpicheckout"] and $::active_connections_pi > $::max_connections_pi} {
HTTP::respond 302 Location "Website.html" "Connection" "Close" "Cache-Control" "no-cache" "Pragma" "no-cache" TCP::close
}
}
}
when HTTP_RESPONSE {
if $Inpicall==1
{ incr ::active_connections_pi -1
$Inpicall=0
}
}
when CLIENT_CLOSED { if $inpicall==1 { incr ::active_connections_pi -1 $Inpicall=0
}
}
Would this only max connections for traffic hitting the URI or all Connections hitting the Virtual Server?
Chris.
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* 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
Discover DevCentral Connects
