DANE for SMTP: binding TLS to DNS
DANE (DNS-based Authentication of Named Entities, RFC 6698 / 7671) lets you publish a
DNS record that says "the TLS cert at mx.example.com:25 must match this
fingerprint." Sending MTAs that support DANE will refuse to deliver mail if the
presented cert doesn't match. It's the strongest mail-channel TLS pinning available, and
it requires DNSSEC to be useful.
Why MTA-STS isn't enough
MTA-STS (RFC 8461) was designed as DANE-without-DNSSEC: an HTTPS-fetched policy that tells senders "use TLS to my MX." Two operational gaps:
- Trust on first use (TOFU). An attacker who controls your DNS during the policy fetch and can serve a cert for
mta-sts.example.comcan publish a permissive policy. DANE's anchor is signed in DNSSEC; MTA-STS's anchor is webPKI + DNSSEC-less DNS. - Cache fragility. A botched policy update with
mode: enforcecan lock out senders for the cached TTL. DANE TLSA matches the cert the receiver actually presents — no policy file to corrupt.
Most mature deployments run both. MTA-STS for senders that don't validate DANE (Microsoft 365, Yahoo). DANE for senders that do (Gmail, ProtonMail, large enterprise Postfix).
The TLSA record format
_25._tcp.mx.example.com. IN TLSA 3 1 1 \
E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
The four fields:
| Field | Values | Meaning |
|---|---|---|
| Usage | 0/1/2/3 | 3 = "exact cert/key, no PKI validation needed". The sane choice for SMTP. 0/1 require webPKI to also validate; 2 is "trust anchor." |
| Selector | 0/1 | 0 = full cert, 1 = SubjectPublicKeyInfo (just the public key). Use 1 — survives renewal-only-cert rotations. |
| Matching | 0/1/2 | 0 = full data, 1 = SHA-256 hash, 2 = SHA-512. Always 1. |
| Hash | hex | SHA-256 of the SPKI |
The recommended deployment: 3 1 1 (Usage 3, Selector SPKI, Matching SHA-256).
Computing the hash from your cert
openssl x509 -in mx-cert.pem -pubkey -noout | \
openssl pkey -pubin -outform DER | \
openssl dgst -sha256 -hex
That hex output (without the (stdin)= prefix) goes after 3 1 1
in the TLSA record.
The cert rotation gotcha
This is where DANE deployments fail most often. Let's Encrypt rotates your cert every
60-90 days. If you publish 3 1 1 <hash-of-current-cert>, then renewal
day will mismatch and senders will defer mail with TLSA validation errors.
Solutions:
- Pin the public key, not the cert. Use
certbot --reuse-keyso renewals keep the same key. Selector 1 (SPKI) means the hash stays valid across renewals. This is the standard approach. - Publish two records during rotation. Add the new key's hash to DNS, wait the TTL, rotate the cert, remove the old hash. Postfix and Exim with DANE-aware libs match if any TLSA record matches.
With --reuse-key + Selector 1, your TLSA record never needs to change for
the life of the keypair. Rotate the key (not just the cert) every couple of years.
The DNSSEC requirement is real
DANE without DNSSEC is worthless. Receiving MTAs (Postfix with smtp_tls_security_level
= dane) explicitly check that the TLSA records were retrieved from a DNSSEC-signed
zone. If your zone isn't signed, the lookup returns AD=0 (not authenticated) and Postfix
falls back to opportunistic TLS — DANE didn't help.
This is also why our DNSSEC contrarian piece has an exception: deploy DNSSEC if you want DANE.
Who validates DANE in 2026
| Sender | DANE validates inbound | Notes |
|---|---|---|
| Gmail (Workspace) | Yes (since 2024) | Default for outbound to DANE-published domains |
| Microsoft 365 | Yes (Outlook outbound, 2024 GA) | Requires admin opt-in for some tenants |
| Postfix (3.3+) | Yes | smtp_tls_security_level = dane or dane-only |
| Exim | Yes | Build-time option |
| ProtonMail | Yes | Default since 2022 |
DANE is no longer fringe. As of 2026 the major email providers handle it. The remaining gap is small business mail receivers running ancient sendmail with no operator.
Verifying your DANE deployment
# With danetool from gnutls or directly via dig
dig +dnssec +short TLSA _25._tcp.mx.example.com
# End-to-end check
posttls-finger -L verbose -l dane mx.example.com
posttls-finger (from Postfix) actually does the SMTP handshake and tells you
whether DANE matched. Run this after every cert rotation as a smoke test.
UnveilScan and DANE
Our tls_extended checker probes _25._tcp.<each-MX> for
TLSA records, validates the chain (signed via DNSSEC), and confirms each MX presents a
cert that matches. Findings: email.dane_tlsa_no_mx (you have TLSA but the
MX doesn't match), email.dane_tlsa_missing (MTA-STS without DANE — LOW).
Audit your mail TLS posture
Free Basic scan covers MX/STARTTLS/MTA-STS. Extended adds DANE TLSA validation, DKIM RSA-1024 detection, BIMI.
Run a scan