F5 Persistence Mirroring w/ iRules

img_1926

In a failover pair of devices, mirroring persistence records is important. When one LTM fails, we need the other to know which server a user’s session was “stuck” to. If a device failed and the other device was not aware of these records, the decision process would start again and a user could lose their session (wait for the tickets to roll in…) We want our HA pair of F5’s to failover seamlessly so they can be updated without impacting users, as well as transparency to end-users when a device fails.

The problem with the F5 is when you are using multiple persistence methodologies, mirroring does not function for each type you are using in the iRule, only the type in the ‘Default Persistence Profile’ chosen in the virtual-server. This is a problem when you are using a few different types in one iRule. For example; persist cookie, persist source_addr, persist uie, etc. all in one iRule.

So what do I do? The solution to this is difficult if not impossible to find in dev-central. I had to open a support case to even find this out. Use universal persistence!! In almost all cases when I opened support tickets the engineer would state that when I was using ‘persist cookie’ that it was unusual. I always thought to myself, “What, this is crazy!! Why even offer me a persistence type if it is not recommended to be used by the manufacturers of the device themselves!!”

The solution to this problem is to convert your existing iRule that uses a few different types of persistence to all use universal. The syntax may not be as simple, but universal persistence can do everything the other types can and more. Unfortunately F5 doesn’t have universal persistence documented very well (common theme), but this is a good start.

Let’s go over a simple example iRule. In this example I’m examining URI (virtual directory) and making decisions based on that value. I am using source IP and cookie hash stickiness. Different apps require different types of persistence. A normal person would offer what F5 provides, but that is not recommended by F5.

when HTTP_REQUEST {
 switch -glob [string tolower [HTTP::uri]] {
 "/app1*" {
 pool POOL-APP1
 persist source_addr 255.255.255.255
 }
 "/app2*" -
 "/app3*" {
 pool POOL-APP23
 persist cookie hash "ASP.NET_SessionId"
 }
 "/app4*" {
 pool POOL-APP4
 persist none
 }
 default {
 HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri]
 }
 }
 }

Unfortunately I can only pick one default persistence type in my virtual-server so not every record will fail over to the second node. We need to fix this by converting the syntax to universal and pick UIE as the default type.

when HTTP_REQUEST {
 switch -glob [string tolower [HTTP::uri]] {
 "/app1*" {
 pool POOL-APP1
 persist uie [IP::client_addr]
 }
 "/app2*" -
 "/app3*" {
 pool POOL-APP23
 persist uie [HTTP::cookie "ASP.NET_SessionId"]
 }
 "/app4*" {
 pool POOL-APP4
 persist none
 }
 default {
 HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri]
 }
 }
 }

Pretty simple, no? Now I assign my universal persistence profile with the ‘Mirror Persistence’ option checked.

uie1

Persistence records will now mirror to the passive device. View the records on each device by running ‘tmsh show ltm persistence persist-records’ to validate that the records are on each F5.

Aside: I think by now you all know how big of a fan I am of the Cisco ACE. Guess how easy this is with the ACE? Add ‘replicate sticky’ to your sticky group configuration. Way too simple…

F5 Persistence Mirroring w/ iRules

Poodle Vulnerability: Who’s Using SSLv3?

poodle

There are a ton of different articles on devcentral about certain iRules for changing the encryption that users are using, dropping them, etc. I found it difficult to find any code specific to just logging who is using SSLv3 so I can track them down and try to contact the customer. Managers found the reports that I generated useful to make a business decision instead of simply shutting of SSLv3 on the F5.

All this rule does is define a high-speed-logging server and send a message to the logging server so you can run reports against the logs. It logs source IP and URI (virtual-directory) from the request. Apply this to whichever virtual-server you need to log these requests from.

when CLIENT_ACCEPTED {
   set logpub [HSL::open -publisher /Common/HSL-SERVER]
}
when HTTP_REQUEST {
   set cipher [SSL::cipher version]
   set uri [HTTP::uri]
   if { $cipher equals "SSLv3" } {
      HSL::send $logpub "$cipher encryption used from client; [IP::client_addr] to $uri"
   }
}
Poodle Vulnerability: Who’s Using SSLv3?

iRule – IP Restrict Internal Applications

Fork in the road

In some scenarios it is necessary to limit access to applications behind the F5. Lets say you are hosting an application that is load balanced and is publicly and privately accessible on the same virtual-server. This can be accomplished by using an iRule.

In my scenario I need to limit access to applications running on an HTTP (non-SSL/TLS) virtual-server so that internal clear-text calls are permitted on the LAN, but users on the Internet are redirected to the same resource on HTTPS. My private networks all start with 10.* so it was fairly easy for me to write a rule to accomplish this. The rule can be customized to fit many different scenarios.

In summary my logic first inspects the IP address of the clients request. If it starts with 10., process the request by looking at URI (virtual-directory). If there is a successful match, send to the appropriate server. If not, redirect the full HOST and URI request from the client to HTTPS.

Secondarily if the clients IP does not match my public range, drop requests to certain resources that are not accessible at all from the Internet and redirect the rest to HTTPS as we did before.

 when HTTP_REQUEST {
    if { [IP::client_addr] starts_with 10. } {
       switch -glob [string tolower [HTTP::uri]] {
          "/app1*" -
          "/app2*" {
                pool POOL-APP-HTTP
                persist none
          }
          "/fs*" {
                pool POOL-FS-HTTP
                persist none
          }
          default {
                HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri]
          }
      }
 }
 else {
    switch -glob [string tolower [HTTP::uri]] {
       "/internal1*" {
          drop
       }
       default {
          HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri]
       }
    }
 }
}
iRule – IP Restrict Internal Applications