Forum Discussion
David_Horton_20
Nimbostratus
Jan 26, 2007Connection limits on IP Address
Hi
I am trying to create an iRule to manage traffic based on IP Address. I want to set a limit and only allow that number of people in. My current rule creates an array of ip addresses, when you make a http request your ip gets placed in the array. If the array gets larger than a limit I am setting in the iRule then only people with addresses already in the array get a connection. I remove an IP address from the array when the CLIENT_CLOSED event fires, this usually happens when the client closes their browser or after a period of inactivity.
In my test environment I have the limit set to one and have one tester user using the site(making multiple http requests), if I try and browse the site normally I am denied access, however if I make multiple connection requests using a load testing tool then CLIENT_CLOSED gets fired for the tester user and they are kicked off. If anyone could provide any more information on CLIENT_CLOSED, when and how it gets fired that would be very helpful.
I have put my current iRule in below.
Thanks
Dave
when RULE_INIT {
array set ::active_IPs { }
array unset ::active_IPs
set ::max_active_IPs 1
set count_active_IPs [array size ::active_IPs]
}
when HTTP_REQUEST {
set client_ip [IP::remote_addr]
set count_active_IPs [array size ::active_IPs]
if { [info exists ::active_IPs($client_ip) ] } {
pool Active
return
} else {
if { $count_active_IPs >= $::max_active_IPs } {
HTTP::redirect "http://www.busy.com"
} else {
set ::active_IPs($client_ip) 1
pool Active
}
}
}
when CLIENT_CLOSED {
set client_ip [IP::remote_addr]
if { [info exists ::active_IPs($client_ip)] } {
unset ::active_IPs($client_ip)
}
}
- Colin_Walker_12Historic F5 AccountIt might make more sense to place your logic under the CLIENT_CONNECTED event. As it stands now you're performing the check to see how many people are logged in, and if this IP address is one of them, every time the browser sends an HTTP request (possibly hundreds of requests per page), rather than every time a new connection is established.
- David_Horton_20
Nimbostratus
Thanks Colin, I will definitely investigate using CLIENT_CONNECTED, makes more sense. - hoolio
Cirrostratus
Here is an updated (but untested) version which checks the connection limit in CLIENT_ACCEPTED and redirects clients who don't already have an existing connection open to a busy page in HTTP_REQUEST. It might be more graceful to allow clients who have established a previous TCP connection to continue opening new TCP connections. This could be done using the session table.Name : connection limit with HTTP redirect rule v1.1 - Aaron Hooley, 30 Sept 2008 Purpose: Limit the number of TCP connections from clients to the virtual server. When the connection limit is reached, only allow clients who already have an active connection open to the VIP to establish new TCP connections. Clients who establish a new TCP connection after the limit is reached are sent an HTTP redirect to a busy page. when RULE_INIT { Set the maximum number of TCP connections set ::max_active_IPs 20 Clear the array if it exists if {[array exists ::active_IPs]}{ array unset ::active_IPs } } when CLIENT_ACCEPTED { Track whether we'll redirect the client in HTTP_REQUEST set redirect 0 Check if the current client IP already exists in our array of active client IPs if { [info exists ::active_IPs([IP::client_addr])] } { Client exists in the current connection array, so don't redirect them set redirect 0 } else { Client didn't have an existing active TCP connection, so check if there are available connection slots if { [array size ::active_IPs] >= $::max_active_IPs } { We're over the connection limit, so redirect the client set redirect 1 } else { We're allowing the client, so add it to the array set ::active_IPs([IP::client_addr]) 1 Don't redirect the client set redirect 0 } } } when HTTP_REQUEST { If the client connection wasn't allowed in CLIENT_ACCEPTED, redirect them here. Tell the client to close the TCP connection with Conenction: Close header in response if {$redirect}{ HTTP::respond 302 "http://busy.example.com" \ "Connection" "Close" \ "Cache-Control" "no-cache" \ "Pragma" "no-cache" } } when CLIENT_CLOSED { Client connection was closed, so remove the IP address from the array if { [info exists ::active_IPs([IP::client_addr])] } { unset ::active_IPs([IP::client_addr]) } }
- Jack_H_39707
Nimbostratus
Dear hoolio, I am having some error when testing the rules above. Would need your advise as I believed I have done wrongly in any steps. - hoolio
Cirrostratus
If there is a space after the backslash on these lines, you can remove it to fix the syntax error:HTTP::respond 302 "http://busy.example.com" \ "Connection" "Close" \ "Cache-Control" "no-cache" \ "Pragma" "no-cache"
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