HAProxy and SNI-based SSL offloading with intermediate CA

In a world of diminishing IPv4 space and slow IPv6 adoption, SNI-based SSL is getting more and more important. Using the TLS extension SNI, only hardware limits the number of virtual SSL-hosts we can put on a single IP address. Most modern web browsers and web servers support SNI nowadays. Since September 2012, HAProxy supports native SSL as well which means the job of SSL-offloading can now be implemented with a simple HAProxy configuration:

frontend f_web_ssl
  bind ssl crt /etc/haproxy/default.pem crt /etc/haproxy/certs.d ciphers ECDHE-RSA-AES256-SHA:RC4-SHA:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM

This line will instruct HAProxy to look for server (since this is only one-way SSL) certificate files in /etc/haproxy/certs.d and match them to the SNI-name passed by the client. If no match is found or no SNI handshake was taking place, the default.pem certificate is presented to the client. The ciphers are included to pass the BEAST attack test.

Once a match is found, the frontend needs to be told which backend to use:

use_backend b_web if { hdr(host) -i www.my-sni-based-ssl-website.org }

Since there can be multiple certificates, there can be multiple use_backend (or use_server) lines in a frontend. Using the default backend we can also take care of non-SNI-capable clients.

Now, the documentation states that we have to copy the private and public key into one file in order to use it for SSL-offloading/SNI-matching. But what if there are additional intermediate CA certificates? Usually, intermediate CA certificates come with those these cheap domain validation Comodo PositiveSSL certificates. Once you send in the CSR, you’ll get the domain’s public key certificate (domain.crt), an intermediate PositiveSSLCA2.crt and the root AddTrustExternalCARoot.crt. The solution? Just concatenate the certificates into one file and HAProxy will deal with it just fine. It looks like the certificate order in the file matters:

  1. Private key certificate
  2. Public key certificate
  3. Intermediate CA certificate

To verify the new SNI-SSL-based virtual host is operating properly, use a SSL checker like www.ssllabs.com/ssltest.

5 thoughts on “HAProxy and SNI-based SSL offloading with intermediate CA

  1. Hi,
    Nice article.
    Sorry but I am a little bit confused.

    1, I need just make a folder and copy ssl files into the folder then refer to the folder with this sample?:

    bind ssl crt /etc/haproxy/default.pem crt /etc/haproxy/certs.d ciphers ECDHE-RSA-AES256-SHA:RC4-SHA:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM

    Will the haproxy read all the files and automatically recognize which cert belongs to which virtualhost?
    Or I don’t understand how that matching will work. I cannot see any matching rule just after with the backend.

    2, I use the startssl. Which give me 4 files.

    ssl.crt public cert
    ssl.key private cert
    sub.class1.server.ca.pem Intermediate CA certificate

    You just mentioned the first three. and the root cert?

    Thanks in advance,

    • Hi, MiszterX

      I use the startssl, the ‘trick’ cat ssl.crt ssl.key > ssl.pem in the HAProxy config file

      bind *:443 ssl crt /etc/ssl/ssl.pem


  2. Ran into a problem on this that others might want to know about…
    If you have multiple certificates for the same domain with different tld’s, such as:
    haproxy seems to just take the first certificate it finds in the directory that matches the domain name (“test”, in this case). So if I try to hit http://www.test.sk, it gives me the cert for http://www.test.com.
    So far, I haven’t found any way around this.

  3. Thanks for these haproxy articles. This is the second time you’ve helped me out with my config (the other one was the SSL redirect loop article)!

Comments are closed.