HTTP To HTTPS Cookie Persistence

Problem this snippet solves:

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. Decrypted HTTPS traffic is sent to backend servers on different port (e.g. 81). 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

Code :

# iRule v11 option

rule cookie_persist_http_plus_s {

# Check if there is a cookie and use persistence table
# if the entry does not exist, loadbalance and create record
when HTTP_REQUEST {
if { [HTTP::cookie value "bIPs"] ne "" } {
persist uie [HTTP::cookie value "bIPs"]
set need_cookie 0
} else {
set need_cookie 1
}
}
when PERSIST_DOWN {
# This event will only work in 11.0+. 
# Ask F5 Support for details on BZ225436 for details.

# Server that UIE peristence pointed to was down
set need_cookie 1
}
# Calculate CRC32 checksum of the server's IP
# and store it as a cookie and create persistence record
when HTTP_RESPONSE {
if { $need_cookie } {
HTTP::cookie insert name "bIPs" value [crc32 [IP::server_addr]] path "/"
persist add uie [HTTP::cookie value "bIPs"]
}
}
}

# iRule v10.x option

rule cookie_persist_http_plus_s {

# Check if there is a cookie and use persistence table
# if the entry does not exist, loadbalance and create record
when HTTP_REQUEST {
if { [HTTP::cookie value "bIPs"] ne "" } {
persist uie [HTTP::cookie value "bIPs"]
}
}
# Calculate CRC32 checksum of the server's IP
# and store it as a cookie and create persistence record
when HTTP_RESPONSE {
HTTP::cookie insert name "bIPs" value [crc32 [IP::server_addr]] path "/"
persist add uie [HTTP::cookie value "bIPs"]
}
}

# Once you have the iRule created, it's time to associate it with 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
}

# And finally you can create virtual servers and pools, for example:

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 { }
    }
}
Published Mar 18, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment