I've got a HAProxy 1.5.9 server that will serve either a certificate signed by a self signed CA or a Let's Encrypt certificate depending on which 'servername' is provided. This is my configuration file:

  mode tcp
  option clitcpka

listen ft_app
  bind *:5000 ssl crt /certs/private.pem ca-file /app/certs/self-signed-ca.pem crt /certs/self-signed.pem crt /app/certs/lets-encrypt.pem ciphers AES:ALL:!aNULL:!eNULL:!3DES:!DES:!RC4:!DHE:!EDH:!MD5:!PSK:!aECDH:@STRENGTH no-sslv3 no-tlsv10 no-tlsv11

  mode tcp
  option tcplog
  tcp-request inspect-delay 10s

  use_backend app_http if HTTP
  default_backend app_tcp

backend app_http
  mode http
  option httplog
  balance roundrobin

  reqadd X-Forwarded-Proto:\ https
  cookie SRVID insert indirect nocache
  http-check expect status 200

  server app_4 cookie app_4 check inter 10s rise 2 fall 2
  server app_3 cookie app_3 check inter 10s rise 2 fall 2
  server app_2 cookie app_2 check inter 10s rise 2 fall 2
backend app_tcp
  option tcp-check
  server app_4 check inter 10s rise 2 fall 2
  server app_3 check inter 10s rise 2 fall 2
  server app_2 check inter 10s rise 2 fall 2

It works. What I don't understand here is exactly how HAProxy selects which certificate to serve up. I assume that is grabbing the 'servername' from the certificate metadata. If so exactly which field, and how do I examine it, openssl x509 -in ca.pem -text -noout doesn't seem to have any likely suspects.


I figured it out. RTFM. From the HAProxy docs:


The certificates will be presented to clients who provide a valid TLS Server Name Indication field matching one of their CN or alt subjects. Wildcards are supported, where a wildcard character '*' is used instead of the first hostname component (eg: *.example.org matches www.example.org but not www.sub.example.org).

If no SNI is provided by the client or if the SSL library does not support TLS extensions, or if the client provides an SNI hostname which does not match any certificate, then the first loaded certificate will be presented. This means that when loading certificates from a directory, it is highly recommended to load the default one first as a file or to ensure that it will always be the first one in the directory.

So, it used the CN or alt name, or defaults to the first provided certificate. I checked the CN, which doesn't match, but then I found the alt name:

        X509v3 Subject Alternative Name: 

That matches the domain I connect with when I get that certificate! So in my case Haproxy selects the certificate using alt names as the CN isn't a FQDN.


The server name in a TLS certificate is first the “Common Name” displayed as Subject: ... CN=www.example.com

When you have a certificate that contains more than 1 server name it is called SAN certificate https://en.m.wikipedia.org/wiki/Subject_Alternative_Name

And the additional server names that are valid with that certificate are

DNS Name: example.com
DNS Name: www.example.om
DNS Name: ...


With Server Name Indication from the client HAProxy can match the requested url with the available certificates.

If no sni is used by the client or no certificate matches HAProxy probably uses the first certificate as the default (and the client gets a certificate mismatch error

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.