For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

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