diff --git a/content/posts/2024/dane-tlsa-record-for-letsencrypt/index.md b/content/posts/2024/dane-tlsa-record-for-letsencrypt/index.md new file mode 100644 index 0000000..29d3c49 --- /dev/null +++ b/content/posts/2024/dane-tlsa-record-for-letsencrypt/index.md @@ -0,0 +1,212 @@ +--- +title: "How to create or renew a TLSA record for DANE with certificates from Let's Encrypt" +slug: create-or-renew-tlsa-records +description: > + I had to renew my TLSA records for DNS-based Authentication of Named Entities (DANE) + on my server that uses SSL certificates from Let's Encrypt. +date: 2024-10-03T09:26:58Z +draft: false +# ShowLastmod: true +toc: true +scrolltotop: true +tags: + - server + - certificate +--- + +I have been operating my own mail server for some 10+ years. Recently, some +e-mails that others attempted to send to me any my family would not longer be +delivered. This is a very unfortunate situation, because most people will not +make a second attempt (e.g., with a different recipient address), leave alone +provide you with an error message. However, luckily, this morning (Reunification +Day in Germany!), I received this screenshot: + +{{< figure src="outlook-error.jpg" + alt="(German) screenshot of an e-mail delivery error due to an invalid TLSA record" + caption="(German) screenshot of an e-mail delivery error due to an invalid TLSA record">}} + +And then it was all clear to me. The resource records (RR) in my domain-name +system (DNS) configuration that configure [DNS-based Authentication of Named +Entities (DANE)][dane] were no longer valid. I use certificates issued by Let's +Encrypt, and evidently their chain of trust had changed so that the trust +anchors that I had written into my DNS records were no longer valid. + +Correctly setting up TLSA records for DANE is everything but trivial. After some +trial and error, I found the following resource most useful: + + + +Key points: + +- When using TLSA RR in the form `2 1 1 ...`, i.e., declaring that the payload + (`...`) of the record is the digest of a "trust anchor", be aware that this + must be the `SHA256` digest of the _public key_ of your trust anchor. +- Let's Encrypt's `certbot` tool places three files on your server: `cert.pem`, + `chain.pem` and `fullchain.pem`, where `cert.pem` is the mail server's + certificate, `chain.pem` is the trust chain _excluding the root CA_ and + `fullchain.pem` is `cert.pem` + `chain.pem`. The important bit here is that + **none of these certificate files contain the root CA**! +- As a consequence, do not use a digest of Let's Encrypt's root CAs in your TLSA + record, _unless_ you want to add that root CA to the certificate files on your + server (don't). +- Configure TLSA records for _all_ intermediate CAs, e.g., R10-R14. + +Interstingly and embarassingly, the Information Sciences Institute (ISI) on +their page linked to above has a list of mail servers that still use a TLSA +record with a _retired_ CA from Let's Encrypt -- and that list contains +`bovender.de' :-/ I guess it's about time to fix that! + +## Let's Eencrypt's chains of trust + +Let's Encrypt's chains of trust are described here: + + + +For the reasons mentioned above, we are not interested in the root CAs (ISRG +Root X1 and ISRG Root X2). Instead, we want to use the digests of the public +keys of the subordinate (intermediate) CAs. At the time of writing (2024-10), +Let's Encrypt lists four active intermediate CAs: + +- E5 and E6 for certificates with ECDSA public keys +- R10 and R11 for certificates with RSA public keys + +To find out which of the two algorithms (ECDSA and RSA) was used to generate +your mail server's certificate, SSH into your server, navigate to +`/etc/letsencrypt/live/` as root and issue: + +```text +$ openssl x509 -in cert.pem -noout -text +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 03:d3:73:ef:60:97:31:88:bc:e5:31:99:f3:00:d5:b0:c1:92 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, O = Let's Encrypt, CN = R11 + Validity + Not Before: Sep 24 22:37:51 2024 GMT + Not After : Dec 23 22:37:50 2024 GMT + Subject: CN = bovender.de + Subject Public Key Info: +# ... +``` + +Thus, my mail server's current (!) certificate was issued by **R11**. + +This may be different in the future. For example, currently my web server's certificate uses the ECDSA algorithm: + +```text +$ cd ../bovender/ +$ openssl x509 -in cert.pem -noout -text +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 04:22:00:17:8a:ed:51:09:56:15:62:2e:b5:85:49:70:05:ac + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C = US, O = Let's Encrypt, CN = E6 + Validity + Not Before: Aug 19 11:34:11 2024 GMT + Not After : Nov 17 11:34:10 2024 GMT + Subject: CN = bovender.de +``` + +This certificate was issued by the **E6** intermediate CA. + +An alternative way to find out more about a web server's SSL certificate is to +use `curl`: + +```plain +$ curl -I --write-out '%{certs}' https://bovender.de +HTTP/2 301 +server: nginx/1.27.1 +date: Thu, 03 Oct 2024 09:25:05 GMT +content-type: text/html +content-length: 169 +location: https://www.bovender.de/ +strict-transport-security: max-age=63072000; includeSubDomains; preload + +# ... + +Subject:C = US, O = Let's Encrypt, CN = E6 +Issuer:C = US, O = Internet Security Research Group, CN = ISRG Root X1 + +# ... + +-----END CERTIFICATE----- +``` + +E6 again (surprise!). + +The key type that `certbot` uses to renew certificates is contained in +`/etc/letsencrypt/renewal/.conf`: + +```plain +$ cat mail.conf +# renew_before_expiry = 30 days +version = 2.11.0 +archive_dir = /etc/letsencrypt/archive/mail +cert = /etc/letsencrypt/live/mail/cert.pem +privkey = /etc/letsencrypt/live/mail/privkey.pem +chain = /etc/letsencrypt/live/mail/chain.pem +fullchain = /etc/letsencrypt/live/mail/fullchain.pem + +# Options used in the renewal process +[renewalparams] +account = [REDACTED] +authenticator = webroot +server = https://acme-v02.api.letsencrypt.org/directory +key_type = rsa +# ... +``` + +The line `key_type` declares that RSA be used for my mail server's certificate. + +## Setting up TLSA RRs in your DNS zone + +As advised by [ISI.edu][isi], it is best practive to have TLSA records for all +possible intermediate CAs as you will never know which intermediate CA will be +the next to issue a renewed certificate. This is even more important if you have +a cron job set up to automatically renew certificates that are about to expire. + +For the record (pun intended), here are my `_25._tcp` entries. Everything after +the pound sign (`#`) MUST NOT be included in the record, of course. + +```plain +2 1 1 2bbad93ab5c79279ec121507f272cbe0c6647a3aae52e22f388afab426b4adba # R10 +2 1 1 6ddac18698f7f1f7e1c69b9bce420d974ac6f94ca8b2c761701623f99c767dc7 # R11 +``` + +Following the advice by "~viktor" on [ISI.edu][isi], I have left only those two +records in my DNS zone that represent currently used intermediate CAs (R10 and +R11). I know that `certbot` will not issue ECDSA certificates for my mail server +because the configuration file (see above) contains the line `key_type=RSA`. My +web server has an ECDSA certificate, but I currently see no use for DANE for my +web server as [Chrome and Firefox do not support it][dane]. + +## Verify the validity of the TLSA record + +To test the DANE works as expected, try one of these sites: + +- +- +- + +Place this into your DNS records and wait for the updated records to propagate +worldwide. + +## "Die Moral von der Geschicht" + +"The moral of the story": + +- Server administration was, is, and will always be complicated. +- Always mistrust yourself. +- Regularly verify that everything works as expected, especially + security-related stuff. +- If something does not work, spend more time researching on the world wide web. + I came across the [ISI.edu][isi] page only after several hours and is was far + more useful for me than all the websites and blog and forum posts that I had + previously read. + +[dane]: https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities +[isi]: https://dnssec-stats.ant.isi.edu/~viktor/x3hosts.html diff --git a/content/posts/2024/dane-tlsa-record-for-letsencrypt/outlook-error.jpg b/content/posts/2024/dane-tlsa-record-for-letsencrypt/outlook-error.jpg new file mode 100644 index 0000000..a743cae Binary files /dev/null and b/content/posts/2024/dane-tlsa-record-for-letsencrypt/outlook-error.jpg differ