Persistence Cookie Parsing (TMOS 11.1+ compatible)

Problem this snippet solves:

Hi Folks,

the iRule below allows you to extract persistence cookie information as defined in SOL6917.

The provided iRule has support to extract persistence cookie information for:

  • IPv4 pool members
  • IPv4 pool members in non-default route domains
  • IPv6 pool members
  • IPv6 pool members in non-default route domains

The iRule stores the extracted information in the variable

$lb_select
in a
[LB::select]
compatible format as outlined below.

pool /Common/MyPool member 10.0.0.1 80
pool /Common/MyPool member 10.0.0.1%1 80
pool /Common/MyPool member 2001:0112:0000:0000:0000:0000:0030:0030 80
pool /Common/MyPool member 2001:0112:0000:0000:0000:0000:0000:0030%1 80

Cheers, Kai

How to use this snippet:

  1. Integrate the provided code in your iRule to extract and analyse persistence cookie information.
  2. Tweak the
    $pool
    and
    $cookie_name
    variables as needed to match a hardcoded pool and your custom cookie names.
  3. Access the
    $lb_select
    variable to extract the persistence cookie information.
  4. Enjoy!

Code :

when HTTP_REQUEST {

# Setting the currently selected pool and cookie name

set pool "[LB::server pool]"
set cookie_name "BIGipServer[getfield $pool "/" 3]"

# Inject the persistence cookie test values as outlined in SOL6917 
#
# IPv4 route domain disabled cookie value
# HTTP::header replace "Cookie" "BIGipServer[getfield $pool "/" 3]=1677787402.36895.0000"
# IPv6 route domain disabled cookie value
# HTTP::header replace "Cookie" "BIGipServer[getfield $pool "/" 3]=vi20010112000000000000000000000030.20480"
# IPv4 route domain enabled cookie value
# HTTP::header replace "Cookie" "BIGipServer[getfield $pool "/" 3]=rd5o00000000000000000000ffffc0000201o80"
# IPv6 route domain enabled cookie value
# HTTP::header replace "Cookie" "BIGipServer[getfield $pool "/" 3]=rd3o20010112000000000000000000000030o80"

# Trying to extract the persistence cookie value

if { [HTTP::cookie value $cookie_name] ne "" } then {
# A persistence cookie value is found. Enumerate the format of the persistence cookie value.
switch -glob -- [HTTP::cookie value $cookie_name] {
"rd*00000000000000000000ffff*" {
# The received persistence cookie has an route domain enabled IPv4 format
if { [scan [HTTP::cookie value $cookie_name] {rd%do00000000000000000000ffff%2x%2x%2x%2xo%d} rd oct1 oct2 oct3 oct4 port] == 6 } then {
# The received persistence cookie is well formated. Contructing the lb select string.
set lb_select "pool $pool member ${oct1}.${oct2}.${oct3}.${oct4}%$rd $port"
} else {
# The received persistence cookie is malformated.
set lb_select ""
}
}
"rd*" {
# The received persistence cookie has an route domain enabled IPv6 format
if { [scan [HTTP::cookie value $cookie_name] {rd%do%4[0-9a-fA-F]%4[0-9a-fA-F]%4[0-9a-fA-F]%4[0-9a-fA-F]%4[0-9a-fA-F]%4[0-9a-fA-F]%4[0-9a-fA-F]%[0-9a-fA-F]o%d} rd group1 group2 group3 group4 group5 group6 group7 group8 port] == 10 } then {
# The received persistence cookie is well formated. Contructing the lb select string.
set lb_select "pool $pool member ${group1}:${group2}:${group3}:${group4}:${group5}:${group6}:${group7}:${group8}%$rd $port"
} else {
# The received persistence cookie is malformated
set lb_select ""
}
}
"vi*" {
# The received persistence cookie has an route domain disabled IPv6 format
if { [scan [HTTP::cookie value $cookie_name] {vi%4[0-9a-fA-F]%4[0-9a-fA-F]%4[0-9a-fA-F]%4[0-9a-fA-F]%4[0-9a-fA-F]%4[0-9a-fA-F]%4[0-9a-fA-F]%[0-9a-fA-F].%d.} group1 group2 group3 group4 group5 group6 group7 group8 port] == 9 } then {
# The received persistence cookie is well formated. Extracting the port information
set port [format %04x ${port}]
set port [expr { "0x[string range $port 2 3][string range $port 0 1]" }]
# Contructing the lb select string.
set lb_select "pool $pool member ${group1}:${group2}:${group3}:${group4}:${group5}:${group6}:${group7}:${group8} $port"
} else {
# The received persistence cookie is malformated
set lb_select ""
}
}
"*.*.*" {
# The received persistence cookie has an route domain disabled IPv4 format
if { [scan [HTTP::cookie value $cookie_name] {%d.%d.} ipv4 port] == 2  } then {
# The received persistence cookie is well formated. Extracting the port information
set port [format %04x $port]
set port [expr { "0x[string range $port 2 3][string range $port 0 1]" }]
# Extracting the IPv4 octets and contructing the lb select string.
scan [format %08x $ipv4] "%2x%2x%2x%2x" oct4 oct3 oct2 oct1
set lb_select "pool $pool member ${oct1}.${oct2}.${oct3}.${oct4} $port"
} else {
# The received persistence cookie is malformated
set lb_select ""
}
}
default {
# The received persistence cookie has an unknown format
set lb_select ""
}
}
} else {
# The current request does not provide a persistence cookie
set lb_select ""
}
# Log the extracted cookie information
log local0.debug "Cookie Persistence Info: $lb_select"
}

Tested this on version:

12.0
Updated Jun 06, 2023
Version 2.0
No CommentsBe the first to comment