HAProxy SSL Termination (Offloading) Everything You Need to Know

The HAProxy load balancer provides high-performance SSL termination, allowing you to encrypt and decrypt traffic. You can quickly and easily enable SSL/TLS encryption for your applications by using HAProxy SSL termination.

HAProxy is compiled with OpenSSL, which allows it to encrypt and decrypt traffic as it passes. In this blog post, you will learn how to set this up and why delegating this function to HAProxy simplifies your infrastructure.

The Benefits of SSL Termination

When you operate a farm of servers, it can be a tedious task maintaining SSL certificates. Even using a Let’s Encrypt Certbot to automatically update certificates has its challenges because, unless you have the ability to dynamically update DNS records as part of the certificate renewal process, it may necessitate making your web servers directly accessible from the Internet so that Let’s Encrypt servers can verify that you own your domain.

Enabling SSL on your web servers also costs more CPU usage, since those servers must become involved in encrypting and decrypting messages. That CPU time could otherwise have been used to do other meaningful work. Web servers can process requests more quickly if they’re not also crunching through encryption algorithms simultaneously.

The term SSL termination means that you are performing all encryption and decryption at the edge of your network, such as at the load balancer. The load balancer strips away the encryption and passes the messages in the clear to your servers. You might also hear this called SSL offloading.

SSL termination has many benefits. These include the following:

  • You can maintain certificates in fewer places, making your job easier.

  • You don’t need to expose your servers to the Internet for certificate renewal purposes.

  • Servers are unburdened from the task of processing encrypted messages, freeing up CPU time.

Enabling SSL with HAProxy

HAProxy version 1.5, which was released in 2016, introduced the ability to handle SSL encryption and decryption without any extra tools like Stunnel or Pound. Enable it by editing your HAProxy configuration file, adding the ssl and crt parameters to a bind line in a frontend section. Here’s an example:

frontend www.mysite.com
bind 10.0.0.3:80
bind 10.0.0.3:443 ssl crt /etc/ssl/certs/mysite.pem
default_backend web_servers

The ssl parameter enables SSL termination for this listener. The crt parameter identifies the location of the PEM-formatted SSL certificate. This certificate should contain both the public certificate and the private key. That’s it for turning on this feature. Once traffic is decrypted it can be inspected and modified by HAProxy, such as to alter HTTP headers, route based on the URL path or Host, and read cookies. The messages are also passed to backend servers with the encryption stripped away.

Although you lose some of the benefits of SSL termination by doing so, if you prefer to re-encrypt the data before relaying it, then you’d simply add an ssl parameter to your server lines in the backend section. Here’s an example:

backend web_servers
balance roundrobin
server server1 10.0.1.3:443 check maxconn 20 ssl
server server2 10.0.1.4:443 check maxconn 20 ssl

When HAProxy negotiates the connection with the server, it will verify whether it trusts that server’s SSL certificate. If the server is using a certificate that was signed by a private certificate authority, you can either ignore the verification by adding verify none to the server line or you can store the CA certificate on the load balancer and reference it with the ca-file parameter. Here’s an example that references the CA PEM file:

backend web_servers
balance roundrobin
server server1 10.0.1.3:443 check maxconn 20 ssl ca-file /etc/ssl/certs/ca.pem
server server2 10.0.1.4:443 check maxconn 20 ssl ca-file /etc/ssl/certs/ca.pem

If the certificate is self-signed, in which case it acts as its own CA, then you can reference it directly.

Redirecting From HTTP to HTTPS

When a person types your domain name into their address bar, more likely than not, they won’t include https://. So, they’ll be sent to the http:// version of your site. When you use HAProxy for SSL termination, you also get the ability to redirect any traffic that is received at HTTP port 80 to HTTPS port 443.

Add an http-request redirect scheme line to route traffic from HTTP to HTTPS, like this:

frontend www.mysite.com
bind 10.0.0.3:80
bind 10.0.0.3:443 ssl crt /etc/ssl/certs/mysite.pem
http-request redirect scheme https unless { ssl_fc }
default_backend web_servers

This line uses the unless keyword to check the ssl_fc fetch method, which returns true unless the connection used SSL/TLS. If it wasn’t used, the request is redirected to the https scheme. Now, all traffic will end up using HTTPS.

This paves the way to adding an HSTS header, which tells a person’s browser to use HTTPS from the start the next time they visit your site. You can add an HSTS header by following the steps described in our blog post, HAProxy and HTTP Strict Transport Security (HSTS) Header in HTTP Redirects.

Limiting Supported Versions of SSL

As vulnerabilities are discovered in older versions of SSL and TLS, those versions are marked deprecated and should no longer be used. With HAProxy, you can allow only certain versions of SSL to be negotiated. Add an ssl-min-ver directive to a frontend, specifying the oldest version you want to support.

In the following example, only TLS version 1.2 and newer are allowed:

frontend www.mysite.com
bind 10.0.0.3:80
bind 10.0.0.3:443 ssl crt /etc/ssl/certs/mysite.pem ssl-min-ver TLSv1.2
http-request redirect scheme https unless { ssl_fc }
default_backend web_servers

Today, possible values for this parameter are:

  • SSLv3

  • TLSv1.0

  • TLSv1.1

  • TLSv1.2

  • TLSv1.3

You can set this for all proxies by adding it to your global section in the form of an ssl-default-bind-options directive, as shown:

global
ssl-default-bind-options ssl-min-ver TLSv1.2

Limiting Supported Certificates

In addition to setting the allowed versions of SSL and TLS, you can also set the encryption ciphers that you’ll use by adding a ciphers parameter to the bind line. These are set in preferred order, with fallback algorithms bringing up the end of the list. HAProxy will select the first cipher that the client also supports unless the prefer-client-ciphers parameter is present, in which case the client’s preferred cipher is selected.

It looks like this:

bind 10.0.0.3:443 ssl crt /etc/ssl/certs/mysite.pem ssl-min-ver TLSv1.2 ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256

Consider using the Mozilla SSL Configuration Generator when deciding which ciphers to include.

You can also set a default value by adding an ssl-default-bind-ciphers directive to your global section, as shown:

global
ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256

Choosing the Certificate With SNI

Server Name Indication (SNI) is a TLS extension that allows the browser to include the hostname of the site it is trying to reach in the TLS handshake information. You can use this to dynamically choose which certificate to serve.

Instead of setting the crt parameter to the path to a single certificate file, specify a directory that contains multiple PEM files. HAProxy will find the correct one by checking for a matching common name or subject alternative name.

Here’s an example:

frontend www.mysite.com
bind 10.0.0.3:80
bind 10.0.0.3:443 ssl crt /etc/ssl/certs/
http-request redirect scheme https unless { ssl_fc }
default_backend web_servers

If the client does not send SNI information, HAProxy uses the first file listed in the directory, sorted alphabetically. Therefore, it’s a good idea to name the PEM files so that the default certificate is listed first.

Supporting EC and RSA Certificates

HAProxy supports both Elliptic Curve (EC) and RSA certificates and will choose the one that the client supports. To enable this, store both certificates on the load balancer server, but name one with an .rsa extension and the other with an .ecdsa extension. For example, mycert.pem.rsa and mycert.pem.ecdsa. Then, in the HAProxy configuration, leave off the extension, like this:

bind 10.0.0.3:443 ssl crt /etc/ssl/certs/mycert.pem

Client Certificates

You can restrict who can access your application by giving trusted clients a certificate that they must present when connecting. HAProxy will check for this if you add a verify required parameter to the bind line, as shown:

bind 10.0.0.3:443 ssl crt /etc/ssl/certs/mysite.pem verify required ca-file /etc/ssl/certs/ca.pem crl-file /etc/ssl/certs/crl.pem

In addition to verify required, you can use ca-file to set a path to a CA file in order to verify that the client’s certificate is signed and trusted. You can also include a crl-file parameter to indicate a certificate revocation list.

Enabling SSL Termination: Final Word

In this blog post, you learned how to enable SSL termination with HAProxy. Allowing HAProxy to manage encryption and decryption has several benefits, including reducing work done on your backend servers, making certificate maintenance easier, and avoiding exposing your servers directly to the Internet for certificate renewal purposes.

Want to stay up to date on topics like this? Follow us on Twitter and subscribe to this blog! You can also join the conversation on Slack.

Explore the advanced features available in HAProxy Enterprise. Contact us to learn more and sign up for a free trial.

Subscribe to our blog. Get the latest release updates, tutorials, and deep-dives from HAProxy experts.