Vai al contenuto principale

Configurare DANE/TLSA con Postfix, Bind e Let's Encrypt

Di CaptainDNS
Pubblicato il 22 febbraio 2026

Schema architetturale che mostra Postfix, Bind9 e Let's Encrypt collegati tramite DANE/TLSA
TL;DR
  • DANE/TLSA lega il certificato TLS del tuo server mail a un record DNS firmato con DNSSEC, eliminando la dipendenza dalle autorità di certificazione
  • La combinazione consigliata è 3 1 1 (DANE-EE, SPKI, SHA-256): l'hash TLSA sopravvive ai rinnovi Let's Encrypt finché la chiave privata non cambia
  • Postfix supporta nativamente la verifica DANE in uscita con smtp_dns_support_level = dnssec e smtp_tls_security_level = dane
  • L'automazione avviene tramite un deploy-hook Certbot che rigenera l'hash TLSA e ricarica la zona Bind9 a ogni rinnovo
  • Verifica il tuo deployment con dig TLSA, openssl s_client e l'inspector DANE/TLSA CaptainDNS

Gestisci un server mail Postfix e vuoi proteggere le tue connessioni SMTP contro attacchi di tipo downgrade o man-in-the-middle? DANE (DNS-based Authentication of Named Entities) è la risposta. Pubblicando un record TLSA nella tua zona DNS firmata con DNSSEC, indichi ai server remoti quale certificato TLS il tuo server deve presentare. Nessun intermediario, nessuna autorità di certificazione di cui fidarsi.

La sfida con Let's Encrypt è il rinnovo automatico ogni 90 giorni. Se l'hash TLSA non corrisponde più al certificato, i server che verificano DANE rifiuteranno la connessione. Questo tutorial copre la configurazione completa dello stack Postfix + Bind9 + Let's Encrypt + DANE, inclusa l'automazione del rinnovo per evitare qualsiasi interruzione.

Questa guida è rivolta agli amministratori di sistema Linux che gestiscono un server mail self-hosted. Presuppone una conoscenza base di Postfix, DNS e della riga di comando. Per i fondamenti di DANE e TLSA, consulta la nostra guida completa DANE/TLSA (primo articolo di questa serie).

Prerequisiti

Prima di iniziare, verifica di avere:

ComponenteVersione minimaVerifica
Debian/Ubuntu12+ / 22.04+cat /etc/os-release
Postfix3.4+ (supporto DANE nativo)postconf mail_version
Bind99.18+ (DNSSEC inline-signing)named -v
Certbot2.0+certbot --version
DNSSEC attivoZona firmata + DS presso il registrardig +dnssec captaindns.com SOA

Se DNSSEC non è ancora attivo sulla tua zona, è il prerequisito. Bind9 9.18+ supporta l'inline-signing che semplifica la gestione. Attivalo prima di proseguire.

Porte e accesso di rete

Postfix utilizza la porta 25 (SMTP) e opzionalmente la 587 (submission). Let's Encrypt richiede la porta 80 o 443 per la challenge HTTP-01 (o una challenge DNS-01 se la porta 80 non è disponibile sul server mail). Assicurati che queste porte siano aperte nel tuo firewall.

Architettura dello stack Postfix, Bind9 e Let's Encrypt con DANE/TLSA

Configurare DNSSEC con Bind9

Se la tua zona è già firmata con DNSSEC, passa alla sezione successiva. Altrimenti, ecco la configurazione minima con Bind9 e l'inline-signing.

Attivare l'inline-signing

Nel tuo file di configurazione della zona (/etc/bind/named.conf.local o equivalente):

zone "captaindns.com" {
    type primary;
    file "/var/lib/bind/captaindns.com.zone";
    dnssec-policy default;
    inline-signing yes;
    key-directory "/var/lib/bind/keys";
};

La direttiva dnssec-policy default genera e gestisce automaticamente le chiavi ZSK e KSK. L'inline-signing firma la zona al volo senza modificare il file sorgente.

Pubblicare il DS presso il registrar

Dopo il primo caricamento della zona, Bind9 genera le chiavi. Recupera il DS record:

# Elencare le chiavi generate
ls /var/lib/bind/keys/

# Estrarre il DS record (adattare il nome del file KSK)
dnssec-dsfromkey /var/lib/bind/keys/Kcaptaindns.com.+013+xxxxx.key

Trasmetti il DS record al tuo registrar (interfaccia web o API). La propagazione richiede da pochi minuti a 48 ore a seconda del registrar.

Verificare la catena DNSSEC

dig +dnssec +short captaindns.com SOA
# Deve restituire il SOA con il flag "ad" (Authenticated Data)

dig +dnssec captaindns.com DNSKEY
# Deve restituire le DNSKEY con le firme RRSIG

Generare il certificato Let's Encrypt

Ottenere il certificato

# Installazione di Certbot (se non già installato)
apt install certbot

# Ottenere un certificato per l'hostname del server mail
certbot certonly --standalone -d mail.captaindns.com

Se la porta 80 è già utilizzata da un altro servizio, usa il plugin webroot o la challenge DNS-01:

# Alternativa con webroot (se Apache/Nginx è attivo sul server)
certbot certonly --webroot -w /var/www/html -d mail.captaindns.com

# Alternativa con challenge DNS (se porta 80 non disponibile)
certbot certonly --manual --preferred-challenges dns -d mail.captaindns.com

Configurare Postfix per usare il certificato

Modifica /etc/postfix/main.cf:

# Certificato TLS (ricezione - smtpd)
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.captaindns.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.captaindns.com/privkey.pem
smtpd_tls_security_level = may
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1

# Verifica DANE in uscita (smtp)
smtp_dns_support_level = dnssec
smtp_tls_security_level = dane
smtp_tls_loglevel = 1

I due blocchi hanno ruoli diversi: smtpd_tls_* configura il TLS per le connessioni in entrata (il tuo server presenta il suo certificato), mentre smtp_tls_* configura il TLS per le connessioni in uscita (Postfix verifica il TLSA del destinatario).

Ricarica Postfix:

postfix reload

Creare il record TLSA

Scegliere i parametri TLSA

La combinazione consigliata dalla RFC 7672 per SMTP è 3 1 1:

CampoValoreSignificato
Usage3 (DANE-EE)Verifica diretta del certificato del server
Selector1 (SPKI)Hash della chiave pubblica (non dell'intero certificato)
Matching type1 (SHA-256)Hash SHA-256

Il vantaggio del selector SPKI (1): l'hash non cambia quando rinnovi il certificato Let's Encrypt finché la chiave privata resta la stessa. È essenziale per evitare di aggiornare il TLSA a ogni rinnovo.

Generare l'hash TLSA

# Estrarre l'hash SPKI SHA-256 dal certificato
openssl x509 -in /etc/letsencrypt/live/mail.captaindns.com/cert.pem \
  -pubkey -noout | \
  openssl pkey -pubin -outform DER | \
  openssl dgst -sha256 -binary | \
  xxd -p -c 64

Il risultato è una stringa esadecimale di 64 caratteri, ad esempio:

a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890

Puoi anche usare il generatore DANE/TLSA CaptainDNS per generare il record senza comandi.

Aggiungere il TLSA nella zona Bind9

Il nome del record TLSA segue il formato _porta._protocollo.hostname. Per la porta 25 (SMTP):

_25._tcp.mail.captaindns.com. IN TLSA 3 1 1 a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890

Aggiungi questa riga al tuo file di zona, incrementa il serial del SOA, poi ricarica:

# Ricaricare la zona (Bind9 firma automaticamente con inline-signing)
rndc reload captaindns.com

Verificare la pubblicazione

# Verificare che il TLSA sia pubblicato e firmato
dig +dnssec _25._tcp.mail.captaindns.com TLSA

# Risultato atteso: il TLSA con le RRSIG

Automatizzare il rinnovo

Questa è la parte critica. Let's Encrypt rinnova il certificato ogni 90 giorni. Se usi DANE-EE con SPKI (3 1 1), l'hash non cambia finché Certbot riutilizza la stessa chiave privata. Ma devi assicurartene e prevedere il caso in cui la chiave cambi.

Strategia di conservazione della chiave

Di default, Certbot genera una nuova chiave a ogni rinnovo. Per conservare la stessa chiave (e quindi lo stesso hash TLSA), aggiungi l'opzione --reuse-key:

# Forzare il riutilizzo della chiave privata
certbot certonly --standalone -d mail.captaindns.com --reuse-key

Oppure aggiungi in /etc/letsencrypt/renewal/mail.captaindns.com.conf:

[renewalparams]
reuse_key = True

Deploy-hook per l'aggiornamento automatico

Anche con --reuse-key, è prudente predisporre un deploy-hook che verifichi l'hash e aggiorni il TLSA se necessario. Crea lo script /etc/letsencrypt/renewal-hooks/deploy/update-tlsa.sh:

#!/bin/bash
# Deploy-hook Certbot: aggiornamento TLSA se l'hash SPKI cambia

DOMAIN="mail.captaindns.com"
ZONE="captaindns.com"
ZONE_FILE="/var/lib/bind/captaindns.com.zone"
CERT="/etc/letsencrypt/live/$DOMAIN/cert.pem"

# Calcolare il nuovo hash SPKI SHA-256
NEW_HASH=$(openssl x509 -in "$CERT" -pubkey -noout | \
  openssl pkey -pubin -outform DER | \
  openssl dgst -sha256 -binary | \
  xxd -p -c 64)

# Recuperare l'hash attuale nel DNS
CURRENT_HASH=$(dig +short _25._tcp.$DOMAIN TLSA | awk '{print $4}')

if [ "$NEW_HASH" != "$CURRENT_HASH" ]; then
  echo "TLSA hash changed, updating zone..."

  # Sostituire l'hash nel file di zona
  sed -i "s/\(IN TLSA 3 1 1 \)[a-f0-9]\{64\}/\1$NEW_HASH/" "$ZONE_FILE"

  # Incrementare il serial (formato YYYYMMDDNN)
  CURRENT_SERIAL=$(grep -oP '\d{10}' "$ZONE_FILE" | head -1)
  NEW_SERIAL=$((CURRENT_SERIAL + 1))
  sed -i "s/$CURRENT_SERIAL/$NEW_SERIAL/" "$ZONE_FILE"

  # Ricaricare la zona
  rndc reload "$ZONE"

  echo "TLSA updated: $NEW_HASH"
else
  echo "TLSA hash unchanged, no update needed."
fi

# Ricaricare Postfix per applicare il nuovo certificato
postfix reload

Rendi lo script eseguibile:

chmod +x /etc/letsencrypt/renewal-hooks/deploy/update-tlsa.sh

Testare il rinnovo

# Simulare un rinnovo (dry-run)
certbot renew --dry-run

# Forzare un rinnovo reale (per testare l'hook)
certbot renew --force-renewal

Flusso di rinnovo automatico: Certbot rinnova il certificato, il deploy-hook verifica l'hash SPKI e aggiorna il TLSA in Bind9 se necessario

Strategia di rollover SPKI (cambio di chiave)

Se devi rigenerare la chiave privata (compromissione, migrazione), pubblica il nuovo TLSA prima di implementare il nuovo certificato. La RFC 7671 raccomanda un periodo di doppia pubblicazione:

  1. Generare la nuova chiave e calcolare il suo hash SPKI
  2. Pubblicare entrambi i TLSA nella zona (vecchio + nuovo)
  3. Attendere la propagazione DNS (minimo 2x TTL)
  4. Implementare il nuovo certificato
  5. Rimuovere il vecchio TLSA dopo la propagazione
; Doppio TLSA durante la transizione
_25._tcp.mail.captaindns.com. IN TLSA 3 1 1 <vecchio-hash>
_25._tcp.mail.captaindns.com. IN TLSA 3 1 1 <nuovo-hash>

Verificare la configurazione

Verifica DNS

# Verificare il TLSA
dig +short _25._tcp.mail.captaindns.com TLSA
# Atteso: 3 1 1 <hash-64-chars>

# Verificare DNSSEC
dig +dnssec _25._tcp.mail.captaindns.com TLSA | grep -c "RRSIG"
# Atteso: >= 1

Verifica TLS

# Testare la connessione TLS con verifica TLSA
openssl s_client -connect mail.captaindns.com:25 -starttls smtp \
  -dane_tlsa_domain mail.captaindns.com \
  -dane_tlsa_rrdata "3 1 1 $(dig +short _25._tcp.mail.captaindns.com TLSA | awk '{print $4}')"

Il risultato deve mostrare Verification: OK e DANE TLSA 3 1 1 matched EE certificate.

Verifica Postfix in uscita

Verifica che Postfix controlli correttamente DANE per le email in uscita:

# Inviare un'email di test e verificare i log
echo "Test DANE" | mail -s "DANE test" test@gmail.com
grep "Verified TLS connection" /var/log/mail.log | tail -5

I log devono menzionare dane nel livello di sicurezza.

Verifica online

Usa il verificatore di sintassi DANE/TLSA CaptainDNS per validare la sintassi del tuo record, poi l'inspector DANE/TLSA per una verifica completa che includa la catena DNSSEC.

Piano d'azione consigliato

Deployment DANE completo su un server mail self-hosted in 6 passaggi
  1. Configurare dnssec-policy default e inline-signing yes nella zona Bind9. Pubblicare il DS record presso il registrar. Verificare la catena di fiducia con dig +dnssec.

  2. Eseguire certbot certonly --standalone -d mail.captaindns.com --reuse-key per ottenere il certificato con conservazione della chiave privata.

  3. Modificare main.cf con i percorsi del certificato (smtpd_tls_*), attivare la verifica DANE in uscita (smtp_dns_support_level = dnssec, smtp_tls_security_level = dane).

  4. Generare l'hash SPKI SHA-256 con openssl, aggiungere il record _25._tcp.mail.captaindns.com. IN TLSA 3 1 1 &lt;hash&gt; nella zona, ricaricare con rndc reload.

  5. Creare il deploy-hook /etc/letsencrypt/renewal-hooks/deploy/update-tlsa.sh che confronta gli hash SPKI e aggiorna il TLSA se necessario. Testare con certbot renew --force-renewal.

  6. Validare con dig TLSA, openssl s_client -dane_tlsa_domain, i log Postfix e l'inspector DANE/TLSA CaptainDNS.

FAQ

Come generare un record TLSA per Let's Encrypt?

Usa il comando openssl x509 -in cert.pem -pubkey -noout | openssl pkey -pubin -outform DER | openssl dgst -sha256 -binary | xxd -p -c 64 per estrarre l'hash SPKI SHA-256. Il risultato di 64 caratteri esadecimali forma il dato del TLSA con i parametri 3 1 1.

Bisogna aggiornare il TLSA a ogni rinnovo Let's Encrypt?

No, se usi --reuse-key con Certbot e la combinazione DANE-EE/SPKI (3 1 1). L'hash SPKI dipende dalla chiave pubblica, non dal certificato. Finché la chiave privata resta la stessa, l'hash non cambia. Predisponi un deploy-hook di verifica per sicurezza.

Come attivare la verifica DANE in Postfix?

Aggiungi smtp_dns_support_level = dnssec e smtp_tls_security_level = dane in /etc/postfix/main.cf. Postfix verificherà automaticamente i TLSA dei domini destinatari tramite DNSSEC. Se il TLSA è assente o non valido, Postfix torna al TLS opportunistico.

DANE funziona con certificati auto-firmati?

Sì. Con DANE-EE (usage 3), il certificato è validato dal TLSA nel DNS, non da un'autorità di certificazione. Un certificato auto-firmato con un TLSA corretto e una zona DNSSEC valida viene accettato dai server che verificano DANE.

Come testare che DANE sia configurato correttamente?

Tre livelli di verifica: 1) dig +dnssec _25._tcp.mail.captaindns.com TLSA per il DNS, 2) openssl s_client -connect mail.captaindns.com:25 -starttls smtp -dane_tlsa_domain per la corrispondenza certificato/TLSA, 3) l'inspector DANE/TLSA CaptainDNS per un report completo che includa la catena DNSSEC.

Bind è obbligatorio o si può usare un altro server DNS?

Bind9 non è obbligatorio. Qualsiasi server DNS che supporti DNSSEC funziona: NSD, Knot DNS, PowerDNS. I principi sono identici, cambia solo la sintassi di configurazione. Bind9 è usato in questo tutorial perché è il più diffuso sui server Linux e il suo inline-signing semplifica la gestione DNSSEC.

Cosa succede se il TLSA non corrisponde più al certificato?

I server che verificano DANE (come Postfix con dane o Gmail) rifiuteranno di stabilire la connessione TLS e torneranno in modalità non crittografata o rifiuteranno il messaggio secondo la loro policy. Ecco perché la doppia pubblicazione TLSA durante le rotazioni di chiave è essenziale. Se il tuo TLSA è desincronizzato, rimuovilo temporaneamente per tornare al TLS opportunistico il tempo di correggere.

📚 Guide DANE/TLSA correlate

Fonti

Articoli simili