Forum Discussion

ocnsinc_68625's avatar
ocnsinc_68625
Icon for Nimbostratus rankNimbostratus
May 10, 2012

Connection Limit iRule not rejecting concurrent sessions as expected

Hi --

 

 

The below iRule was enabled on a specific V/S to reject more than one session for a given unique source IPADDR. After enabling the iRule, rejection notifications are logged in the "ltm" syslog. However, when checking the member servers in the V/S pool, some concurrent sessions are still getting through the iRule. Does any see an issue with the below iRule or know of any other issue that may cause the iRule to partially work?

 

 

Thanks --

 

 

====================================================

 

when RULE_INIT {

 

array set ::Connections { }

 

}

 

 

when CLIENT_ACCEPTED {

 

set ipaddr [IP::remote_addr]

 

set tcpPrt [TCP::client_port]

 

log local0. "Client Accepted from $ipaddr"

 

if { [info exists ::Connections($ipaddr)] } {

 

set tcpport $::Connections($ipaddr)

 

log local0. "Reject Client Session from $ipaddr:$tcpPrt - "

 

log local0. " --> Session Entry $ipaddr:$tcpport, in progress ..."

 

reject

 

return

 

} else {

 

set ::Connections($ipaddr) $tcpPrt

 

set tcpport $::Connections($ipaddr)

 

log local0. "Created Session Entry for $ipaddr:$tcpport ..."

 

}

 

}

 

 

when CLIENT_CLOSED {

 

if { [info exists ::Connections($ipaddr)] } {

 

set tcpport $::Connections($ipaddr)

 

log local0. "Remove Session Entry $ipaddr:$tcpport ..."

 

unset ::Connections($ipaddr)

 

}

 

}

 

====================================================
  • George_Watkins_'s avatar
    George_Watkins_
    Historic F5 Account
    Hi ocnsinc,

    It looks like you've got the right idea here. One tip that will make things a lot easier for you will be to use the table command in place of an array. The TCL array with get initialize on every new connection therefore it won't maintain its contents across multiple connections. Each connection will have an array in memory with different contents. For this reason you cannot track connections using an array. A table however is stored in memory and is shared amongst all connections and TMM instances on the BIG-IP. Here is an iRule that is very similar to the one you wrote. It should provide the intended result:

    
    when RULE_INIT {
         lifetime (in seconds) of connection tracker record(s), maximum length of time connection will be tracked if connection is not explicitly closed
        set static::lifetime 600
        
         logging - 0 = off, 1 = on; disable unless testing
        set static::logging 0
    }
    
    when CLIENT_ACCEPTED {
        set static::table_name [virtual name]_connection_tracker
        set conn [table lookup -subtable $static::table_name [IP::remote_addr]]
    
        if { $conn ne "" } {
             client already has an active connection, rejecting subsequent connection
            reject
            if { $static::logging == 1 } { log local0. "Rejecting connection from [IP::remote_addr]" }
        } else {
            table add -subtable $static::table_name [IP::remote_addr] 1 indef $static::lifetime
            if { $static::logging == 1 } { log local0. "Adding connection for [IP::remote_addr] to tracker" }
        }
    }
    
    when CLIENT_CLOSED {
        table delete -subtable $static::table_name [IP::remote_addr]
        if { $static::logging == 1 } { log local0. "Removing connection for [IP::remote_addr] from tracker" }
    }
    

    Hope that helps,

    -George
  • Hi George –

     

     

    I appreciate the response. Yeah I wanted to use the “table” command however, it’s not available in TMOS V10.0.0 HF2 

     

     

    According to this article  https://devcentral.f5.com/Default.aspx?tabid=63&articleType=ArticleView&articleId=2375, the “table” command is not available until TMOS v10.1 --

     

     

    Other than upgrade to TMOS v10.1 or higher, any further suggestions here to track all connections in memory using something other than an array in the iRule?

     

     

    Thanks ---
  • spark_86682's avatar
    spark_86682
    Historic F5 Account
    The only way to access a sort of global data store on 10.0.x is the session command. However, it can't provide a 100% perfect solution, since it doesn't really provide any good concurrency tools for you (which is why we wrote the table command). You'd have to do something like:

    
    if { [session lookup uie $ipaddr] != 1} {
       session add uie $ipaddr 1
    } else {
       reject
    }
    

    But multiple connections could still come in at the exact same time and get through. That's probably the best you can do without upgrading (which you really should do; 10.0 is over 3 years old).