Table des matières

DKIM

«DomainKeys Identified Mail» permet au serveur SMTP de signer les messages sortants avec une clé privée. La clé publique correspondante est publiée sur le serveur DNS du domaine. Ainsi, le serveur destinataire pourra vérifier l'authenticité du domaine d’émetteur et celle du message lui-même.

Le principe (en gros)

DKIM de fait que signer et contrôler la signature. C'est à un autre service de décider de la conclusion à en tirer, smapassassin par exemple.

Installation

Pour rappel, l'exposé s'appuie sur une distribution Dabian «Trixie», encore à l'état de «testing» au moment où ces lignes sont écrites.

Nous partons d'un serveur SMTP Postfix fonctionnel, appartenant au domaine nain-t.net, référencé comme MX sur le serveur DNS sous le nom smtp.nain-t.net, avec une gestion des boîtes aux lettres @nain-t.net confiée à Dovecot. Les utilisateurs référencés peuvent utiliser smtp.nain-t.net pour poster des e-mails via le système submission1).

apt install opendkim opendkim-tools

Création des clés

L'outil opendkim-genkey est là pour ça:

sudo -u opendkim opendkim-genkey --directory=/etc/dkimkeys --domain=nain-t.net --selector=2025

Crée dans le répertoire /etc/dkimkeys les clés 2025.txt et 2025.private. Il est d'usage d'attribuer au «selector» l'année de création de la clé.

ls -l /etc/dkimkeys
total 12
-rw------- 1 opendkim opendkim 1704 15 mai   10:28 2025.private
-rw------- 1 opendkim opendkim  500 15 mai   10:28 2025.txt
-rw-r--r-- 1 root     root      664 11 sept.  2024 README.PrivateKeys

Lisons tout de même le contenu du fichier README.PrivateKeys:

This directory is for storing private keys associated with DKIM signing with
opendkim.

Here is advice from upstream  

(4) Store the private key in a safe place.  We generally use a path like
    /var/db/dkim/SELECTOR.key.pem (where "SELECTOR" is the name you chose).
    The /var/db/dkim directory and the associated .pem file should be owned by
    the user that will be executing the filter (preferably not the
    superuser) and be mode 0700 and 0600 respectively.

In Debian, we use /etc/dkimkeys by default and the directory permissions and
ownership are set correctly.  Ensure that the private key is owned by the
opendkim user and the permissions are 0600.
Tout à l'air correct.

Pour ce qui est de l'installation de la clé publique dans la zone DNS du domaine, tout déprendra des outils proposés par le «registar».

Pour vérifier que la clé est bien accessible, la commande dig s'utilise de la façon suivante:

dig TXT <selector>._domainkey.<domain.tld> +short 

(selector et domain.tld à remplacer, bien entendu).

Configuration d'openDKIM

La version proposée dans Trixie dispose d'une configuration assez différente des versions précédentes. Attention en cas de mise à jour!

La configuration est entièrement effectuée dans /etc/opendkim.conf, dont une version minimale, à modifier légèrement est créée lors de l'installation. Elles suffira à nos besoins. Il n'y a plus de /etc/default/opendkim qui est désormais obsolète.

Cet exemple s'applique à une configuration n'ayant à gérer qu'un seul domaine.

Précaution:

cp /etc/opendkim.conf /etc/opendkim.conf.dpkg-dist

Et commençons par une configuration basique:

# This is a basic configuration for signing and verifying. It can easily be
# adapted to suit a basic installation. See opendkim.conf(5) and
# /usr/share/doc/opendkim/examples/opendkim.conf.sample for complete
# documentation of available configuration parameters.

Syslog			yes
SyslogSuccess		yes
#LogWhy			no

# Common signing and verification parameters. In Debian, the "From" header is
# oversigned, because it is often the identity key used by reputation systems
# and thus somewhat security sensitive.
Canonicalization	relaxed/simple
#Mode			sv
#SubDomains		no
OversignHeaders		From

# Signing domain, selector, and key (required). For example, perform signing
# for domain "example.com" with selector "2020" (2020._domainkey.example.com),
# using the private key stored in /etc/dkimkeys/example.private. More granular
# setup options can be found in /usr/share/doc/opendkim/README.opendkim.
Domain			nain-t.net
Selector		2025
KeyFile		/etc/dkimkeys/2025.private

# In Debian, opendkim runs as user "opendkim". A umask of 007 is required when
# using a local socket with MTAs that access the socket as a non-privileged
# user (for example, Postfix). You may need to add user "postfix" to group
# "opendkim" in that case.
UserID			opendkim
UMask			007

# Socket for the MTA connection (required). If the MTA is inside a chroot jail,
# it must be ensured that the socket is accessible. In Debian, Postfix runs in
# a chroot in /var/spool/postfix, therefore a Unix socket would have to be
# configured as shown on the last line below.
#Socket			local:/run/opendkim/opendkim.sock
#Socket			inet:8891@localhost
#Socket			inet:8891
Socket			local:/var/spool/postfix/opendkim/opendkim.sock

PidFile			/run/opendkim/opendkim.pid

# Hosts for which to sign rather than verify, default is 127.0.0.1. See the
# OPERATION section of opendkim(8) for more information.
#InternalHosts		192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12

# The trust anchor enables DNSSEC. In Debian, the trust anchor file is provided
# by the package dns-root-data.
TrustAnchorFile		/usr/share/dns/root.key
#Nameservers		127.0.0.1

La «canonicalisation» est une méthode de transformation d'un élément dans sa forme la plus simple, la plus conforme à la norme mais toute transformation, même mineure d'un texte change complètement son hachage. Il se trouve que les MTA par lesquels transite un message peuvent en modifier le contenu, principalement dans l'en-tête. Afin d'éviter des rejets intempestifs, la façon de «canonicaliser» par défaut sera plus ou moins permissive: «relaxed» (détendue) pour les en-têtes, «simple» (rigoureuse) pour le corps du message.

Le démon «rsyslog» ne sera probablement plus installé par défaut, il ne l'est pas à ce jour (15/05/2025) dans Trixie «testing», tous les journaux étant désormais gérés par l'usine «systemd». Cependant, le paramètre peut rester actif sans créé de trouble.

Le répertoire /var/spool/postfix/opendkim doit être créé manuellement:

mkdir /var/spool/postfix/opendkim
chown opendkim:opendkim /var/spool/postfix/opendkim

Après avoir redémarré le service:

systemctl restart opendkim

et avoir vérifié qu'il est bien en service:

systemctl status opendkim

Il est également possible de vérifier ça en allant voir si le socket UNIX /var/spool/postfix/opendkim.sock existe, avec les droits d'accès convenables:

ls -l /var/spool/postfix/opendkim/

srwxrwx--- 1 opendkim opendkim 0 15 mai   11:23 opendkim.sock

Il faudra vérifier que tout est fonctionnel avec la commande:

dig <le_descripteur_de_votre_clef>._<votre_domaine> txt

la sortie doit correspondre à la clé publique.

Configuration de Postfix

OpenDKIM fournissant un milter, il suffit de rajouter dans /etc/postfix/main.cf à la ligne sptmd_milters le socket d'opendkim: unix:opendkim/opendkim.sock. (N'oublions pas que dans l'installation Debian, Postfix est «chrooté» (disons «enfermé» en bon français), dans /var/spool/postfix.

Pour l'instant, le paragraphe de configuration des milters ressemble à ceci:

#
# Configuration des milters
#
milter_protocol = 6
milter_default_action = accept
smtpd_milters = unix:/spamass/spamass.sock unix:opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters

Le résultat

Voici ce que l'on trouve dans l'en-tête d'un message posté depuis «free.fr»

Return-Path: <untel@free.fr>
...
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=free.fr;
	s=smtp-20201208; t=1747666570;
	bh=f5mczPvK5SGFpzCU/vdejJWSD+pSXCw5mb5i3FGoxfc=;
	h=Date:To:From:Subject:From;
	b=c6OS+7tcZsKsc74z7JZnfWIXUHjlGI0UGeQJxjMTAF1zgSObruzVX5RF36fcv75r6
	 O6+tmQPx1OIQ/PgZprvIi5l4l0P0Hze+5izlHYHLDYQoJ7TUWKYO09dSeqNER32Xse
	 HY7tM2rYdqG4LYiXglgcO3CY5+4n9KnmtbM9vm3uIbWfkXFni0pObCrfROtEdeHV+o
	 9ceIofdA6CfDd+41fNOR/rlfD6/tQbQPKH0pIz9D+BgOQeFv0xiIQo1p/mgt7tXFpL
	 ni3oH8dQ2j1zgLdYS5/Xo6+UEzc7tVtJ8ZUNhD6zd4F0cJHWYVt7PqgRp/ZJXbcZ52
	 +2i6PVvbm5U2Q==

La signature DKIM, en plus de s'appuyer sur SPF pour «assurer» que le MTA utilisé pour l'envoi est bien validé pour le domaine de l'émetteur, signe une partie de l'en-tête et le corps du message, pour en valider l'authenticité à la réception.

1)
Envoi via le port 587 après identification de l'utilisateur par SASL Auth