My F5 Needs HSTS!!

There are plenty of written resources out there about HSTS (HTTP Strict Transport Security). I don’t intend to explain or elaborate on what it is or why you want it. The IETF RFC is a good place to start.

F5 actually has a nice article with an iRule example of HSTS enforcement. HSTS pairs nicely with OCSP Stapling, check my previous article on how to do that on an F5.

However, in my environment we have servers internal to our network that call the same virtual-server as external customers that may send calls using HTTP and HTTPS. We network engineers never really know what developers do or plan on doing, but we don’t want to break anything on them now or in the future.

I’ve added a simple filter so that if calls from the 10.0.0.0/8 network come in to the virtual-server, just pass it on–otherwise, attach the HSTS header. This is optional, so tweak this to apply to your environment. If you don’t care about internal calls, remove the if statement. Once it’s in place, apply to your virtual-server and enjoy!!

UPDATE:

Initially I had RULE_INIT with “1 year” as the clock time determinant. This is good for performance reasons, because the event is only triggered once. Below is from F5’s iRule wiki showing when RULE_INIT is triggered:

hsts0

I noticed this on my iRule statistics page of my iRule, showing that the time that the iRule was saved, was the set time the max-age will be compared against.

hsts1

The problem with this is that over time, your HSTS max-age will slowly shorten unless your F5 is rebooted or the iRule is modified. This is not ideal, since we want this rule to be evergreen.

So, we have a couple options; change RULE_INIT to CLIENT_ACCEPTED or set your clock scan very far into the future to protect yourself. The HSTS draft doesn’t specify that having a very long max-age is not recommended, so at this point if you want to minimize CPU load on your F5, go that route. CLIENT_ACCEPTED will have a performance impact (likely nominal), but you know that your max-age will always be a set period of time, i.e. one year and you’ll never have to come back to this iRule.

CLIENT_ACCEPTED:

when CLIENT_ACCEPTED {
 set static::expires [clock scan "1 year"]
}
when HTTP_RESPONSE {
 if { [IP::client_addr] starts_with 10. } {
 }
 else {
   HTTP::header insert Strict-Transport-Security "max-age=[expr {$static::expires
   - [clock seconds]}]; includeSubDomains"
 }
}

Static Age:

when RULE_INIT {
  set static::expires [clock scan 20900101]
}
when HTTP_RESPONSE {
  if { [IP::client_addr] starts_with 10. } {
}
else {
  HTTP::header insert Strict-Transport-Security "max-age=[expr {$static::expires 
  - [clock seconds]}]; includeSubDomains"
 }
}
Advertisements
My F5 Needs HSTS!!