Forum Discussion

Leslie_South_55's avatar
Leslie_South_55
Icon for Nimbostratus rankNimbostratus
Sep 05, 2007

HTTP connection limit + cookie insert from BigIP

I have been working with the codeshare for HTTP Session Limit on

 

http://devcentral.f5.com/wiki/default.aspx/iRules/HTTPSessionLimit.html

 

but I am not having any luck. Does anyone know how to add some additional logging, perhaps each time the rule is hit it logs the current active connections or when it checks for the cookie? I am using cookie insert generating the cookie from the LTM, I assume that this rule will work with this persistence as well?

 

 

Appreciate any feedback.

 

-L

17 Replies

  • Thinking over this again... when the client starts a session they should request a document. They shouldn't actually be making any subsequent requests until they get back the HTTP data from the first request, as that HTTP data is what contains references to images and other files. So as long as the rule sets the ClientID cookie in that first response and the client continues to present the session cookie for every request, the rule should work as expected, regardless of whether the client uses persistent TCP connections or pipelining over the same TCP connection.

    Can you test with this version of the original rule which does not ignore subsequent requests over the same TCP connection? It has additional logging of the client port, the HTTP version and the Cookie header in requests. 9.2.x doesn't have the ability to access multiple values for the same cookie name. So logging the entire Cookie line will show when multiple instances of the same cookie are present in the request.

    It might also be helpful to capture a binary formatted tcpdump if you encounter a failure. You can use syntax like the following to do so:

    tcpdump -ni 0.0 -s0 -w/var/tmp/session.dmp host VIP_IP or host NODE_IP

    If you have multiple nodes in the pool, add them to the end of the filter string with more 'or host NODE_IP' tokens.

    Here's the rule with more debug logging. Make sure to clear your browser's cookies before testing. It may also be helpful to test with multiple browser types.

    
    when RULE_INIT {
       set ::debug 1
       set ::total_active_clients 0
       set ::max_active_clients 15
       set ::tcp_conn_counter 0
       log local0. "rule session_limit initialized: total/max: $::total_active_clients/$::max_active_clients"
    }
    when CLIENT_ACCEPTED {
    incr ::tcp_conn_counter
    }
    when HTTP_REQUEST {
          
       if {$::debug}{ set uri [HTTP::uri]}
       ; test cookie presence
       if {[HTTP::cookie exists "ClientID"]} {
          set need_cookie 0
          set client_id [HTTP::cookie "ClientID"]
          if {$::debug}{ log local0. " \[$::tcp_conn_counter.[HTTP::request_num]\] client [IP::client_addr]:[TCP::client_port] (v[HTTP::version])\
         with cookie $client_id -> $uri, count: $::total_active_clients"}
          if {$::debug}{ log local0. " \[$::tcp_conn_counter.[HTTP::request_num]\] |----------------------> [HTTP::header value Cookie]"}
      
       ; if cookie not present & connection limit not reached, set up client_id
       } else {
          if {$::total_active_clients < $::max_active_clients} {
             set need_cookie 1
             set client_id [format "%08d" [expr { int(100000000 * rand()) }]]
             incr ::total_active_clients
          if {$::debug}{ log local0. " \[$::tcp_conn_counter.[HTTP::request_num]\] client [IP::client_addr]:[TCP::client_port]\
             (v[HTTP::version]) with no cookie, under connection limit -> $uri, count: $::total_active_clients"}
          ; otherwise redirect
          } else {
             if {$::debug}{ log local0. " \[$::tcp_conn_counter.[HTTP::request_num]\] client [IP::client_addr]:[TCP::client_port]\
                (v[HTTP::version]) with no cookie over limit, redirected  -> $uri, count: $::total_active_clients"}
             HTTP::redirect "http://sorry.domain.com/"
             return
          }
       }
    }
    when HTTP_RESPONSE {
       ; insert cookie if needed
       if {$need_cookie == 1} {
          if {$::debug}{ log local0. "\[$::tcp_conn_counter.[HTTP::request_num]\] client [IP::client_addr]:[TCP::client_port]\
             (v[HTTP::version]) inserting cookie: $client_id"}
          HTTP::cookie insert name "ClientID" value $client_id
       }
    }
    when CLIENT_CLOSED {
       ; decrement current connection counter for this client_id
       if {$::total_active_clients > 0} {
          incr ::total_active_clients -1
          if {$::debug}{ log local0. "\[$::tcp_conn_counter\] client [IP::client_addr]:[TCP::client_port]\
         closing connection with cookie $client_id -> $uri, count: $::total_active_clients"}
      }
    }

    Hope this helps...

    Aaron
  • used new rule, max set to 5, here are the results

     

     

    Rule : rule session_limit initialized: total/max: 0/5

     

    Rule rule_http-session-6 : [1.1] client 10.20.47.82:1642 (v1.1) with no cookie, under connection limit -> /, count: 1

     

    Rule rule_http-session-6 : [1.1] client 10.20.47.82:1642 (v1.1) with no cookie, under connection limit -> /Library/e/web/Portal/en_US/offers.workflow:ShowPromo?LandingPage=/All/US/Products, count: 2

     

    Rule rule_http-session-6 : [1.1] client 10.20.47.82:1642 (v1.1) inserting cookie: 83348434

     

    Rule rule_http-session-6 : [1.2] client 10.20.47.82:1642 (v1.1) with no cookie, under connection limit -> /Library/skins/style_sheet_core.css, count: 3

     

    Rule rule_http-session-6 : [1.2] client 10.20.47.82:1642 (v1.1) inserting cookie: 37131661

     

    Rule rule_http-session-6 : [1.3] client 10.20.47.82:1642 (v1.1) with no cookie, under connection limit -> /Library/js/common/Message.js, count: 4

     

    Rule rule_http-session-6 : [1.3] client 10.20.47.82:1642 (v1.1) inserting cookie: 71842209

     

    Rule rule_http-session-6 : [1.4] client 10.20.47.82:1642 (v1.1) with no cookie, under connection limit -> /Library/portal/images/logo.gif, count: 5

     

    Rule rule_http-session-6 : [1.4] client 10.20.47.82:1642 (v1.1) inserting cookie: 52011422

     

    Rule rule_http-session-6 : [2.1] client 10.20.47.82:1643 (v1.1) with no cookie over limit, redirected -> /Library/portal/images/v16.gif, count: 5

     

    Rule rule_http-session-6 : [2.5] client 10.20.47.82:1642 (v1.1) with no cookie over limit, redirected -> /Static/images/products_page/124.jpg, count: 5

     

    Rule rule_http-session-6 : [2.1] client 10.20.47.82:1643 (v1.1) with no cookie over limit, redirected -> /Static/images/common/icons/plus.gif, count: 5

     

    Rule rule_http-session-6 : [3.1] client 10.20.47.82:1647 (v1.1) with no cookie over limit, redirected -> /Static/images/common/css/divider.gif, count: 5

     

     

    note the redirects, I have the HTTP::redirect on line 32 set to

     

    HTTP::redirect "http://server.domain.com:88/"

     

     

    so I am confused as to whey it shows a redirect to actual items on the page?

     

     

    -L
  • The log entry is just printing out the URI the client requested. That's not the URI that the client is being redirected to.

     

     

    I'm not sure why it's happening, but it looks like LTM is setting the cookie, but the client doesn't always present it in subsequent requests. I'm assuming the cookie is being set with no path or other options that would tell the client to not send the cookie. If that's the case it looks like an issue with the client. I'm not sure there is a perfect iRule fix. You could account for this by raising the global limit.

     

     

    Anyone else have ideas on why a client would get a cookie, make another request after the cookie was set, but not include the cookie in that subsequent request? This seems to violate the protocol for cookie handling.

     

     

    Aaron
  • Hi lsouth,

     

     

    Did you ever test this further? I have a customer who is interested in similar functionality and wanted to find out if you took this any further.

     

     

    Thanks,

     

    Aaron
  • One other thing... in the current iteration of the rule, a new session is created and the total session count incremented on each HTTP request which doesn't already have a session cookie. The only time the total count is decremented is when the TCP connection is closed. So if there are multiple clients connecting over the same TCP connection (ie, coming in via a proxy), session leakage would occur. For proxied users, multiple sessions would be created, but only one session removed when the TCP connection is closed. To account for this, you'd have to count the number of new sessions created per TCP connection and then decrement the session count by this count in CLIENT_CLOSED.

     

     

    Aaron
  • we were not able to get this working, and I have not spent any additional cycles on it as the priority changed - imagine that :-)
  • This is an old thread, but lines up with other ones that seem to want to limit the number of sessions. The code seems to be looking at the number of connections and limiting that to a threshold. The problem is that many client browsers will generate multiple requests from different source ports and the application session will continue through a series of transactions, each of which will generate (and drop) connections with the server. To me the logic may redirect a user who is in the middle of an active server session if they happen to send a transaction at at time that the overall connection limit is exceeded.