Forum Discussion

Irwin_Fletcher_'s avatar
Irwin_Fletcher_
Icon for Nimbostratus rankNimbostratus
Jul 26, 2007

URI Session ID based persistence issue

I’ve come across a need for persistence based off a session ID imbedded in a URI, and unfortunately, I can not get it to work.

 

 

Here’s the lowdown – I need to persist users based upon a session ID found in the URI (source & cookie based persistence are not an option). Users will be jumping from http to https and back, and they need to be sent to the same pool member (Persist Across Services is enabled).

 

 

Here is the iRule I was testing with (it is applied to the http and https VS)

 

 

when HTTP_REQUEST {

 

set fletchpersist [findstr [HTTP::uri] "(X(1)S(" 7 ")"]

 

log local0. "fletchpersistvalue is $fletchpersist"

 

if { $fletchpersist != "" } {

 

persist uie $fletchpersist

 

} else {

 

pool fletch_mobiletest_0

 

}

 

}

 

 

 

The original user request comes in for http://www.mysite.com/

 

 

Then the webservice will determine the browser does not accept cookies, and send the user a redirect to http://www.mysite.com/(X(1)S(l00lky55541j11jofh04eyfl))/login.aspx

 

 

In this case ‘l00lky55541j11jofh04eyfl’ is the session ID, and since it sends this value to the log file via the log statement in the iRule, I assume it is identifying it correctly.

 

 

Once the user follows the redirect and hits the new URL above, he is sent another redirect to the same exact URL/URI, however its to the secure site at https://

 

 

Now, the user will be coming in via https (which is decrypted and re-encrypted so we can inspect the URI), and needs to be sent to the same pool member. Since the session ID is the same as in the previous unencrypted request, I would assume the UIE based persistence iRule would send the connection to the same server.

 

 

Wrong. The https connection is re-load balanced.

 

 

Here is what I observed…..

 

 

Even though the iRule will log the session ID no matter where in the session it comes, the BIG-IP will not enter the value into the persistence table unless it comes in the first http request. So since the first request is for http://www.mysite.com, nothing gets entered into the persistence table. The next request (which comes in the same TCP connection) is for http://www.mysite.com/(X(1)S(l00lky55541j11jofh04eyfl))/login.aspx, which has the value I need to persist off of.

 

 

However unless I force the initial http request to have that session ID in it (which will never happen ‘in the wild’), the session ID is not entered into the table, and the subsequent HTTPS connection (with the ID in the URI) gets re-load balanced.

 

 

Should the BIG-IP be entering the session ID into the persistence table even though it is not in the first request?

 

If not, anybody have a suggestion for getting the ID into the table?

 

 

Thanks in Advance!

 

6 Replies

  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    I've also had difficulty persisting across objects with the "persist" command, and I'm in the process of updating the documentation with some helpful detail.

    In the meantime, you can try using the "session" command instead to enforce the persistence you need regardless of virtual/pool association:
    when RULE_INIT {
      set ::fletchtimeout 600
    }
    when HTTP_REQUEST {
      set fletchpersist [findstr [HTTP::uri] "(X(1)S(" 7 ")"]
      log local0. "fletchpersistvalue is >$fletchpersist<"
      if {$fletchpersist != "" }{
        set server [session lookup uie $fletchpersist]
        if {$server != "" }{
           directly select the desired server as stored in the session table
          log local0. "server found:  $server"
          node [getfield $server : 1] [getfield $server : 2]
        }
      } else {
        log local0. "No fletchpersist value found. Load balancing connection."
        pool fletch_mobiletest_0
      }
    }
    when LB_SELECTED {
       add server info to session table when server selected
      session add uie $fletchpersist [LB::server addr]:[LB::server port] $::fletchtimeout
    }
    when LB_FAILED {
       detach and choose a new server if the selected server fails to respond.
       new session entry will be written in LB_SELECTED on each attempt
      LB::detach
      LB::reselect
    }

    HTH

    /deb
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    The code above needed a couple of corrections.

     

     

    If there was no match on the findstr command, the value for $fletchpersist == null and "session add" throws a runtime error "wrong args" because no value was specified for the "key" parameter. Fixed by making execution of "session add" command dependent on non-null value for key.

     

     

    Once that was fixed, I started getting the dreaded "prerequisite operation not in progress" when trying to add a session table entry after the node was directly selected. Session commands don't seem to have the right context after direct node selection, instead generating that error. Fixed by making execution of "session add" command further dependent on absence of value for $server (value only exists if node was directly selected.) Also re-added existing session table entry in HTTP_REQUEST to update persistence timeout, preventing persistence from timing out.
    when RULE_INIT {
      set ::fletchtimeout 600
    }
    when HTTP_REQUEST {
      set fletchpersist [findstr [HTTP::uri] "(X(1)S(" 7 ")"]
      log local0. "fletchpersistvalue is >$fletchpersist<"
      if {$fletchpersist != "" }{
        set server [session lookup uie $fletchpersist]
        if {$server != "" }{
           directly select the desired server as stored in the session table
           re-add to session table to update timeout
           (session table update in LB_SELECTED n/a for direct node selection)
          session add uie $fletchpersist $server $::fletchtimeout
          node [getfield $server : 1] [getfield $server : 2]
          log local0. "fletchpersist: $fletchpersist  server found:  $server"
        }
      } else {
        log local0. "No fletchpersist value found. Load balancing connection."
        pool ryan_mobiletest_0
      }
    }
    when LB_SELECTED {
       add server info to session table when server selected
       only add if key exists & node not directly selected above  
      if {$fletchpersist != "" && $server ==""}{
        session add uie $fletchpersist [LB::server addr]:[LB::server port] $::fletchtimeout
        log local0. "fletchpersist: $fletchpersist  server: [session lookup uie $fletchpersist]"
      }
    }
    when LB_FAILED {
       detach and choose a new server if the selected server fails to respond.
       new session entry will be written in LB_SELECTED on each attempt
      LB::detach
      LB::reselect
    }
  • Hi,

     

     

    I've tried using this code and it seems to work mostly (i changed the pools and the regex to suit my app)

     

     

    however i intermitently get the following error :

     

     

    Feb 1 23:54:51 tmm tmm[1681]: 01220001:3: TCL error: rule_test - Prerequisite operation not in progress (line 4) invoked from within "session lookup uie $fletchpersist"

     

     

    I've been digging around for ideas, but the only stuff i've seen mentioned is to ensure that the default pool is in place, which it is.

     

     

    Any insight would be massively appreciated..

     

     

    AB
  • Hi Andy,

     

     

    As mentioned in a similar post (Click here), if you do have a default pool and no other iRules, you might try opening a case with F5 Support to ask them to help troubleshoot the issue. If you find anything via this route, could you reply back here?

     

     

    Thanks,

     

    Aaron
  • I got a response from support..

     

     

    'You will be pleased to know that the iRule is OK and there are no issues with the way its written.

     

     

    The error message you are seeing is caused when the client connection is dropped / disconnected before the iRule has finished processing it.

     

     

    This is why you only see the error on some connections and not all of them.

     

     

    So this is expected behaviour as far as we can tell.'
  • Thanks for posting the response. But I'm not sure I understand. In order to get to the persist lookup command in HTTP_REQUEST (where the error is being logged), LTM must parse the HTTP headers of the request. So are they suggesting that the client establishes a connection to the VIP, sends at least the full headers and then resets the connection? That doesn't seem very likely to happen on a regular basis.

     

     

    Aaron