Cookie Encryption Across Pools and Services

Problem this snippet solves:

Implements cookie persistence based on node IP address, not member IP/port, so it will work across multiple pools even if the ports differ. You can apply this iRule to any number of virtual servers, each with their own pool, with pool members having differing ports. The only requirement is that all pools attached to all virtual servers using this iRule must have the same exact pool members with the exception of optional differing ports. If the ports are the same in every pool (or if there is only one pool attached to multiple virtual servers) then you can use a regular built-in cookie persistence profile with a custom cookie name. You do not need this iRule in that case. This rule requires a full LTM license.

Code :

# Note: Change all instances of BIGIP_COOKIE to rename the cookie, and
# all instances of "passphrase" to a real password.

# Note: As with any cookie persistence, be mindful of using this
# when the domain name changes as the cookie will be tied to a single
# domain.  You may want to modify the insert command to include a specific
# domain, but it must be a root domain of all of your sites (so you could
# use a domain of "abc.com" for sites "www.abc.com" and "secure.abc.com".

# All virtual servers must have an HTTP profile and a default pool.
# Requires TMOS 9.4.2 or higher

when HTTP_REQUEST {
# If the cookie exists, connect to the IP specified in the cookie
if { [HTTP::cookie exists "BIGIP_COOKIE"] } {
set decrypted [HTTP::cookie decrypt "BIGIP_COOKIE" "passphrase"]
if { ($decrypted ne "") } {
set persist_node [HTTP::cookie "BIGIP_COOKIE"]
foreach member [active_members -list [LB::server pool]] {
set node [lindex $member 0]
if { $node eq $persist_node } {
node $persist_node [lindex $member 1]
}
}
}
}
}

when LB_FAILED {
LB::reselect
}

when HTTP_RESPONSE {
   HTTP::cookie insert name "BIGIP_COOKIE" value [IP::remote_addr] path /
   # Optionally comment out the above line and use the following line
   # instead while specifying a domain
   # HTTP::cookie insert name "BIGIP_COOKIE" value [IP::remote_addr] path / domain abc.com
   HTTP::cookie encrypt "BIGIP_COOKIE" "passphrase"
}

# For versions below 9.4.2 (Contributed by bhattman at gmail.com) NOTE: Because active members -list doesn't exist in prior versions this version has to loop through a array of nodes in a pool. It's more involved works if you don't have version 9.4.2 or higher

when HTTP_REQUEST {
        # If the cookie exists, connect to the IP specified in the cookie
        if { [HTTP::cookie exists "BIGIP_COOKIE"] } {
                set decrypted [HTTP::cookie decrypt "BIGIP_COOKIE" "passphrase"]
                if { ($decrypted ne "") } {
                        set persist_node [HTTP::cookie "BIGIP_COOKIE"]
                        # Mimics active member -list for version prior to 9.4.2
set GOOD_NODES {}
set NS {     }
foreach N $NS {
        if { [LB::status pool  member $N ] eq "up" } {
           lappend GOOD_NODES $N
        }      
     }
                        foreach member $GOOD_NODES {
                                set node [lindex $member 0]
                                if { $node eq $persist_node } {
                                        node $persist_node [lindex $member 1]
                                }
                        }
                }
        }
}

when LB_FAILED {
        LB::reselect
}

when HTTP_RESPONSE {
   HTTP::cookie insert name "BIGIP_COOKIE" value [IP::remote_addr] path /
   # Optionally comment out the above line and use the following line
   # instead while specifying a domain
   # HTTP::cookie insert name "BIGIP_COOKIE" value [IP::remote_addr] path / domain abc.com
   HTTP::cookie encrypt "BIGIP_COOKIE" "passphrase"
}

Tested this on version:

9.4
Published Mar 17, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment