Let's Encrypt Open Beta, with DANE!

03 Dec 2015

So, I was stupid, didn't read properly, and tried to do this Let's Encrypt stuff without subscribing for the (then) closed beta. Now getting in was not really a problem, or so I've been told, but since today you can apply for the open beta.

Generating the certificate

Shameless copy-pasta from a couple of weeks back. I'm using letsencrypt-auto again, which does not support nginx yet. So if you are running a webserver, stop it. We want to get a certificate for both domain and a subdomain, so we pass them both as -d parameters.

$ git clone https://github.com/letsencrypt/letsencrypt.git
$ cd letsencrypt
# ./letsencrypt-auto auth -d luukhendriks.eu -d blog.luukhendriks.eu

If you tried this before, there might be built/cached stuff causing some trouble:

ImportError: No module named _io

In that case, an easy fix is (re)moving the existing stuff, which also might be in /home/$user/.local/share/ depending on whether you used sudo (credits to `Nemis' on the Let's Encrypt Community Forum):

mv /root/.local/share/letsencrypt{,.bak}

Configure nginx accordingly:

ssl_certificate             /etc/letsencrypt/live/luukhendriks.eu/fullchain.pem
ssl_certificate_key         /etc/letsencrypt/live/luukhendriks.eu/privkey.pem;

DANE-time: creating the TLSA record

If you are not familiar with DANE yet, there are a lot of sources on the Web explaining this better than I can, but the short version is something like this: as we trust the chain from root to domain in a DNSSEC scenario, we can trust values in the zone. We put a hash of our certificate under a special name, so clients can verify whether the certificate (served over HTTPS) for the requested domain matches what the domain owner put in the DNS. This is cool, because you could technically eliminate CA's and all that jazz.

So the only requirement here, is that your domain is DNSSEC signed. Now, create a hash of the certificate using one of the following ways:

$ openssl x509 -noout -fingerprint -sha256 < /etc/letsencrypt/live/luukhendriks.eu/cert.pem | sed 's/://g'

$ openssl s_client -connect blog.luukhendriks.eu:443 < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -sha256 -in /dev/stdin | sed 's/://g'

N.B.: If using the first option, use the cert.pem as input, not the fullchain.pem!

Add the TLSA record, it should look something like this:

_443._tcp.blog.luukhendriks.eu 1800 IN TLSA 3 0 1 85A6164F8D3F3B8E436625A952780081DF7B07E612FE9C0365FB368B6C60D473

The 3 0 1 are the Certificate Usage, Selector, and Matching Type fields, respectively, followed by the fingerprint we've just generated. Section 2.1 of RFC6698 describes all the possible options of those fields. In this case, it boils down to something like this Domain-issued certificate (3), which is a Full certificate (0), is presented by the following SHA-256 hash(1).

Check check double check

Simply browse to your website, and look for green things in your address bar. Make sure the new certificate is being served. Now to verify the TLSA record and get even more green stuff, check out DNSSEC/TLSA Validator by CZ.NIC Labs. It will add icons for both DNSSEC and TLSA validation. Now, if you roll with the cool guys and do v6-only stuff and use the SixOrNot plugin, you might stumble upon a situation where you find a Bogus DNSSEC Signature, depicted by a red padlock. Actually, you might see this on Mozilla Add-Ons page for SixOrNot: addons.mozilla.org is not served over v6, so your DNS64 translates the A record for you. You access the site over v6, so the browser/plugin sees a different IP address than signed in the DNS.

Why can't we simply have it all?