by Nate Lampton

Setting up SSL Offloading (Termination) on an F5 Big-IP Load Balancer

At Lullabot several of our clients have invested in powerful (but incredibly expensive) F5 Big-IP Load Balancers. One of the primary reasons for investing in an F5 is for the purpose of SSL Offloading, that is, converting external HTTPS traffic into normal HTTP traffic so that your web servers don't need to do the work themselves. HTTPS requests (and more specifically, the SSL handshaking to start the connection) is incredibly expensive, often on the magnitude of at least 10 times slower than normal HTTP requests.

In a quick, largely unscientific test, here are two Apache Bench results against a stock Apache install, one with SSL and one without. Just serving up a static text file:

ab -c 100 -n 100 http://localhost/EXAMPLE.txt
Requests per second:    611.21 [#/sec] (mean)
Time per request:       163.609 [ms] (mean)
Time per request:       1.636 [ms] (mean, across all concurrent requests)
Transfer rate:          816.54 [Kbytes/sec] received

ab -c 100 -n 100 https://localhost/EXAMPLE.txt
Requests per second:    48.52 [#/sec] (mean)
Time per request:       2060.857 [ms] (mean)
Time per request:       20.609 [ms] (mean, across all concurrent requests)
Transfer rate:          64.82 [Kbytes/sec] received

Yikes, HTTPS is 12 times slower than HTTP! Not to mention more processor intensive. Comparing against nginx or Varnish, the slowness ratio increases as they serve HTTP traffic even faster. Now there are certainly ways to speed up SSL (using faster cyphers for example), but the fact remains that SSL is expensive. By using hardware-level decryption at the load balancer, the web server software (or reverse-proxy software like nginx or Varnish) can focus on serving pages.

Getting Started

For those not familiar with a Big-IP load balancer's administration, most of the configuration is done via a web interface, accessible via the device's IP address.

Big-IP Administration Page
The Big-IP Administrative interface

The navigation for the site is located in the left-hand column.

Adding SSL Certificates

The first thing you need to do to get SSL termination set up is to install the SSL certificate onto the machine. This is done by navigating to Local Traffic -> SSL Certificates -> Import. You must import the .key and the .crt files obtained from your Certificate Authority (i.e. Verisign, Comodo, etc.) separately with the same "Name" property. So give your certificate and key a name, usually matching the domain name, such as "example-com" or "example-com-wildcard". Upload the .key file as a Key, and the .crt file as a Certificate; both using the same value in the Name field.

Adding an SSL Certificate
Adding an SSL Certificate

After finishing, the list of SSL Certificates should include your certificate and key in the list as a single entry, meaning they're associated with each other.

After adding an SSL Certificate
After adding an SSL Certificate

Set up SSL Profile

Now that our SSL certificate is uploaded into the load balancer, we need to create an SSL profile that utilizes the certificate. Visit Local Traffic -> Profiles -> SSL -> Client. The term "Client" means traffic between the outside world and the load balancer (conversely "Server" means traffic between your internal servers and the load balancer). Click the "Create..." button to add a new profile.

Give your profile a name (it can be the same as the certificate if you like), such as "example-com-wildcard". Leave the Parent profile as the default "clientssl". Check the box for custom options, then select your Certificate and Key that should be used to communicate with your end-user browsers. Leave all the other defaults.

Adding the SSL Profile
Adding the SSL Profile

Set up the Virtual Server

F5 Load Balancers use a concept of a "Virtual Server" to accept connections at a certain IP address and hostname. I won't go into the details here and assume you already have a Virtual Server for HTTP.

If you already have a Virtual Server for HTTPS, edit it. If not, create a new virtual server with these settings:

Name: [same as your HTTP virual server, with "https" added somewhere]
Destination Type: Host
Destination Address: [same as your HTTP virtual server]
Service Port: 443, HTTPS
HTTP Profile: http
SSL Profile (Client): example-com-wildcard
SSL Profile (Server): None
SNAT Pool: [same as your HTTP virtual server]

Configuring the HTTPS Virtual Server
Configuring the HTTPS Virtual Server

The most important part of this configuration is selecting an SSL Profile for the "Client", but not for the "Server". This is all that is needed to actually "enable" SSL termination. The F5 is actually decrypting all incoming traffic no matter what, but by selecting "None" for the Server-side profile, the traffic simply is not re-encrypted before communicating with the back-end servers.

Don't skip this: Just because you have SSL termination enabled on this virtual server, you still need to point it at the correct location. If you're editing an existing virtual machine, it is probably currently pointing at a pool of servers on port 443. In the case of Apache, it will throw an error page, refusing to serve insecure HTTP pages over a secure port (443). To fix this (or set it up if this is a new virtual machine), click the "Resources" tab on the new virtual machine.

Under the "Load Balancing" section, select the same "Default Pool" option as you are using for your HTTP virtual machine. This makes it so that both HTTP and traffic that was formerly HTTPS come into the same port on your backend servers.

Setting the Load Balancing Pool to match the HTTP Virtual Server
Setting the Load Balancing Pool to match the HTTP Virtual Server

Identifying HTTPS traffic in your application

The only problem with the above approach to SSL termination is that all traffic getting to your web application is now over HTTP. This is a problem because often times security checks on the page will enforce an HTTPS connection and possibly attempt to redirect the user to HTTPS. In order for the application to avoid redirects like this, we need to inform the web server that the contents of the request were previously encrypted over HTTPS, even though they aren't any more.

To do this, it's recommended to set up an iRule that sets a special header. Visit Local Traffic -> iRules -> iRule List. Click the "Create..." button.

In the new iRule, give it a name such as "https-offloaded-header". In the rule contents, use the following code:

# Notify the backend servers that this traffic was SSL offloaded by the F5.
  HTTP::header insert "X-Forwarded-Proto" "https"; 

Save the iRule, then head back over to your virtual server under Local Traffic -> Virtual Servers -> Virtual Server List and click on your HTTPS virtual server. Under the "Resources" tab, click "Manage..." in the iRules section.

Move your new iRule from the "Available" list into the "Enabled" list. Moving it to the top of the rule list is also a good idea if you're doing any kind of HTTP/HTTPS redirects on your load balancer as setting headers after doing a redirect can cause pages to be undeliverable. Click "Finished" when done.

Now we're setting a special HTTP header on requests that have been SSL offloaded onto the F5. In your application, check this header in your code. For a PHP application, you may want to use this header to set the $_SERVER['HTTPS'] super-global. And even more specifically for Drupal (since that's what we do here at Lullabot), you would probably include code like this in your settings.php file.

  $_SERVER['HTTPS'] = 'On';

Since most PHP applications (including Drupal) check if they're on an HTTPS page by checking this variable, no further changes are necessary to the application.

If you're looking for more information on setting up an F5, Googling usually will not turn up too much because F5 has put the bulk of their documentation on a private site, for which you must first register (for free thankfully), at

Updated 5/10/2012: Switched iRule to using "X-Forwarded-Proto".