Howto OpenDKIM
- Installation
- Configuration
- Configurer Postfix pour utiliser OpenDKIM
- Vérifications
- Monitoring
- FAQ
- opendkim: smfi_opensocket() failed
- ADSP (Author Domain Signing Practices)
- Pas d’en-tête DKIM-Signature
- Logs de signature (mode debug)
- Logs de vérification (mode debug)
- Requêtes DNS externes pour ADSP
- Gmail/Google et DKIM
- Problème de header (dkim-filter: no sender header found)
- Regenérer la zone DNS
- body hash did not verify
- Lignes trop longues
- Signer tous les emails avec la même clé ?
- Configuration simplifiée avec une seule clé privée (déconseillé)
- Documentation : http://opendkim.org/docs.html
- opendkim.conf(5) : http://opendkim.org/opendkim.conf.5.html
DKIM (DomainKeys Identified Mail) est une norme qui décrit l’ajout d’une signature cryptographique dans les en-têtes d’un email envoyé.
DKIM signe les mails avec une clé privée stockée sur le serveur. La clé publique est mise à disposition dans un enregistrement DNS TXT et permet au destinataire de vérifier que le domaine contenu dans l’adresse d’expédition appartient bien à l’expéditeur.
La signature se fait à partir à de l’expéditeur contenu dans
l’en-tête (From:
), d’autres en-têtes au choix (sujet, date,
etc.) et du corps du message.
OpenDKIM est logiciel libre
permettant de vérifier et générer des signatures DKIM. Il implémente un
service milter
( mail + filter ) lui permettant notamment
d’être utilisé avec Postfix.
La norme DKIM remplace DomainKey obsolète (utilisée à l’origine par Yahoo).
Installation
# apt install opendkim opendkim-tools
# adduser opendkim ssl-cert
Créer
/etc/systemd/system/opendkim.service.d/override.conf
afin
que le service ne se relance pas trop rapidement :
[Service]
RestartSec=5s
# opendkim -V | head -4
opendkim: OpenDKIM Filter v2.11.0
Compiled with OpenSSL 1.1.0f 25 May 2017
SMFI_VERSION 0x1000001
libmilter version 1.0.1
# systemctl status opendkim
● opendkim.service - OpenDKIM DomainKeys Identified Mail (DKIM) Milter
Loaded: loaded (/lib/systemd/system/opendkim.service; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/opendkim.service.d
└─override.conf
Active: active (running) since Mon 2023-07-03 11:41:31 CEST; 19s ago
Docs: man:opendkim(8)
man:opendkim.conf(5)
man:opendkim-genkey(8)
man:opendkim-genzone(8)
man:opendkim-testadsp(8)
man:opendkim-testkey
http://www.opendkim.org/docs.html
Process: 18085 ExecStart=/usr/sbin/opendkim -x /etc/opendkim.conf (code=exited, status=0/SUCCESS)
Main PID: 18086 (opendkim)
Tasks: 6 (limit: 4915)
CGroup: /system.slice/opendkim.service
└─18086 /usr/sbin/opendkim -x /etc/opendkim.conf
Configuration
La configuration principale se trouve dans le fichier
/etc/opendkim.conf
.
On ajoute la ligne suivante à /etc/opendkim.conf
:
Include /etc/opendkim-evolix.conf
Puis on « injecte » notre configuration via
/etc/opendkim-evolix.conf
:
# cat /etc/opendkim.conf
AuthservID hosting.example.com
UserID opendkim:opendkim
Syslog yes
SyslogSuccess yes
LogWhy yes
UMask 007
InternalHosts /etc/opendkim/TrustedHosts
Mode sv
OversignHeaders From
Socket inet:8891@localhost
PidFile /var/run/opendkim/opendkim.pid
RemoveOldSignatures yes
AlwaysAddARHeader yes
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
Note 1 : Attention, /etc/opendkim.conf
,
/etc/opendkim-evolix.conf
et les fichiers dans
/etc/opendkim/
doivent appartenir à l’utilisateur et au
groupe opendkim
.
Note 2 : Depuis Debian 9, l’unité systemd charge
seulement /etc/opendkim.conf
et non plus
/etc/default/opendkim
.
Note 3 : bien aligner AuthservID avec le « myhostname » de Postfix
Avec notre configuration, on peut gérer une ou plusieurs clés privées via :
/etc/opendkim/KeyTable
: fichier contenant une ou plusieurs clés privées associés à des “sélecteurs”/etc/opendkim/SigningTable
: fichier contenant la table de correspondance entre l’adresseFrom:
et l’éventuelle clé à signer
Note : un sélecteur est une expression qui sert aux
clients à trouver le sous-domaine de l’enregistrement TXT qui contient
la clé publique DKIM du domaine (via
<SELECTOR>._domainkey.example.com
).
Mettre dans le fichier /etc/opendkim/TrustedHosts
la
liste des adresses IP autorisées à ajouter une signature DKIM aux
messages (a priori des serveurs SMTP internes uniquement) :
127.0.0.1
::1
#192.0.2.142
#192.0.2.0/25
Ajuster les droits :
# chown -R opendkim:opendkim /etc/opendkim*
# chmod 640 /etc/opendkim.conf /etc/opendkim/*
# chmod 750 /etc/opendkim/
Enfin, démarrer le démon :
# systemctl start opendkim
$ systemctl status opendkim
Générer une nouvelle clé
Générer une clé pour le domaine
example.com
et le sélecteur foo
avec les
commandes :
# opendkim-genkey -h sha256 -b 4096 -D /etc/ssl/private/ -d example.com -s foo -v
opendkim-genkey: generating private key
opendkim-genkey: private key written to foo.private
opendkim-genkey: extracting public key
opendkim-genkey: DNS TXT record written to foo.txt
# chown opendkim:opendkim /etc/ssl/private/foo.private
# chmod 640 /etc/ssl/private/foo.private
Ajouter la clé privée, que l’on nomme par convention
foo._domainkey.example.com
(mais on pourrait l’appeler
simplement foo
ou bar
) , et son
sélecteur dans /etc/opendkim/KeyTable
:
foo._domainkey.example.com %:foo:/etc/ssl/private/foo.private
Note : on précise %
pour ne pas restreindre la clé à un
domaine et pouvoir l’utiliser sur plusieurs domaines différents (cf
/etc/opendkim/SigningTable
).
On peut récupérer l’enregistrement DNS dans
/etc/ssl/private/foo.txt
(généré à la création de la clé
privée), et l’ajouter dans la zone DNS du domaine en question :
foo._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; "
"p=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtdnoCyrwNyCAttQz0VaJq3cheWtki8KTfCwPu+QDcyv8IHLpQGK2UsEw03epEjTI/ijdyyVsElDPoqsCZ4+R3H5I41Vj8xcGLvqIaG3mbgOhcxuD+eEPR1K+JbSptwMiP/oja7VFyftQtx5XkQh8oj458WR/EE++SzjOGXOVmFYzf+LnNXJ/Rc0avAUPcTF1NmoU8IP52aKTvw"
"nrbPFhIPkUyIR1/5k+5h4ZJqY+2h+JqDuol0E73Yl79rsF5ycjwLtBCPsz80jzCpOF5YHkDx0CYPyTKoIA3eZlgOVSJPmDYUWCrj/9k2bL/nSL5EJoB/X/kQcLRTy83dqf+gzWd850yP9vpUQQ2d+Z1hdlAFvzVMboSNz12+au7kAglXmN47l9Z8igxVWJfl7BEsegQF8gYPB4yepSW3DtfxBC5zCjLYYN1xXabf3wZfeCF6yOoQk1C2yN"
"ThvBa4NyQDWizZGs4t9eHTR8QHMzJogPQQvyS45ILN1HHeikIQZP/lormmFQzq9X8sDGt4Edy8A3OMLjHom81tP6zxb4I8Pq0V4bEt4m4KA+K89A+b9cTD2Xr/wbqgQ1nwTcnEfGgBxbc3iRKkUnwhjeIocsxmwHqmDIVV8HKB5egUg8US/eo9al8w4JYEdzx9tETW/5dQOeLTMVw2N0/A7M9zVbBQEyuaMCAwEAAQ==" ) ; ----- DKIM key foo for example.com
Le fichier /etc/opendkim/SigningTable
indique le
nom de la clé privée (défini dans /etc/opendkim/KeyTable
) à
utiliser pour signer un message en fonction de son entête
From:
:
*@example.com foo._domainkey.example.com
Ne pas oublier d’ajuster les droits lors de la création :
# chown -R opendkim:opendkim /etc/opendkim/KeyTable
# chmod 640 /etc/opendkim.conf /etc/opendkim/KeyTable
S’il y a plusieurs domaines, on peut spécifier la même clé ou une clé
différente d’après ce qui est déclaré dans
/etc/opendkim/KeyTable
:
*@example.com foo._domainkey.example.com
*@example.org foo._domainkey.example.com
*@example.net bar._domainkey.example.org
Les lignes sont traitées dans l’ordre, seul le premier match est
utilisé, sauf si MultipleSignatures
est activé.
Configurer Postfix pour utiliser OpenDKIM
Pour configurer avec Postfix on ajoute
simplement les instructions suivantes dans le fichier
/etc/postfix/main.cf
:
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = inet:127.0.0.1:8891
#milter_default_action=accept
# Pour accélérer les signatures, pas d'attente pour contacter le milter
in_flow_delay = 0s
Cela entraînera l’ajout d’un en-tête DKIM-Signature:
à
tous les messages qui correspondent à la configuration d’OpenDKIM.
Authentication-Results (AR)
Si vous utilisez OpenDKIM en mode “verifier” (avec l’option
Mode sv
ou Mode v
dans la configuration
d’OpenDKIM) cela entraînera une vérification des signatures DKIM des
emails reçus, et l’ajout d’un en-tête
Authentication-Results
(AR) :
Authentication-Results: antispam.example.com; dkim=pass
(2048-bit key; unprotected) header.d=example.com header.i=john@example.com header.b="AAcPZ8gu";
dkim-adsp=pass; dkim-atps=neutral
En cas d’échec, par exemple la clé n’est pas bien mis dans la zone DNS, on aura quelque chose du type :
Authentication-Results: antispam.example.com; dkim=permerror (0-bit key) …
Et que l’on force l’option AlwaysAddARHeader
si il n’y a
pas de signature DKIM cela donnera :
Authentication-Results: antispam.example.com; dkim=none; dkim-atps=neutral
Mettre le retour d’Amavis en no_milters
Attention, si vous utilisez aussi Amavis,
vérifiez bien que /etc/postfix/master.cf
a bien l’option
no_milters
dans son option
-o receive_override_options
pour le process SMTPD de retour
d’Amavis (en général 127.0.0.1:10025
) sinon OpenDKIM
pourrait signer aussi les emails entrants au retour d’Amavis (cela
dépend évidemment de votre SigningTable
) :
opendkim[18086]: 8A836229A8: mail-pl1-f202.google.com [209.85.214.202] not internal
opendkim[18086]: 8A836229A8: not authenticated
opendkim[18086]: 2760F22B59: DKIM-Signature field added (s=dkim-foo, d=google.com)
Vérifications
Vérifier les clés et la configuration DNS
On peut vérifier que la configuration est correcte, notamment l’enregistrement DNS ainsi :
# opendkim-testkey -d example.com -s foo -k /etc/ssl/private/foo.private -vv
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: key loaded from /etc/ssl/private/foo.private
opendkim-testkey: checking key 'foo._domainkey.example.com'
opendkim-testkey: key secure
Vérifier la signature DKIM d’un mail
A partir du serveur, il faut s’envoyer un email de test (avec un expéditeur d’en-tête correct). Par exemple, en ligne de commande :
$ telnet 127.0.0.1 25
HELO example.com
MAIL FROM: <noreply@example.com>
RCPT TO: <foo@example.org>
DATA
From: <noreply@example.com>
To: Foo <foo@example.org>
Subject: test DKIM
Ceci est un test
.
A la réception, la source de l’email devrait contenir un en-tête supplémentaire du type :
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=foo;
t=1541094902; bh=xj6JF8HXzDkYeJ72cJNmx7FnTp5CeDo6y+MwRwIeNC4=;
h=Date:From:To:Subject:From;
b=lJ8oU+KkUBWEWVl/HpztFx5Hdv2rhqLP03JfJ1yqp3+TR3aZX+uOCI4MKqvonYzXM
kHl4YYsYT7fSnuSaF48feGbGQ1AauGKd2x9UKcBEBQq2cGLG7ahfXph/SF5eh7/psL
dXal6gCw6416bJQMBa9sb+zSA/9Avy3zQ0jGCALw=
Dans Thunderbird, le plugin DKIM verifier
permet de
vérifier les en-têtes DKIM des mails reçus.
Sinon, si vous avez accès à un email Gmail ou Yahoo, vous pouvez lui
envoyer un email. En affichant le message original, vous pourrez
vérifier la présence de DKIM-Signature:
. Cela vous
indiquera si la signature est correcte et acceptée.
Vérifier via des services externes
Vérifier (notamment) son enregistrement DNS pour DKIM : https://toolbox.googleapps.com/apps/checkmx/ (2 premiers résultats à ignorer).
Vérifier en envoyant un email vers un service externe : https://dkimcore.org/tools/ ou http://dkimvalidator.com/ ou https://www.mail-tester.com/.
Monitoring
Il est important de s’assurer que le démon opendkim tourne en permanence.
Nagios
Voici un check basique pour vérifier que le port TCP d’opendkim répond bien :
$ /usr/lib/nagios/plugins/check_tcp -H 127.0.0.1 -p 8891
log2mail
Pour être alerté en cas de *warning: connect to Milter service inet:8891: Connection refused on ajoute la configuration suivante au logiciel log2mail :
file = /var/log/syslog
pattern = "warning: connect to Milter service inet:8891: Connection refused"
mailto = alert@example.com
FAQ
opendkim: smfi_opensocket() failed
Si vous obtenez le message suivant au démarrage :
Starting OpenDKIM Milter: opendkim: smfi_opensocket() failed
C’est que la socket réseau est déjà occupée !
ADSP (Author Domain Signing Practices)
**ADSP est désormais obsolète, et remplacé par la spécification DMARC
ADSP est une extension à DKIM permettant d’indiquer le traitement à effectuer en cas de signature DKIM invalide ou absente.
Si l’on est sûr que tous les mails émis avec le nom de domaine utilisé sont bien signés avec DKIM, on peut l’indiquer via l’enregistrement DNS suivant, ce qui provoquera la pénalisation des emails sans signature :
_adsp._domainkey IN TXT "dkim=all"
On peut vérifier que l’enregistrement ADSP est bien pris en compte avec la commande suivante :
# opendkim-testadsp example.com
Pas d’en-tête DKIM-Signature
Si vous ne constatez pas l’ajout de la signature DKIM, vérifiez votre
configuration, vérifiez que vous utilisez bien un champ
From:
correct et correspondant à un domaine à signer. Si
besoin activé le « mode debug », cf ci-dessous.
Logs de signature (mode debug)
Il peut aussi être intéressant d’activer les options suivantes dans
/etc/opendkim.conf
pour avoir davantage de logs :
Syslog yes
SyslogSuccess yes
LogWhy yes
On verra ainsi des logs dans /var/log/mail.log
du type
:
opendkim[18086]: E4DB722DFA: mail-ej1-f53.google.com [209.85.218.53] not internal
opendkim[18086]: E4DB722DFA: not authenticated
opendkim[18086]: 18F02230B9: DKIM-Signature field added (s=dkim-foo, d=example.com)
Logs de vérification (mode debug)
Il peut être intéressant d’activer l’option suivante /etc/opendkim.conf` pour avoir des logs pour chaque signature vérifiée par opendkim :
LogResults true
Requêtes DNS externes pour ADSP
Attention, par défaut OpenDKIM effectue ses vérifications ADSP en faisant de multiples requêtes DNS sans utiliser le resolver local, ce qui qui peut provoquer des ralentissements notamment si cela n’est pas autorisé au niveau firewall. Nous conseillons de désactiver ces vérifications qui sont obsolètes :
DisableADSP true
Gmail/Google et DKIM
Informations de Gmail/Google à propos de DKIM : https://support.google.com/a/answer/174124?hl=fr.
Problème de header (dkim-filter: no sender header found)
Avec dkim-filter, en Debian 7, il se peux que, suite a une règle de ce type dans postfix :
/^received:/ IGNORE
cela casse dkim-filter, car il ne vois pas si le sender est correct dans le header du mail, et donc il ne sais pas si c’est un domaine qu’il doit signé ou pas.
Regenérer la zone DNS
Lorsqu’une clé a déjà été générée mais que le fichier contenant la zone DNS n’est plus disponible, il est possible de la régénérer avec la commande suivante :
opendkim-genzone -F -d example.com /etc/opendkim/KeyTable
body hash did not verify
Cette erreur vient du fait que le payload du message a été modifié par un serveur SMTP entre le départ et l’arrivée (inclus). Cela peut venir de lignes trop longues (cf plus bas).
Lignes trop longues
D’après https://www.rfc-editor.org/rfc/rfc2822#section-2.1.1 les lignes d’un email ne doivent pas être trop longues sinon elles peuvent se faire découper par un serveur SMTP entre le départ et l’arrivée (inclus)… ce qui changer le payload du message car il aura notamment des sauts de ligne en plus.. et donc le body hash de la signature DKIM ne sera plus valide.
Signer tous les emails avec la même clé ?
Pour signer tous les domaines avec un même clé, on peut mettre un
wildcard dans /etc/opendkim/SigningTable
:
* key1
Mais c’est déconseillé car tous les emails car OpenDKIM tenteraient de traiter tous les domaines, et cela peut poser des problèmes avec des emails tordus (par exemple OpenDKIM plante quand on trouve une espace sans chasse dans le nom de domaine).
Configuration simplifiée avec une seule clé privée (déconseillé)
Il est aussi possible d’avoir une configuration utilisant une seule clé privée mais c’est déconseillé :
Domain
: fichier contenant la liste des domaines acceptés.KeyFile
: clé privée (unique).Selector
: sélecteur DNS (unique).- Pas de
KeyTable
ni deSigningTable
.
Générer une paire de clés avec le sélecteur
dkim-<SERVER_NAME>
(par exemple) dans le répertoire
/etc/opendkim/keys/
:
# mkdir /etc/opendkim/keys
# sudo -u opendkim opendkim-genkey -h sha256 -b 4096 -D /etc/opendkim/keys/ -s dkim-<SERVER_NAME>
Cela met la clé privée dans
/etc/opendkim/keys/dkim-<SERVER_NAME>.private
, et
l’enregistrement DNS TXT contenant la clé publique dans
/etc/opendkim/keys/dkim-<SERVER_NAME>.txt
Créer les whitelistes :
# vim /etc/opendkim/domains_whitelist
+ # Indiquez ici les domaines pour lesquels OpenDKIM va signer les mails.
# vim /etc/opendkim/hosts_whitelist
+ # Indiquez ici les IPs/sous-réseaux des serveurs SMTP internes pour lesquels OpenDKIM va signer les mails.
+ 127.0.0.1
+ ::1
Ajuster la configuration générale dans
/etc/opendkim.conf
:
UserID opendkim:opendkim
Syslog yes
SyslogSuccess yes
LogWhy yes
UMask 007
Mode sv
OversignHeaders From
Socket inet:8891@localhost
PidFile /var/run/opendkim/opendkim.pid
RemoveOldSignatures yes
# Liste les IPs des serveurs SMTP internes pour lesquels OpenDKIM va signer les mails
InternalHosts refile:/etc/opendkim/hosts_whitelist
ExternalIgnoreList refile:/etc/opendkim/hosts_whitelist
# Clé privée (générée avec "sudo -u opendkim opendkim-genkey -h sha256 -b 4096 -D /etc/opendkim/keys/ -s dkim-<SERVER_NAME>")
KeyFile /etc/opendkim/keys/dkim-<SERVER_NAME>.private
# Utilisé dans l'enregistrement DNS utilisé pour récupérer la clé publique ($selector._domainkey.$domain)
Selector dkim-<SERVER_NAME>
# Liste des domaines pour lesquels OpenDKIM va signer les mails (accepte les regex)
Domain refile:/etc/opendkim/domains_whitelist
Pour ajouter un domaine :
Ajouter le texte contenu dans le fichier
/etc/opendkim/keys/dkim-<SERVER_NAME>.txt
aux
enregistrements DNS du domaine. Cela va rendre la clé publique
accessible via un enregistrement TXT du sous-domaine
dkim-<SERVER_NAME>._domainkey.$domain
.
On peut vérifier l’enregistrement DNS avec :
$ host -t TXT dkim-<SERVER_NAME>._domainkey.$domain
Puis, ajouter le domaine à la liste
/etc/opendkim/domains_whitelist
et redémarrer le service
:
# vim /etc/opendkim/domains_whitelist
+ $domain
# systemctl restart opendkim
# systemctl status opendkim