Forum Discussion
hooleylist
Oct 30, 2009Cirrostratus
Hi Carol,
If you use assume a /24 subnet, you could use something like this:
when RULE_INIT {
The maximum number of TCP connections to the virtual server from a single client subnet
set ::max_connections_per_ip 10
Clear the array of clients with open connections to the VIP
array set ::active_clients { }
Replace this array with a datagroup named white_client of type 'address' once done testing!
set ::white_client [list \
10.41.0.0 \
10.11.12.0 \
]
}
when CLIENT_ACCEPTED {
log local0. "\$::active_clients: [array get ::active_clients] (size: [array size ::active_clients])"
Scan the octets of the client IP address into four variables
scan [IP::client_addr] {%[0-9].%[0-9].%[0-9].%[0-9]} 1 2 3 4
Save the "network" of the IP using /24 subnet (last octet is 0)
set slash_24_subnet "$1.$2.$3.0"
Check if the client is already in the active clients array
if { ([info exists ::active_clients($slash_24_subnet)]) } {
Regardless of whether we reject this client, we've already accepted the TCP connection.
so increment the counter for this client. The count will be decremented when the connection is closed.
incr ::active_clients($slash_24_subnet)
log local0. "Incremented \$::active_clients($slash_24_subnet) to: $::active_clients($slash_24_subnet)"
Check if client is already over the maximum
if {$::active_clients($slash_24_subnet) > $::max_connections_per_ip} {
Send TCP reset to client
reject
log local0. "Rejected IP [IP::client_addr] (subnet: $slash_24_subnet), count ($::active_clients($slash_24_subnet))"
}
Don't need an else clause here. The default action will be to allow the connection to continue.
} elseif { ![matchclass [IP::client_addr]/24 equals $::white_client] }{
Client wasn't already in the array and isn't in the white list, so add them to the array with a count of 1.
set ::active_clients($slash_24_subnet) 1
log local0. "Initialised \$::active_clients($slash_24_subnet) to: 1"
}
}
when CLIENT_CLOSED {
Check if the client has a count in the array
if { [info exists ::active_clients($slash_24_subnet)]} {
Decrement the count by 1
incr ::active_clients($slash_24_subnet) -1
Check if the count is 0 or negative
if { $::active_clients($slash_24_subnet) <= 0 } {
Clear the array element
unset ::active_clients($slash_24_subnet)
}
}
}
Aaron