--- 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: - email - server - security --- 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 senders 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 from this and other pages to remember: - 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 Encrypt'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 when the certificate is renewed. 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 that DANE works as expected, try one of these sites: - - Query TLSA records: - ## "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