Rotazione chiavi DKIM: runbook operativo (G-7 a G+30)
Di CaptainDNS
Pubblicato il 19 maggio 2026

- Frequenza consigliata: da 6 a 12 mesi in produzione standard, 3 mesi in ambienti critici (settore bancario, pubblico)
- Strategia senza interruzioni: due selettori in parallelo, 7 giorni prima del passaggio, 30 giorni dopo il ritiro
- Algoritmi: RSA 2048 resta il valore predefinito compatibile, Ed25519 in double-publish per i MTA moderni
- Archiviazione: chiave privata in KMS (AWS, GCP, Vault), mai in chiaro in un repository Git
- Automazione: cron ogni 3-6 mesi, validazione post-rotazione tramite i report DMARC aggregate
La rotazione delle chiavi DKIM è un'operazione ricorrente. Le guide dei fornitori (Microsoft, AWS, SendGrid) descrivono il pulsante "rotate" senza spiegare la finestra di sovrapposizione, il ritardo di propagazione DNS o la procedura di ripristino. Questo runbook colma tale lacuna con una timeline calendariale da G-7 a G+30, script openssl testati e le insidie segnalate sul campo.
Per il riferimento generale, consultare la guida completa DKIM. Qui l'obiettivo è operativo: generare la coppia di chiavi DKIM, pubblicare il selettore DKIM, commutare la firma, monitorare DMARC, ritirare il selettore precedente. Pubblico previsto: sistemisti, DevOps, SRE e team di infrastruttura in produzione.
Verifichi i suoi selettori DKIM prima della rotazione
Perché ruotare le chiavi DKIM?
Tre ragioni operative giustificano la rotazione periodica.
Compromissione della chiave. Una chiave privata DKIM finisce sempre per trapelare: backup non cifrato, accesso KMS legacy di un ex dipendente, dump di un fornitore SaaS. La rotazione limita la finestra di sfruttamento di una fuga.
Limite crittografico. La RFC 8301 ha deprecato le chiavi RSA inferiori a 1024 bit già nel 2018 e raccomanda almeno RSA 2048. Una chiave RSA 1024 pubblicata nel 2018 oggi viene rifiutata da Google, Yahoo e Microsoft. Ruotare regolarmente costringe a sostituire gli algoritmi legacy.
Igiene crittografica. NIST SP 800-57 Part 1 Rev. 5 raccomanda criptoperiodi brevi per le chiavi di firma: da 1 a 2 anni al massimo, più brevi per gli ambienti sensibili. Senza rotazione regolare, la prima rotazione forzata si trasforma in un disastro.
DKIM2, in corso di standardizzazione presso l'IETF, aggiunge una protezione contro la riproduzione ma non elimina la necessità di rotazione delle chiavi DKIM. Pertanto, vedere DKIM2 e la protezione contro il replay.
Strategia: selettori paralleli anziché sostituzione diretta
Principio fondamentale: non sostituire mai una chiave DKIM con overwrite. Pubblicare sempre un nuovo selettore in parallelo, commutare la firma e poi ritirare il selettore precedente dopo un periodo di tolleranza.
Tre fattori impongono la coesistenza temporanea:
- Cache del resolver DNS. Il valore TXT di un selettore resta in cache per il TTL (da 1 a 24 ore). Alcuni resolver servono ancora il valore precedente.
- Retry SMTP. Un MTA destinatario mantiene un messaggio in coda fino a 5 giorni. Se il selettore viene ritirato troppo presto, la riverifica fallisce.
- Audit forense. I team di sicurezza devono verificare la firma di un messaggio ricevuto due settimane prima. Un selettore ritirato rende tale verifica impossibile.
Convenzione di denominazione: selettori datati trimestralmente. Esempio: s2026-q1 per gennaio-marzo 2026, s2026-q2 per quello successivo. Questa convenzione evita collisioni con i selettori vendor (selector1 Microsoft 365, google Google Workspace, mte1 SendGrid). I due selettori coesistono durante la finestra di sovrapposizione:
s2025-q4._domainkey.captaindns.com. 3600 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOC..."
s2026-q1._domainkey.captaindns.com. 3600 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOC..."
Durata minima di sovrapposizione: 7 giorni sul lato propagazione, 30 giorni sul lato ritiro per coprire i retry SMTP più lunghi.
Calendario operativo della rotazione
Generare la nuova coppia (vedere la sezione successiva), archiviare la chiave privata in KMS, pubblicare la chiave pubblica sotto il nuovo selettore nel DNS senza attivare la firma lato MTA. La finestra di 7 giorni copre la propagazione DNS e consente una verifica di integrità prima della commutazione.
dig +short TXT s2026-q1._domainkey.captaindns.comIl selettore precedente firma ancora tutti i messaggi in uscita. Verificare il contenuto pubblicato con il DKIM Record Check.
Riconfigurare il MTA per firmare con il nuovo selettore. La commutazione deve essere atomica: evitare di firmare alternativamente con le due chiavi, ciò complica l'audit DMARC.
Su Postfix combinato con OpenDKIM, modificare
KeyTableeSigningTable, quindi ricaricare. Su SES BYODKIM, invocareaws sesv2 put-email-identity-dkim-signing-attributes. Su Microsoft 365, il cmdletRotate-DkimSigningConfiggestisce automaticamente la commutazione.Per 24 ore, analizzare i report DMARC. Il campo
auth_results/dkim/selectordeve riflettere il nuovo selettore per il 100 % del traffico legittimo. Qualsiasi traccia del selettore precedente indica un flusso riconfigurato male. Soglia di allerta: 1 % di traffico residuo sul selettore precedente dopo 48 ore.Aggregare i report DMARC degli ultimi 7 giorni. Se il nuovo selettore copre il 100 % del traffico, passare a G+8. In caso contrario, prolungare la finestra e analizzare i flussi residui (cron job interni, applicazioni legacy, fornitore terzo).
Disattivare qualsiasi possibilità tecnica di firmare con il selettore precedente. Il TXT pubblico resta pubblicato per consentire la verifica dei messaggi in coda retry.
Su OpenDKIM, rimuovere la riga corrispondente. Su Vault, revocare il lease di lettura della chiave precedente per impedire qualsiasi rollback accidentale.
Eliminazione definitiva del record TXT. Il termine di 30 giorni copre i retry SMTP (fino a 5 giorni) e le cache DNS atipiche. Dopo l'eliminazione, verificare che
dig +short TXT s2025-q4._domainkey.captaindns.comrestituisca una risposta vuota. Distruggere la chiave privata corrispondente in KMS.
| Giorno | Azione | Selettore precedente | Selettore nuovo |
|---|---|---|---|
| G-7 | Pubblicare il TXT del nuovo selettore | Firma e pubblicato | Pubblicato (inattivo) |
| G+0 | Commutare la firma MTA | Pubblicato | Firma e pubblicato |
| G+1 | Monitorare i report DMARC | Pubblicato | Firma e pubblicato |
| G+7 | Validare 100 % del traffico sul nuovo | Pubblicato | Firma e pubblicato |
| G+8 | Rimuovere la firma MTA del precedente | Pubblicato (congelato) | Firma e pubblicato |
| G+30 | Eliminare il TXT precedente | Eliminato | Firma e pubblicato |

Generare la coppia con openssl
Quattro comandi openssl coprono la totalità delle esigenze. Tutti sono stati testati con OpenSSL 3.x.
RSA 2048: generazione della chiave privata.
openssl genrsa -out dkim_private.pem 2048
RSA 2048: estrazione della chiave pubblica in base64 per il DNS.
openssl rsa -in dkim_private.pem -pubout -outform der | openssl base64 -A
Il risultato è il valore da incollare nel tag p= del record TXT.
Ed25519: generazione della chiave privata.
openssl genpkey -algorithm ed25519 -out dkim_ed25519_private.pem
Ed25519: estrazione della chiave pubblica in base64 (32 byte).
openssl pkey -in dkim_ed25519_private.pem -pubout -outform der | tail -c 32 | openssl base64
Il tail -c 32 è necessario: openssl emette un header ASN.1 di 12 byte davanti ai 32 byte effettivi della chiave Ed25519, header che la RFC 8463 impone di rimuovere per p=.
Tabella comparativa delle tre opzioni realistiche nel 2026:
| Algoritmo | Dimensione chiave pubblica | Dimensione firma | Supporto 2026 | Rischio TXT split |
|---|---|---|---|---|
| RSA 2048 | ~392 caratteri | 256 byte | Universale | Basso (1 stringa) |
| RSA 4096 | ~736 caratteri | 512 byte | Universale | Alto (3 stringhe TXT) |
| Ed25519 | ~44 caratteri | 64 byte | Parziale (Google, Fastmail, MTA open source) | Nessuno |
Raccomandazione 2026: RSA 2048 da solo per la massima compatibilità, oppure double-publish RSA 2048 più Ed25519 per beneficiare della firma Ed25519 presso i ricevitori compatibili. Evitare RSA 4096: la chiave pubblica supera i 255 caratteri e impone una suddivisione TXT in più stringhe, fragile a ogni modifica DNS. Per il dettaglio comparativo, vedere RSA vs Ed25519 per DKIM.
Gestione della chiave privata
La chiave privata DKIM è un segreto crittografico al pari di una chiave TLS. Esistono tre modelli di archiviazione accettabili in produzione.
KMS gestito (AWS KMS asymmetric keys, GCP Cloud KMS, Azure Key Vault). La chiave viene generata e resta nell'HSM. Il MTA invoca l'API KMS per firmare ogni messaggio. La chiave privata non viene mai esposta nella memoria dell'applicazione, la rotazione è tracciata tramite IAM. Svantaggio: da 5 a 20 ms di latenza per chiamata.
HashiCorp Vault Transit. Equivalente self-hosted del KMS gestito. La chiave resta nel backend Transit, il MTA firma tramite l'API. Percorso convenzionale: secret/dkim/captaindns/s2026-q1.
File PEM cifrato a riposo. Minimo accettabile per le piccole infrastrutture. La chiave viene archiviata sul server di invio in un volume cifrato (LUKS, encrypted EBS), permessi 0600, proprietario opendkim:opendkim. Distribuzione tramite Ansible Vault, Sealed Secrets di Kubernetes o SOPS.
Anti-pattern da bandire:
- Chiave privata commitata nel repository Git, anche in branch privato. Git conserva la cronologia per sempre.
- Chiave privata passata come variabile d'ambiente non cifrata (
DKIM_PRIVATE_KEY=...) in un docker-compose o un file.env. - Chiave privata archiviata in un secret manager condiviso con account di servizio non necessari (principio del minimo privilegio violato).
Al momento della rotazione, non dimenticare di ruotare anche gli accessi KMS. Un ex dipendente che abbia avuto accesso in lettura a secret/dkim/captaindns/s2025-q4 non deve mantenere tale accesso anche se la chiave non è più attiva: resta valida per firmare messaggi retrodatati.

Automatizzare la rotazione tramite cron
Una rotazione manuale viene dimenticata alla prima assenza del team. L'automazione è indispensabile oltre i 3-4 domini attivi. Suddividere il job in 3 fasi idempotenti:
- Generate: produrre la coppia e archiviare la chiave privata in KMS.
- Publish-DNS: invocare l'API del provider DNS per aggiungere il TXT.
- Switch-signing: riconfigurare il MTA dopo la finestra G-7.
Scheletro bash Generate + Publish-DNS su Cloudflare:
#!/bin/bash
set -euo pipefail
SELECTOR="s$(date +%Y-q%q)"
DOMAIN="captaindns.com"
ZONE_ID="${CLOUDFLARE_ZONE_ID}"
# Generate RSA 2048
openssl genrsa -out "dkim_${SELECTOR}.pem" 2048
PUB=$(openssl rsa -in "dkim_${SELECTOR}.pem" -pubout -outform der | openssl base64 -A)
# Store private key in Vault
vault kv put "secret/dkim/${DOMAIN}/${SELECTOR}" private_key=@"dkim_${SELECTOR}.pem"
# Publish DNS via Cloudflare API
curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
-H "Content-Type: application/json" \
--data "{\"type\":\"TXT\",\"name\":\"${SELECTOR}._domainkey\",\"content\":\"v=DKIM1; k=rsa; p=${PUB}\",\"ttl\":3600}"
# Verify publication
sleep 30
dig +short TXT "${SELECTOR}._domainkey.${DOMAIN}"
Cron: 0 3 1 */6 * (ogni 6 mesi, il 1° del mese alle 3 UTC) avvia la fase Generate più Publish-DNS, seguita 7 giorni dopo da un secondo cron che esegue Switch-signing.
Integrazioni vendor:
- AWS SES BYODKIM: comando
aws sesv2 put-email-identity-dkim-signing-attributescon la coppiaDomainSigningSelectoreDomainSigningPrivateKeycodificata in base64. - Microsoft 365:
Rotate-DkimSigningConfig -Identity captaindns.com -KeySize 2048(Exchange Online PowerShell). La rotazione genera un nuovo selettore lato Microsoft ma impone di pubblicare il nuovo CNAME nel DNS per attivare la nuova chiave. - SendGrid: la rotazione viene gestita tramite l'API
POST /whitelabel/domains/{id}/validatedopo aver aggiunto il nuovo CNAME presso il provider DNS.
Allertamento consigliato: di conseguenza, è necessario scatenare un allarme se il tasso dkim=fail nei report DMARC aggregate supera l'1 % durante la finestra G+0 a G+7. La validazione post-rotazione viene eseguita in modo programmatico tramite l'API DKIM Record Check.

Insidie ricorrenti da evitare
Cinque insidie ricorrenti emergono dai ticket di supporto e dai thread reddit r/sysadmin.
TTL troppo lungo sul selettore precedente. Un TTL di 24 ore impedisce la propagazione rapida di una correzione. Abbassare il TTL a 300 secondi 48 ore prima di G+0, poi riportarlo a 3600 secondi dopo G+7.
Selettore con trattini mal posizionati. Alcuni parser DKIM stretti rifiutano un selettore contenente un trattino in prima o ultima posizione. Preferire s2026q1 a -s2026-q1-.
DMARC in allineamento stretto (adkim=s). Una firma d=mail.captaindns.com viene rifiutata per un From: contact@captaindns.com. Verificare che il dominio d= della nuova chiave resti identico a quello della precedente.
Chiave pubblica nascosta lato SaaS. Mailchimp, ActiveCampaign e altri pubblicano un CNAME anziché un TXT diretto. In pratica, la rotazione è gestita dal fornitore: occorre validare che il CNAME punti alla nuova destinazione dopo la rotazione dichiarata.
Tag s= mal configurato. Il tag opzionale s=email restringe l'uso della chiave alla firma di messaggi email. Una chiave pubblicata con s=* o senza tag accetta tutti i servizi. Per il dettaglio, vedere il tag s= nel record DKIM.
Esempio di TXT mal codificato (avvolgimento base64 multilinea con ritorno a capo grezzo, rifiutato da alcuni resolver):
s2026-q1._domainkey.captaindns.com. IN TXT ( "v=DKIM1; k=rsa; "
"p=MIIBIjANBgkqhkiG\n"
"9w0BAQEFAAOC..." )
Esempio corretto (stringa unica o suddivisione pulita in blocchi di 255 caratteri):
s2026-q1._domainkey.captaindns.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
FAQ
FAQ
Con quale frequenza occorre ruotare una chiave DKIM?
Da 6 a 12 mesi in produzione per un'organizzazione standard, 3 mesi in ambiente critico (banca, settore pubblico). La RFC 6376 non fissa una durata ma NIST SP 800-57 raccomanda criptoperiodi brevi per le chiavi di firma. Oltre i 18 mesi, il rischio di fuga (backup, ex dipendenti, accessi KMS legacy) supera il costo operativo di una rotazione pulita.
Cosa fare se i report DMARC segnalano dkim=fail durante la rotazione?
Verificare anzitutto che il nuovo selettore sia pubblicato con dig +short TXT s2026-q1._domainkey.captaindns.com, poi validare la firma con un DKIM record checker. Se il selettore precedente è stato ritirato troppo presto, ripubblicarlo con lo stesso p= e attendere 7 giorni. Le cache dei resolver (fino a 24 h) e i retry SMTP (fino a 5 giorni) spiegano la maggior parte dei fallimenti.
È possibile ruotare una chiave DKIM senza downtime?
Sì, è l'unica modalità operativa accettabile in produzione. La strategia si basa su due selettori in parallelo: il nuovo pubblicato 7 giorni prima del passaggio, il precedente conservato 30 giorni dopo. Durante la sovrapposizione, entrambe le firme sono valide. Nessuna interruzione, nessun messaggio rifiutato per dkim=none.
Come ruotare in un ambiente multi-provider (M365, AWS SES, SendGrid)?
Ogni provider gestisce il proprio selettore DKIM, quindi le rotazioni sono indipendenti ma devono essere coordinate. Procedura: 1) elencare tutti i selettori attivi tramite un audit DNS, 2) pianificare le rotazioni sfalsate di due settimane per isolare le fonti di errore, 3) verificare che selector1._domainkey (M365), s2026-q1._domainkey (SES BYODKIM) e s1._domainkey (SendGrid) coesistano senza collisione.
RSA 2048, RSA 4096 o Ed25519: cosa scegliere nel 2026?
RSA 2048 resta il valore predefinito compatibile. Ed25519 è più sicuro e più rapido ma richiede un double-publish (k=rsa e k=ed25519) perché alcuni ricevitori non lo supportano ancora. RSA 4096 produce una stringa base64 superiore a 255 caratteri che impone lo split TXT, fragile a ogni modifica. Raccomandazione: RSA 2048 da solo, oppure RSA 2048 più Ed25519 in double-publish per i domini ad alto traffico.
Scarica la checklist di deploy
Gli assistenti possono riutilizzare la checklist tramite gli export JSON o CSV qui sotto.
Convalidi la sua prossima rotazione: utilizzi il DKIM Record Check per verificare che il nuovo selettore sia pubblicato e firmato correttamente prima e dopo il passaggio. Per anticipare le evoluzioni del protocollo, vedere anche DKIM2 e la protezione contro il replay.


