2019-05-04
Considering enabling Server Name Indication (SNI) on my webserver
While making a lot of my websites available via HTTPS I started wondering about enabling Server Name Indication (SNI) because the list of hostnames in the one certificate (subjectAltName parameter) keeps growing and they aren't all related. So on a test system with haproxy I created two separate private keys, two separate certificate signing requests and requested two separate certificates. One for the variants of camp-wireless.org and one for most of the idefix.net names. The whole requesting procedure happened on the system where my automated renewal and deployment of LetsEncrypt certificates with dehydrated happens so the request went fine. For the configuration of haproxy I was following HAProxy SNI where 'terminating SSL on the haproxy with SNI' gets a short mention. So I implemented the configuration as shown in that document and got greeted with an error:
haproxy[ALERT] 123/155523 (3435) : parsing [/etc/haproxy/haproxy.cfg:86] : 'bind :::443' unknown keyword '/etc/haproxy/ssl/webserver-idefix-main.pem'.And found out that the crt keyword has to be repeated. This is why I like having a test environment for things like this. Making errors in the certificate configuration on the 'production' server will give visitors scary and/or incomprehensible errors. So the right configuration for my test is now:frontend https-in bind :::443 v4v6 ssl crt /etc/haproxy/ssl/webserver-campwireless.pem crt /etc/haproxy/ssl/webserver-idefix-main.pemAnd testing it shows the different certificates in use when I use the -servername parameter for openssl s_client to test things.$ openssl s_client -connect testrouter.idefix.net:443 -servername idefix.net -showcerts -verify 3 .. Server certificate subject=/CN=idefix.net issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 .. Verification: OK $ openssl s_client -connect testrouter.idefix.net:443 -servername camp-wireless.org -showcerts -verify 3 .. Server certificate subject=/CN=www.camp-wireless.org issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 .. Verification: OKThe certificates are quite separate. Generating the certificate signing requests with a separate private key for each request works fine. So if I upgrade my certificate management to renew, transport, test and install multiple certificate for the main webserver it would work. Update 2019-05-04: Step one: writing a bit of extra tools to make really sure all the subjectAltName fields in the new certificate requests add up to the same list that was in the old certificate requests. I wanted to be really sure here! Update 2019-05-05: As you can see if you look very carefully at the certificates I made the move. The hard part was the automated transport, test and install of a bunch of certificates for the webproxy. I decided to use more Makefile smarts to combine the private key and generated certificate into a pem file for the server, and only reload the haproxy configuration after all the pem files are regenerated. The relevant bit:httpscertificates := $(wildcard /etc/haproxy/ssl/webserver-*.pem) /etc/haproxy/ssl/certificate-stamp: $(httpscertificates) /usr/sbin/service haproxy reload touch $@ /etc/haproxy/ssl/%.pem: /etc/haproxy/ssl/%.key /home/dehydrated/remotemanaged/%.crt /usr/local/bin/checkcert $^ cat $^ > $@The last rule is a generic rule to create a .pem file from a .key and .crt file, making sure first the .key file has the same public key as the .crt file. The rule for certificate-stamp depends on the already found .pem files and does a reload and touch when one of them was updated. This rule will not create new .pem files out of itself when a new .key and .crt show up. I will have to run a make for the right target by hand the first time. When adding or removing a certificate I will also have to update the haproxy config file. The next step could be to use a crt-list parameter and list all the found pem files in the file.