— Real-World Example with mail.it.nuface.tw and BIND9
0. Environment Overview
- Main domain:
nuface.tw - Mail domain:
it.nuface.tw - MX:
it.nuface.tw. MX 10 mail.it.nuface.tw. - Mail host:
mail.it.nuface.tw. A x.x.x.x - DNS: self-hosted BIND9 (Chunghwa Telecom as registrar only, DS uploaded)
- DNSSEC: enabled and working on
nuface.tw/it.nuface.tw/mail.it.nuface.tw - Mail server: Postfix (Docker)
- Certificate path (inside container):
/etc/letsencrypt/live/mail.it.nuface.tw/fullchain.pem/etc/letsencrypt/live/mail.it.nuface.tw/privkey.pem
Goal:
- Publish a TLSA record for
mail.it.nuface.tw:25 - Enable DANE in BIND9 + Postfix
- Allow remote MTAs to verify your MX using DANE
- Use DANE when you send mail to other DANE-enabled domains
1️⃣ Generate TLSA data (3 1 1) from your certificate
We’ll use this common combination:
- Usage:
3= DANE-EE (end-entity certificate) - Selector:
1= SubjectPublicKeyInfo - Matching type:
1= SHA-256
So the TLSA record will look like:
TLSA 3 1 1 <fingerprint>
Run this inside your mail container:
CERT=/etc/letsencrypt/live/mail.it.nuface.tw/fullchain.pem
openssl x509 -in "$CERT" -noout -pubkey \
| openssl pkey -pubin -outform DER \
| openssl sha256 -binary \
| hexdump -ve '32/1 "%02x" "\n"'
You’ll get something like:
3a5b7c9d2f4e8a0123456789abcdef0123456789abcdef0123456789abcdef0
Keep this value for the TLSA record.
2️⃣ Add TLSA to your BIND9 zone
Your current db.nuface.tw (excerpt):
$ORIGIN nuface.tw.
...
it.nuface.tw. IN MX 10 mail.it.nuface.tw.
it IN A x.x.x.x
mail.it IN A x.x.x.x
...
Append this TLSA record:
; DANE for SMTP (TCP/25) on mail.it.nuface.tw
_25._tcp.mail.it IN TLSA 3 1 1 (
3a5b7c9d2f4e8a0123456789abcdef0123456789abcdef0123456789abcdef0
)
Because of $ORIGIN nuface.tw.:
mail.it→mail.it.nuface.tw._25._tcp.mail.it→_25._tcp.mail.it.nuface.tw.
Don’t forget to bump the SOA serial:
@ IN SOA ns1.nuface.tw. postmaster.nuface.tw. (
2025112005 ; Serial (+1)
...
)
Reload BIND:
rndc reload nuface.tw
If you use inline-signing / auto-dnssec maintain, BIND will re-sign the zone automatically.
3️⃣ Verify TLSA is published and signed
From an external host:
dig _25._tcp.mail.it.nuface.tw TLSA +dnssec
You should see:
- The
TLSArecord - A corresponding
RRSIG - The
ad(Authenticated Data) flag in the response
This confirms the DNS side of DANE is correct.
4️⃣ Enable DANE in Postfix (outbound)
DANE is mainly used when you send mail out, to verify the remote MX and its TLSA record.
So we focus on the smtp_* settings.
In main.cf:
# Enable DNSSEC lookups
smtp_dns_support_level = dnssec
# Use DANE by default for outbound SMTP
smtp_tls_security_level = dane
# Optional but useful for debugging
smtp_tls_loglevel = 1
# Your inbound certificate (for others to verify you)
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.it.nuface.tw/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.it.nuface.tw/privkey.pem
# Inbound TLS policy (adjust to your needs)
smtpd_tls_security_level = may
Important:
smtp_*= Postfix as a client (sending mail to others)smtpd_*= Postfix as a server (receiving mail)- For inbound DANE, publishing a correct TLSA + DNSSEC is enough; no special Postfix knob is required.
Reload Postfix:
postfix reload
5️⃣ Testing DANE
- Find another DANE-enabled domain, or set up a test domain of your own.
- Send an email and watch your logs:
grep -i dane /var/log/mail.log
Typical successful log lines:
Verified TLS connection established using DANE
You can also use tools like posttls-finger or external DANE testers to validate behaviour.
6️⃣ Common pitfalls
- Certificate renewal without updating TLSA
- Let’s Encrypt renews every 90 days
- After renewal, regenerate the TLSA fingerprint and update the DNS zone
- Wrong TLSA value
- Make sure you use the correct certificate file and the full command pipeline
- Forgetting SOA serial / zone reload
- Always bump the SOA serial and
rndc reload
- Always bump the SOA serial and
- Partial DNSSEC deployment
- In your case both
it.nuface.twandmail.it.nuface.tware correctly signed – perfect 👍
- In your case both
7️⃣ Final notes
With:
- Self-hosted BIND9 + DNSSEC
mail.it.nuface.twas your MX- Let’s Encrypt certificates
- TLSA 3 1 1
- Postfix configured with
smtp_tls_security_level = dane
you now have a production-grade DANE deployment on top of an already strong email security stack (SPF, DKIM, DMARC, MTA-STS, etc.).