<\/span><\/h3>\nThe iRule operates by creating a unique cookie which is provided to the client within the HTTP RESPONSE. This cookie value (UIE key) is also added to a universal persistance record on the F5 which is later referenced for any further HTTP REQUESTS.<\/p>\n
Below is an example of a universal persistence record,<\/p>\n
root@f5ltm(Active)(tmos)# show ltm persistence persist-records all-properties\r\nSys::Persistent Connections\r\nuniversal - 172.16.100.10:80 - 192.168.1.31:80\r\n-----------------------------------------------------------\r\n\u00a0 TMM\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0\r\n\u00a0 Mode\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 universal\r\n\u00a0 Key\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 8abc87e0260ca1eddb577d37bf4018f5_1359498668\r\n\u00a0 Age (sec.)\u00a0\u00a0\u00a0 6\r\n\u00a0 Virtual Name\u00a0 VS-172.16.100.10-80\r\n\u00a0 Virtual Addr\u00a0 172.16.100.10:80\r\n\u00a0 Node Addr\u00a0\u00a0\u00a0\u00a0 192.168.1.31:80\r\n\u00a0 Pool Name\u00a0\u00a0\u00a0\u00a0 POOL-172.16.100.10-80-A\r\n\u00a0 Client Addr\u00a0\u00a0 172.16.1.1<\/pre>\nNote :<\/em> The Age within the persistence record is an idle timeout. Meaning when a persistence look up is performed the Age is reset back to 0.<\/p>\n<\/span>iRule Options \n<\/strong><\/span><\/h3>\nBecause of the differences in how persistence should be performed there are 2 iRule options available here ; strict and standard.<\/p>\n
<\/span>Strict \n<\/strong><\/span><\/h4>\n# Name : Virtual Server Cookie Persistence (strict)\r\n# Purpose : Cookie Persistence across Virtual Server services\r\n# Methodology : Create cookie containing \"unique\" hash and creation time. \r\n# This cookie is then used to persist connections.\r\n\r\nwhen HTTP_REQUEST {\r\n\t \tset cookie_timeout 900\r\n\r\n\t\tif { [HTTP::cookie exists \"b1P\"] } {\r\n\t\t\t# calculate current\/elapsed time \r\n\t\t\tset now [clock seconds]\r\n set cookie_epoch [getfield [HTTP::cookie \"b1P\"] \"_\" 2]\r\n\t\t\tset timer [expr {$now - $cookie_epoch}]\r\n \t\t\r\n\t\t\tif { $timer > $cookie_timeout } {\r\n\t\t\t\t# if cookie timeout is exceeded create new cookie within response\r\n\t\t\t\tset cookie [HTTP::cookie value \"b1P\"]\r\n set cookie_check 1\r\n #_debug_# log local0. \"[virtual name] [IP::client_addr] TM_EXCEED $cookie 1\"\r\n\t\t\t} else {\r\n\t\t\t\t# if cookie is present and timeout valid then persist\r\n\t\t\t\tpersist uie [HTTP::cookie value \"b1P\"]\r\n set cookie_check 0\r\n #_debug_# log local0. \"[virtual name] [IP::client_addr] TM_OK [HTTP::cookie value \"b1P\"] 1\"\r\n\t\t\t}\t\t\t\t\t\r\n\t\t} else {\r\n \t\t# if there is no cookie present add one within the response\r\n\t\t\tset cookie_check 2\r\n\t\t\t}\r\n}\r\nwhen HTTP_RESPONSE {\r\n\t\tset cookie_expiry 900\r\n\r\n\t\t# if cookie timeout is exceeded within request delete persistance entry\r\n\t\tif { $cookie_check eq 1 } {\r\n persist delete uie $cookie\r\n #_debug_# log local0. \"[virtual name] [IP::client_addr] REMOVE $cookie 1\"\r\n } \t\t\r\n\t\t# if cookie timeout exceeded or there is no cookie then create new cookie and add to reponse\r\n\t\tif { ($cookie_check eq 1) or ($cookie_check eq 2)} {\r\n\t\t\t# create hash for cookie\r\n\t\t\tset now [clock seconds]\r\n\t\t set token \"[IP::server_addr][IP::client_addr][TCP::client_port][expr { int(1000000 * rand()) }]\"\r\n binary scan [md5 $token] H* md5var junk\r\n \r\n\t\t\t# insert cookie and add expiry\r\n\t\t\tHTTP::cookie insert name \"b1P\" path \/ value $md5var\\_$now\r\n\t\t\tHTTP::cookie expires b1P $cookie_expiry\r\n\t\t\t#_debug_# log local0. \"[virtual name] [IP::client_addr] INSERT [HTTP::cookie \"b1P\"] 1or2\"\r\n persist add uie [HTTP::cookie \"b1P\"]\r\n\t\t}\r\n}\r\n<\/pre>\nTo ensure that a client session is only persistent for a fixed time period, the strict version is used. This adds an expiry time to the cookie. Unfortunately because not all browsers honour this expiry value, at the point the cookie is created a timestamp (using the EPOCH format) is also appended to the cookie value. This is then used to ensure that if the client sends a cookie that exceeds the timeout the connection is rebalanced. \nThis option works well for scenarios when session draining is required.<\/p>\n
Within this iRule there are 2 variables that define the timeout. These are :<\/p>\n
\ncookie_timeout – This value represents (in seconds) the amount of time between the cookie create time (appended EPOCH) and the current time.<\/li>\n cookie_expiry – This value represents (in seconds) the amount of time in seconds that will be added to the cookie expiry timeout. i.e should this value be set to 900 secs and the cookie create on the 15th April 2012 15:00 then the expiry time will be set to 15th April 2012 15:15.<\/li>\n<\/ul>\nNote :<\/em> Both timeouts (by default) are set to 15minutes.<\/p>\n<\/span>Standard<\/strong><\/span><\/h4>\n# Name : Virtual Server Cookie Persistence (standard)\r\n# Purpose : Cookie Persistence across Virtual Server services\r\n# Methodology : Create cookie containing \"unique\" hash. This cookie is then used to persist connections.\r\n\r\nwhen HTTP_REQUEST {\r\n\t if { [HTTP::cookie exists \"b1P\"] } {\r\n # if cookie is present then persist \r\n\t\t\tpersist uie [HTTP::cookie value \"b1P\"]\r\n set cookie_check 0 \r\n #_debug_# log local0. \"[virtual name] [IP::client_addr] PRESENT [HTTP::cookie value \"b1P\"] 0\"\t\r\n\t\t\t} else {\r\n\t\t\t\tset cookie_check 1\r\n\t\t\t}\r\n}\r\nwhen HTTP_RESPONSE { \t\r\n # if there is no cookie in request then add cookie to response\r\n\t\tif { $cookie_check eq 1 } {\r\n\t\t\t# create hash for cookie\r\n\t\t\tset now [clock seconds]\r\n\t\t\tset token \"[IP::server_addr][IP::client_addr][TCP::client_port][expr { int(1000000 * rand()) }]\"\r\n binary scan [md5 $token] H* md5var junk\r\n # insert cookie\r\n HTTP::cookie insert name \"b1P\" path \/ value $md5var\\_$now\r\n\t\t\t#_debug_# log local0. \"[virtual name] [IP::client_addr] INSERT [HTTP::cookie \"b1P\"] 1\"\r\n persist add uie [HTTP::cookie \"b1P\"]\r\n\t\t}\r\n}\r\n<\/pre>\nWith this option no expiry time is added to the cookie and the EPOCH timestamp is not referenced. The only value that mandates how long the session is persisted for is the Age value within the universal persistence record. However (as previously mentioned) as this is an idle timeout it can result in the client maintaining persistence to a single server for extremely long periods (i.e until the client stops sending traffic for the length of the universal persistence timeout). \nThis option is recommended if the application session also has a idle timeout. This ensures that the application session times out before the persistence record in turn preventing the situation where an existing session is being sent to a (newly balanced) backend server that has no knowledge of the session.<\/p>\n
Note :<\/em> Based on this you will need to ensure the idle timeout of the persistence record is longer then the idle timeout of the application.<\/p>\n<\/span>iRule Notes<\/strong><\/span><\/h3>\n\nFor the iRule jedi`s out there, you may of noticed that in the iRule (standard) there is no logic that covers the event of a cookie being sent, but there being no corresponding persistence entry. In this scenario at the point the F5 performs a ‘persist lookup’ and no UIE entry is found then the traffic will be rebalanced and a new persistence entry created.<\/li>\n Though the EPOCH value is not used within the standard option, this value is still appended to the cookie to assist in any troubleshooting that may be required.<\/li>\n<\/ul>\n<\/span>DEPLOYMENT<\/strong><\/span><\/h3>\nTo deploy either of the 2 persistence options follow the steps below:<\/p>\n
1. Create an iRule using on of the above options. \n2. Create universal persistence profile using the following settings<\/p>\n
ltm persistence universal PERSIST-COOKIE-HTTP_S { \r\n\u00a0defaults-from universal \r\n\u00a0match-across-pools disabled \r\n\u00a0match-across-services enabled \r\n\u00a0match-across-virtuals disabled \r\n\u00a0mirror disabled \r\n\u00a0override-connection-limit disabled \r\n\u00a0rule <IRULE NAME> \r\n\u00a0timeout <???> \r\n}<\/pre>\n3. Assign the persistence profile to your Virtual Servers (i.e port 80 and 443). \n4. Enable OneConnect on all Virtual Servers that the new persistence profile has been applied to.<\/p>\n
<\/span>TROUBLESHOOTING<\/strong><\/span><\/h3>\nShould persistence still fail or present problems there are a number of ways that you can troubleshoot. Typically I use a method of obtaining a string within the webpage to determine which server I am connected to. I then use a combination of curl (using the cookie options) and grep to determine if basic persistence is working.<\/p>\n
However in circumstances where the issue centres around timeout issues with your persistence session then you can :<\/p>\n
\nEnable debugging within the iRule and remove the #_debug_# syntax for each of the log lines. These logs can then be viewed within \/var\/log\/ltm.<\/li>\n To also log the node that the traffic is sent to\n\nadd the $node variable to the log line<\/li>\n add the following syntax above each log line — set node [persist lookup uie [HTTP::cookie value “b1P”] node]<\/li>\n<\/ul>\n<\/li>\n Add an entry to each log line for any other session cookie values that are being used. So that you can match up the life of the persistence cookie to that of your application session cookie.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"BACKGROUND In order to to maintain persistence between services (such as HTTP and HTTPS) on a single Virtual Server two persistence methods are available ; Cookie Hashing and Source IP. In order to perform “true” Cookie (insert) persistence across services an iRule is required. Note : Though cookie persistence (insert) can be performed within the … Read more<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15],"tags":[],"yoast_head":"\nF5 LTM - Cookie Persistence between HTTP and HTTPS - Fir3net<\/title>\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\t \n\t \n\t \n