Forum Discussion

Austin_Geraci's avatar
Nov 17, 2010

matchclass, uri routing, and cookie persist & snat irule

Hey guys and gals, it's been a bit, I hope all is well.

Please review the below scenerio and let me know if i'm missing something, or if you would do anything differently..

I worked up the below iRule, I'd like to route traffic to one specific pool based on a class of uris, if no match, I'd like to route to another pool and use cookie persist... Simple enough.

The Virtual Server is terminating SSL and re-encrypting it.. using an client and server SSL profile..

In addition the VS is already using a snat iRule.. My thought is to juse use it first..Should I combine the snat iRule, or just keep it and use the below one after the snat iRule?

I should note, the box is running 10x on the 8900 platform.

Thanks!

iRule



when HTTP_REQUEST {
 set uri [string tolower [HTTP::uri]] 
log local0.notice "Incoming Request uri: $uri" 
if { [matchclass [HTTP::uri] starts_with $::myclass] } { 
   log local0.notice "Directing to secure_pool"    
   pool match_pool
 } else {
 log local0.notice "Directing to server_pool" 
  pool server_pool
 persist cookie
}
class

class myclass {

/myfirsturi

/myseconduri

/etcetcetc

}

[/

  • Hey guys - I have a similar question and am preparing to write an iRule that routes to particular pools based on the URI, however, in addition, we'll need to persist the session to an existing pool member if the cookie exists for the pool specified in the URI. If none of the URI paths matched we could just send them to a default pool, applying one of the session ID cookies if present too.

     

     

    For example, here's how the logic would flow:

     

     

    1. Request comes inbound for one of the following URI paths:

     

     

    /plan*

     

    /unica*

     

    /campaign*

     

     

    2. LTM parses the URI and determines which pool should receive the request (likely using a class match operation), by reading the preceding string of the URI patch.

     

     

    3. After determine the path and appropriate pool, the LTM should then search for existing session cookies pertinent to that given pool. In our scenario, each pool will have its own specific session cookies:

     

     

    /plan (cookie: PLANSESSIONID)

     

    /unica (cookie: PLATFORMJSESSIONID)

     

    /campaign (cookie: CAMPAIGNJSESSIONID)

     

     

    Essentially, once the F5 knows which pool should receive the request, it can then search the HTTP header for the matching cookie for that pool to see if there's an existing session, or whether a new session should be initiated.

     

     

    4. If none of the URIs match in the class list, then I'd like to have a default catch-all which will auto-route the request to the /unica URI pool, and then persist off of the corresponding PLATFORMSESSIONID cookie.

     

     

    I'm working on a draft of this now, though it certainly seems to me that the iRule shown further above in this post would work as a good starting point. I'd just need to break out into a few more if/then clauses.

     

     

    What do you guys think?

     

     

    Thanks!

     

    B
  • So I took a first stab at this.. how does this look to you guys? I opted for now class match for now... please provide your input!

     

     

    Thanks

     

    B

     

     

    when HTTP_REQUEST {

     

    if {[HTTP::uri] starts_with "/unica"} {

     

    persist uie [string tolower [HTTP::cookie "UMPSESSIONID"]] 3600

     

    pool Unica_Platform_Test

     

    } elseif {[HTTP::uri] starts_with "/plan"} {

     

    persist uie [string tolower [HTTP::cookie "PLANJSESSIONID"]] 3600

     

    pool Unica_Plan_Test

     

    } elseif {[HTTP::uri] starts_with "/campaign"} {

     

    persist uie [string tolower [HTTP::cookie "CAMPAIGNSESSIONID"]] 3600

     

    pool Unica_Campaign_Test

     

    } elseif {[HTTP::uri] starts_with "/dashboard"} {

     

    persist uie [string tolower [HTTP::cookie "JSESSIONID"]] 3600

     

    pool Unica_Campaign_Test

     

    }

     

    else {

     

    persist uie [string tolower [HTTP::cookie "UMPSESSIONID"]] 3600

     

    pool Unica_Platform_Test

     

    }

     

    }
  • So some other thoughts I had on the above:

     

     

    in each clause I'm assuming that the LTM will automatically try to persist off of the various SESSIONID cookies listed above, assuming they are indeed present. If they exist we should be good, but if they don't (like on an initial visit to the site) will the LTM iRule err out and stop processing or just ignore the persist command (as I'd hope it might)?

     

     

    This assumption continues with the ELSE clause where, if any request comes in which does not match one of the aforementioned URIs, the LTM should try to persist it using the named cookie (UMPSESSIONID) and then send it to the appropriate pool, whether as a sticky session or a new session.

     

     

    As a side note, I got some of the syntax above from another iRule on this site which outlined utilizing the JSESSIONID cookies for J2EE app server persistence:

     

     

    http://devcentral.f5.com/wiki/iRules.Weblogic_JSessionID_Persistence.ashx

     

     

    In that iRule, I noticed that there was also an HTTP_RESPONSE section listed. Just wondering if I'd need an HTTP_RESPONSE clause in this iRule for it to properly work, based on the other tech page link I've listed above?

     

     

    And also on that page is a note from Aaron (hoolio), indicating that we need to use OneConnect for that iRule to work? We've been using that persistence iRule for some time now and don't have OneConnect enabled for that VS. Could this be causing odd connection issues, and should I look at enabling it for this rule too?

     

     

    Thanks in advance!

     

    B
  • Okay, so in thinking about this, it seems that the JSESSIONID check in the outbound HTTP_RESPONSE are required so that the F5 knows to put an entry into its session table, indicating the outbound JSESSIONID as a persistence entry, thus ensuring that when it comes back in future HTTP GET requests from the client, the LTM knows to which pool member the request(s) should be sent.

     

     

    That said, please lend a hand with my other questions is possible:

     

     

    1. If the SESSIONID cookies referenced in the iRule exist we should be good, but if they don't (like on an initial visit to the site) will the LTM iRule err out and stop processing or just ignore the persist command?

     

     

    2. Is my catch all properly structured, so that when any request comes in which does not match one of the aforementioned URIs, the LTM will try to persist it using the cookie name of UMPSESSIONID, and then send it to the appropriate pool, whether as a sticky session or a new session.?

     

     

    3. Regarding OneConnect for the L7 persistence (JSESSIONID), as mentioned in the article above, we've been using that persistence iRule for some time now and don't have OneConnect enabled for our other VS's. Could this be causing odd connection issues, and should I look at enabling it for this new iRule too? Can you please explain why? I'm not entirely sure I understand the explanation given in the other link.

     

     

    Thanks!

     

    Brian
  • Hi Brian,

    You could just use the default cookie insert persistence profile for this and leave out all of the persistence in the iRule. LTM will then set a persistence cookie for each pool the client is sent to.

    Else, if you want to do this manually, you should add a check to see if the cookie value is not null before persisting on it. Persisting on a null string will (or should) cause a run time error and TCP reset. Also, you'd want to add the persistence in the response when the app sets the cookies:

    
    when HTTP_REQUEST {
    switch -glob [HTTP::path] {
    "/unica*" {
    set cookie_name "UMPSESSIONID"
    pool Unica_Platform_Test
    }
    "/plan*" {
    set cookie_name "PLANJSESSIONID"
    pool Unica_Plan_Test
    }
    "/campaign" {
    set cookie_name "CAMPAIGNSESSIONID"
    pool Unica_Campaign_Test
    }
    "/dashboard* {
    set cookie_name "JSESSIONID"
    pool Unica_Campaign_Test
    }
    default {
    set cookie_name "UMPSESSIONID"
    pool Unica_Platform_Test
    }
    }
    if {[HTTP::cookie $cookie_name] ne ""}{
    persist uie [string tolower [HTTP::cookie $cookie_name]] 3600
    }
    }
    when HTTP_RESPONSE {
    if {[HTTP::cookie $cookie_name] ne ""}{
    persist add uie [string tolower [HTTP::cookie $cookie_name]] 3600
    }
    }
    

    And also on that page is a note from Aaron (hoolio), indicating that we need to use OneConnect for that iRule to work? We've been using that persistence iRule for some time now and don't have OneConnect enabled for that VS. Could this be causing odd connection issues, and should I look at enabling it for this rule too?

    I'd definitely suggest using OneConnect with this iRule or with any other L7 persistence like cookie insert. If you’re using SNAT, you can use the default OneConnect profile with a /0 source mask. With no SNAT you should create a custom OneConnect profile with a /32 source mask.

    For details on OneConnect, see this article:

    http://devcentral.f5.com/wiki/AdvDesignConfig.ONECONNECT.ashx

    Aaron
  • Here's my latest crack at it.. this is getting ugly! Any help is much appreciated.

     

     

    Thanks!

     

    B

     

     

    when HTTP_REQUEST {

     

    if {[HTTP::uri] starts_with "/unica" and [HTTP::cookie "UMPSESSIONID"] ne "" }{

     

    persist uie [string tolower [HTTP::cookie "UMPSESSIONID"]] 3600 }

     

    pool Unica_Platform_Test

     

    } elseif {[HTTP::uri] starts_with "/plan" and [HTTP::cookie "PLANJSESSIONID"] ne "" }{

     

    persist uie [string tolower [HTTP::cookie "PLANJSESSIONID"]] 3600 }

     

    pool Unica_Plan_Test

     

    } elseif {[HTTP::uri] starts_with "/campaign" and [HTTP::cookie "CAMPAIGNSESSIONID"] ne "" }{

     

    persist uie [string tolower [HTTP::cookie "CAMPAIGNSESSIONID"]] 3600 }

     

    pool Unica_Campaign_Test

     

    } elseif {[HTTP::uri] starts_with "/dashboard" and [HTTP::cookie "JSESSIONID"] ne "" }{

     

    persist uie [string tolower [HTTP::cookie "JSESSIONID"]] 3600 }

     

    pool Unica_Campaign_Test

     

    }

     

    else {

     

    { [HTTP::cookie "UMPSESSIONID"] ne "" }{

     

    persist uie [string tolower [HTTP::cookie "UMPSESSIONID"]] 3600 }

     

    pool Unica_Platform_Test

     

    }

     

    }

     

     

    when HTTP_RESPONSE {

     

    if { [HTTP::cookie "JSESSIONID"] ne "" }{

     

    persist add uie [string tolower [HTTP::cookie "JSESSIONID"]] 3600 }

     

    } elseif { [HTTP::cookie "UMPSESSIONID"] ne "" }{

     

    persist uie [string tolower [HTTP::cookie "UMPSESSIONID"]] 3600 }

     

    } elseif { [HTTP::cookie "PLANJSESSIONID"] ne "" }{

     

    persist uie [string tolower [HTTP::cookie "PLANJSESSIONID"]] 3600 }

     

    } elseif { [HTTP::cookie "CAMPAIGNSESSIONID"] ne "" }{

     

    persist uie [string tolower [HTTP::cookie "CAMPAIGNSESSIONID"]] 3600 }

     

    }
  • Thanks much! I will poke around with this and see how it goes... any input on my question above about OneConnect?

     

     

    Thanks again,

     

    B
  • Hey Aaron - I just read your note on OneConnect above. I will definitely give the profilei a go. And I have a few more questions to help clear up my thought process. I really appreciate all of your info!

     

     

    So I believe the vendor said we should key off of the various JSESSIONID cookies to ensure proper persistence. That said, I'm sure a persistence cookie manual insert may work just the same. However, for now, I'd like to try your iRule above, and just want to confirm that I understand how it flows. So I've summarized my comprehension below - please clarify if necessary.

     

     

    1. For every incoming HTTP request, the LTM switches the path to lower for iRule evaluation. if it sees any of the matching URI paths, it next sets a variable called cookie_name to have a value of the corresponding JSESSIONID cookie.

     

     

    2. Next the LTM confirms the existence of the actual cookie and, if found, will use it as the persistence mechanism.

     

     

    3. Finally, any outbound HTTP server responses that may be setting persistence cookies will be captured and recorded by the LTM to ensure future requests go back to the correct pool member.

     

     

    Does that sound about right?

     

     

    Thanks,

     

    Brian