virtual server connection rate limit with tables
Problem this snippet solves:
Summary: Limit the rate of connections to a virtual server to prevent overloading of pool members
iRule Methodology:
For a given time interval, ensure that the rate of connections doesn't exceed a configurable threshold. Uses the table command to track number of new connections per second.
Code :
# # Name: virtual server connection rate limiting rule # # Purpose: Limit the rate of connections to a virtual server to prevent overloading of pool members # # Methodology: For a given time interval, ensure the rate of connections doesn't exceed a configurable threshold # # Requirements: # - LTM v10.1 or higher to use the table command # - IP address datagroup containing a whitelist of IPs/subnets that should not be limited/counted (vsratelimit_whitelist_class) # - Addition of this iRule to the virtual server. # # Warning: Due to a bug (fixed in 10.2.2), TMM can crash if this iRule is reconfigured or removed # from the virtual server while traffic is pending. For more info see: # Changing an iRule assignment on a virtual server may cause TMM to panic. # http://support.f5.com/kb/en-us/solutions/public/11000/100/sol11149.html # when RULE_INIT { # Log debug to /var/log/ltm? 1=yes, 0=no. set static::conn_debug 1 # Maximum connection rate (new connections / time interval) # To avoid the bug described in SOL11149, you could move this configuration to a datagroup set static::conn_rate 10 # Time interval (in seconds) # This shouldn't need to be changed. # We track connections opened in the last X seconds set static::interval 1 log local0. "Configured to enforce a rate of [expr {$static::conn_rate / $static::interval}]\ cps ($static::conn_rate connections / $static::interval second)" # IP datagroup name which contains IP addresses/subnets to not track/rate limit set static::whitelist_class vsratelimit_whitelist_class # Generate a subtable name unique to this iRule and virtual server # We use the virtual server name with this prefix (vsratelimit_) set static::tbl "vsratelimit" } when CLIENT_ACCEPTED { # Don't process any of this iRule if the client IP is in the whitelist datagroup if {[class match [IP::client_addr] equals vsratelimit_whitelist_class]}{ # Exit this event from this iRule return } # Track this connection in the subtable using the client IP:port as a key set key "[IP::client_addr]:[TCP::client_port]" # Save the virtual server-specific subtable name (vsratelimit_ ) set tbl ${static::tbl}_[virtual name] # Check if we're under the connection limit for the virtual server set current [table keys -subtable $tbl -count] if { $current >= $static::conn_rate } { # We're over the rate limit, so reset the connection if { $static::conn_debug }{ log local0. "$key: Connection to [IP::local_addr]:[TCP::local_port]\ ([virtual name]). At limit, rejecting (current: $current / max: $static::conn_rate)" } #reject # apachebench stops when it gets a reset, so you can test with TCP::close to send a FIN and close the connection cleanly. TCP::close } else { # We're under the virtual server connection rate limit, # so add an entry for this client IP:port with a lifetime of X seconds table set -subtable $tbl $key " " indefinite $static::interval if { $static::conn_debug }{ log local0. "$key: Connection to [IP::local_addr]:[TCP::local_port]\ ([virtual name]). Under limit, allowing (current: [table keys -subtable $tbl -count] / max: $static::conn_rate)" } } }
Published Mar 18, 2015
Version 1.0