Cookie based persistence maintained between HTTP and HTTPS on the F5

Problem

Customer has pretty standard eCommerce site - end-users are browsing the shop using HTTP and while they are ready to purchase, they go to checkout using HTTPS. HTTPS is offloaded to the BigIP, so catch-all cannot be used. Also, customer is not happy to use source IP based persistence because of inconsistencies in load distribution across the servers. The real problem here is that BigIP does not allow you to maintain persistence when using cookies and transitioning between two virtual servers (from HTTP to HTTPs).

Solution

While BigIP does offer “Match across services” option in some of the persistence profiles like sourceip, there is no such option for cookie persistence. The solution is to use universal persistence profile accompanied by custom-made iRule. Instead of creating persistence records based on node’s IP and port, custom iRule will use just IP address. This will allow you to stick to the same server regardless of which port you use.

Take the following steps to get this configured

  • Create iRule
# Check if there is a cookie and lookup persistence table 
# if the entry does not exist, loadbalance and save record 
when HTTP_REQUEST {
    if { [HTTP::cookie exists "bIPs"] } {
        persist uie [HTTP::cookie value "bIPs"]
    }
}
# For initial requests, we have to calculate MD5 
# checksum of the server's IP, convert it to hex, 
# then finally store it as a cookie and create persistence record 
when HTTP_RESPONSE {
    if { ![HTTP::cookie exists "bIPs"] } {
        binary scan [md5 [IP::server_addr]] H* md5var junk
        HTTP::cookie insert name "bIPs" path / value $md5var
        persist add uie [HTTP::cookie value "bIPs"]
    }
}

*Create universal persistence profile

ltm persistence universal persist-https_plus_s { 
 defaults-from universal 
 match-across-pools disabled 
 match-across-services enabled 
 match-across-virtuals disabled 
 mirror disabled 
 override-connection-limit disabled 
 rule cookie_persist_http_plus_s 
 timeout 3600 
}

*Create relevant pools and virtual servers

ltm pool POOL-HTTP { 
members { 
192.168.117.51:http { 
state up 
} 
192.168.117.52:http { 
state up 
} 
} 
monitor http 
} 
ltm pool POOL-HTTPS-81 { 
members { 
192.168.117.51:hosts2-ns { 
state up 
} 
192.168.117.52:hosts2-ns { 
state up 
} 
} 
monitor http 
} 

ltm virtual VS-192.168.113.101-80 { 
destination 192.168.113.101:http 
ip-protocol tcp 
mask 255.255.255.255 
persist { 
persist-https_plus_s { 
default yes 
} 
} 
pool POOL-HTTP 
profiles { 
http { } 
tcp { } 
} 
} 
ltm virtual VS-192.168.113.101-SSL { 
destination 192.168.113.101:https 
ip-protocol tcp 
mask 255.255.255.255 
persist { 
persist-https_plus_s { 
default yes 
} 
} 
pool POOL-HTTPS-81 
profiles { 
clientssl { 
context clientside 
} 
http { } 
tcp { } 
} 
} 
  • Enable OneConnect on each VS that uses this persistence profile.

CAUTION

Ensure that you enable OneConnect for each VS using this iRule. Otherwise it will not work as expected.