Forum Discussion

max_e_mim_59245's avatar
max_e_mim_59245
Icon for Nimbostratus rankNimbostratus
Oct 19, 2010

http to https cookie persitance

Hi All,

 

 

First post here so please be gentle, Im an application specialist not an f5 or networking guru in any way.

 

 

I had the problem that alot of people in the forums seem to have had..

 

 

one site.

 

2 virtual servers

 

 

one for http

 

the other for https.

 

 

http on port 80

 

https on port 443 with a forward through to my webs on port 8443

 

 

each virtual server has its own pool

 

one for 80 another for 8443

 

 

the pools share the same nodes.

 

 

Persisting using src address persistance was working perfectly, until we started dealing with mobile devices and wireless internet.

 

 

We need persistence because our app is from the stone ages and runs aspclassic sessions, so a user needs to persist to the server where they logged in on.

 

 

Now i thought no problem and doing some reading.. just set the same cookie persistance profile accross the virtual servers.. and then make sure they have the same cookie name. issue is that will only work if your nodes for your pools are the same.. the big ip will set the cookie with the ip of the node and the port.... thats the way it identifies the server for persistance..

 

 

example

 

 

user hits http and has a bigipcookie inserted for persistance to that ip on port 80... when the hit https... the persistence cookie gets updated (because the bigip cookie cant find the node in the https pool because it is looking for port and ip combined in its cookie.) .. then when you get back to http.. after loging in.. you get another cookie.. and have selected a new node..

 

 

 

 

so in my case i needed to create a ssl cookie profile and a non ssl cookie profile.. and have different cookie names for both these profiles.

 

and create an i rule on my https virtual server.. to write the http profiles cookie value..

 

 

when in https, there where only a couple of pages i actually need to check, as i dont want to rewritting this cookie for every https request.. so at the points where the session is created on my webs.. is where i set my persistance...

 

 

now.. im no irule expert.. but i hacked out what i needed form various posts.. thanks to the work in the post .. http://devcentral.f5.com/wiki/default.aspx/iRules/Persistence_Cookie_Logger.html

 

 

 

Hopefully this will help others who are having the same issue.. and if some of the irule gurus could comment on this so maybe i can clean it up.. im a little concerned about using the golbal variable scope and if this will have an issue on performance.. and i think but im not sure that this rule will handle node failure reasonably well.

 

 

also in a production environment should i be logging ?

 

 

here is the code..

 

 

 

when RULE_INIT {

 

see AskF5 SOL6917 for cookie encoding details:

 

https://support.f5.com/kb/en-us/solutions/public/6000/900/sol6917.html

 

set ::mySecureCookie "bccomssl"

 

set ::myNonSecureCookie "bccom"

 

set ::debug 0

 

 

 

}

 

 

check if we have hit login page or join

 

when HTTP_REQUEST {

 

 

if { [HTTP::uri] starts_with "/secure_login.asp" } {

 

we need to set the non secure cookie persistance now

 

log local0. "secure login detected"

 

set cookiemonster 1

 

} elseif { [HTTP::uri] starts_with "/cust_join.asp" } {

 

if we are joining we also need to set the non secure cookie

 

set cookiemonster 1

 

log local0. "join detected"

 

} else {

 

set cookiemonster 0

 

}

 

 

set the non secure cookie persistance

 

if {$cookiemonster == 1} {

 

log local0. "detecting ssl cookie values"

 

if {[HTTP::cookie exists $::mySecureCookie]}{

 

scan [HTTP::cookie $::mySecureCookie] {%[^\.].%d.%d} myIpE myPortE unused

 

 

calculate IP

 

%08x format strings forces padding w/leading 0's to 8 char string

 

set myIpH [format %08x $myIpE]

 

if {$::debug != 0}{log local0. "myIpH=$myIpH"}

 

set myIpD1 [expr 0x[substr $myIpH 6 2]]

 

set myIpD2 [expr 0x[substr $myIpH 4 2]]

 

set myIpD3 [expr 0x[substr $myIpH 2 2]]

 

set myIpD4 [expr 0x[substr $myIpH 0 2]]

 

set myIpD "$myIpD1.$myIpD2.$myIpD3.$myIpD4"

 

 

calculate port

 

set myPortH [format %x $myPortE]

 

set myPortD [string trimleft [expr 0x[substr $myPortH 2 2]][expr 0x[substr $myPortH 0 2]] 0]

 

 

set the port 80 cookie

 

 

 

}

 

 

}

 

 

 

 

}

 

 

when HTTP_RESPONSE {

 

if {$cookiemonster == 1} {

 

 

 

set httpport ":80"

 

set addr "$myIpD$httpport"

 

log local0. "setting non secure cookie at $addr"

 

scan $addr "%u.%u.%u.%u:%u" a b c d e

 

set cookie "[format %u [expr ($d<<24)|($c<<16)|($b<<8)|$a]].[expr 256*$e].0000"

 

HTTP::cookie insert name $::myNonSecureCookie value $cookie path "/"

 

 

}

 

}

 

 

 

 

3 Replies

  • That looks good. Does it work for you?

     

     

    If you're on 10.0+ you can replace the static global variables with static::var. This allows the iRule to be run on multiple TMM instances if you have a platform which supports CMP:

     

     

    http://devcentral.f5.com/wiki/default.aspx/iRules/static

     

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

     

     

    Aaron
  • Thanks Aron,

     

     

    Worked a charm, i did need to add an if exists condition before setting the the port 80 cookie, as i was having some tcl errors appearing in my logs from our monitoring service which wasn't actually sending any cookie values through.

     

     

    I am on 10.1 so ill look to add the static variable, although to honest this rule really only needs to run in the scope of the request response space, so i don't think i need globals or static variables.

     

     

    One additional question, writing to the log.locale... does that cause any performance over head ?

     

     

     

    Thanks

     

     

    Nathan

     

     

     

  • Hi Nathan,

     

     

    Logging will add significant load in production. I'd either comment out the log statements once you're done testing or add a $static::cookie_debug flag and check that before logging. That way you can selectively enable/disable logging just by changing the value of one variable.

     

     

    Aaron