Dans ce septième article dédié à Postfix et Dovecot, nous allons aborder une série de technologies devenues incontournables sur un serveur mail de production. Notre serveur est désormais opérationnel, et nous pouvons envoyer et recevoir des e-mails avec un client mail comme Mozilla Thunderbird. Or, dans l’état actuel des choses, nous risquons d’avoir quelques mauvaises surprises, notamment avec tous les destinataires qui ont un compte mail chez Google, Yahoo, Microsoft ou Apple. Tous nos e-mails envoyés vers l’un de ces comptes finissent dans le dossier Spam du destinataire ou nous reviennent dans la figure, s’ils ne sont pas carrément expédiés au nirvana numérique.
Le concentré d’acronymes quelque peu barbares dans le titre de cet article résume l’ensemble des techniques nécessaires pour ne pas passer pour un spammeur auprès des usual suspects parmi les fournisseurs de courrier électronique :
- Sender Policy Framework (SPF) : un enregistrement DNS qui indique les hôtes autorisés à envoyer des e-mails pour un certain domaine.
- DomainKeys Identified Mail (DKIM) : l’authentification par clé cryptographique du nom de domaine de l’expéditeur d’un e-mail, avec la clé publique stockée sur un serveur DNS.
- Domain-based Message Authentication, Reporting & Conformance (DMARC) : un enregistrement DNS qui indique publiquement que votre serveur mail supporte SPF et DKIM.
Sender Policy Framework
La mise en place du Sender Policy Framework (SPF) est d’une simplicité déconcertante. Il suffit d’ajouter un enregistrement TXT
dans la configuration de votre serveur DNS, en indiquant l’hôte ou l’adresse IP du serveur autorisé à envoyer des e-mails pour le domaine.
Voici un exemple de configuration sur mon serveur de test :
; /var/named/zone.slackbox.fr $TTL 86400 $ORIGIN slackbox.fr. @ IN SOA ns.slackbox.fr. hostmaster.slackbox.fr. ( 2024011801 ; sn 10800 ; refresh (3 heures) 600 ; retry (10 minutes) 1814400 ; expiry (3 semaines) 10800 ) ; minimum (3 heures) IN NS ns.slackbox.fr. IN NS nssec.online.net. IN MX 10 mail.slackbox.fr. slackbox.fr. A 51.158.146.161 ns IN A 51.158.146.161 mail IN A 51.158.146.161 @ IN TXT "v=spf1 mx ~all" www CNAME slackbox.fr. blog CNAME slackbox.fr. gestion CNAME slackbox.fr. cloud CNAME slackbox.fr.
Quelques remarques sur la syntaxe utilisée :
- La chaîne de caractères doit impérativement commencer par
v=spf1
. - Ensuite, on indique les adresses IP des serveurs autorisés à envoyer des e-mails pour le domaine. Dans le cas présent, je dispose déjà d’un enregistrement
MX
. - Mon enregistrement aurait pu être noté
v=spf1 ip4:51.158.146.161 ~all
. Différents chemins mènent à Saint-Bauzille-de-Putois. - L’enregistrement se termine par
~all
, ce qui signifie que les autres adresses IP que celle indiquée ne doivent pas envoyer d’e-mails pour le domaine. - La directive finale
-all
interdit explicitement l’envoi depuis une machine autre que ce qui est spécifié dans l’enregistrement. Évitez de l’utiliser, sous peine d’avoir des problèmes avec les messages relayés.
J’effectue une série de tests depuis une autre machine :
$ host -t TXT slackbox.fr slackbox.fr descriptive text "v=spf1 mx ~all" $ host -t MX slackbox.fr slackbox.fr mail is handled by 10 mail.slackbox.fr. $ host -t A mail.slackbox.fr mail.slackbox.fr has address 51.158.146.161
En langage tam-tam, la configuration ci-dessus signifie que seuls les e-mails en provenance de l’hôte mail.slackbox.fr
(adresse IP 51.158.146.161
) sont considérés comme valides.
Rendez-vous sur la page SPF Record Checker pour tester la validité de votre enregistrement SPF :
DomainKeys Identified Mail
Passons aux choses sérieuses avec la mise en oeuvre de DKIM (DomainKeys Identified Mail). Pour commencer, essayons de voir en grandes lignes le principe de fonctionnement de DKIM :
- Lorsqu’un serveur mail configuré avec DKIM envoie un e-mail, il le signe à l’aide d’une clé privée stockée sur le serveur lui-même.
- Le serveur mail du destinataire peut lire l’enregistrement DNS
TXT
de l’expéditeur qui contient la clé publique, ce qui permet de vérifier le message et la signature cryptographique. - DKIM permet ainsi de vérifier si l’e-mail provient effectivement de l’expéditeur indiqué, puisque seul le serveur mail légitime dispose de la clé privée qui permet de signer les messages.
OpenDKIM est une implémentation Open Source de DKIM, capable de signer les e-mails sortants et de vérifier la signature des e-mails entrants.
Sous Red Hat Enterprise Linux et Rocky Linux, OpenDKIM est fourni par le dépôt EPEL :
# dnf install -y opendkim opendkim-tools
OpenDKIM se configure par le biais du fichier /etc/opendkim.conf
. Avant de modifier quoi que ce soit, on va effectuer une copie de sauvegarde de ce fichier :
# cd /etc/ # cp -v opendkim.conf opendkim.conf.orig 'opendkim.conf' -> 'opendkim.conf.orig'
Éditer /etc/opendkim.conf
en adaptant les directives suivantes :
## CONFIGURATION OPTIONS ## Specifies the path to the process ID file. PidFile /run/opendkim/opendkim.pid ## Selects operating modes. Valid modes are s (sign) and v (verify). Default is v. ## Must be changed to s (sign only) or sv (sign and verify) in order to sign outgoing ## messages. Mode sv ... ## Create a socket through which your MTA can communicate. Socket inet:8891@localhost # Socket local:/run/opendkim/opendkim.sock ... ## Gives the location of a private key to be used for signing ALL messages. This ## directive is ignored if KeyTable is enabled. # KeyFile /etc/opendkim/keys/default.private ## Gives the location of a file mapping key names to signing keys. In simple terms, ## this tells OpenDKIM where to find your keys. If present, overrides any KeyFile ## directive in the configuration file. Requires SigningTable be enabled. KeyTable /etc/opendkim/KeyTable ## Defines a table used to select one or more signatures to apply to a message based ## on the address found in the From: header field. In simple terms, this tells ## OpenDKIM how to use your keys. Requires KeyTable be enabled. SigningTable refile:/etc/opendkim/SigningTable ## Identifies a set of "external" hosts that may send mail through the server as one ## of the signing domains without credentials as such. ExternalIgnoreList refile:/etc/opendkim/TrustedHosts ## Identifies a set "internal" hosts whose mail should be signed rather than verified. InternalHosts refile:/etc/opendkim/TrustedHosts ...
Ensuite, éditer /etc/opendkim/SigningTable
en spécifiant une clé pour chacun des domaines hébergés :
# /etc/opendkim/SigningTable
*@slackbox.fr 01._domainkey.slackbox.fr
*@unixbox.fr 01._domainkey.unixbox.fr
En règle générale, les articles de blog et autres tutoriels sur OpenDKIM estampillent les clés de la date en cours, comme 20240118._domainkey.slackbox.fr
. Ce n’est là qu’une convention, et vous êtes libres de vous y conformer ou non.
Puis, éditer /etc/opendkim/KeyTable
en adaptant la syntaxe utilisée :
# /etc/opendkim/KeyTable
01._domainkey.slackbox.fr slackbox.fr:01:/etc/opendkim/keys/slackbox.fr/01.private
01._domainkey.unixbox.fr unixbox.fr:01:/etc/opendkim/keys/unixbox.fr/01.private
Enfin, éditer /etc/opendkim/TrustedHosts
, qui contient la liste des hôtes pour lesquels on se passera d’une signature DKIM.
# /etc/opendkim/TrustedHosts
127.0.0.1
*.slackbox.fr
*.unixbox.fr
Dans l’exemple ci-dessus, j’ai supprimé l’hôte préconfiguré ::1
étant donné que j’ai désactivé l’IPv6 sur mon serveur de test.
À partir de là, on pourra générer les clés, une par domaine :
# mkdir -v /etc/opendkim/keys/{slackbox.fr,unixbox.fr} mkdir: created directory '/etc/opendkim/keys/slackbox.fr' mkdir: created directory '/etc/opendkim/keys/unixbox.fr' # opendkim-genkey -b 2048 -d slackbox.fr \ -D /etc/opendkim/keys/slackbox.fr -s 01 -v opendkim-genkey: generating private key opendkim-genkey: private key written to 01.private opendkim-genkey: extracting public key opendkim-genkey: DNS TXT record written to 01.txt # opendkim-genkey -b 2048 -d unixbox.fr \ -D /etc/opendkim/keys/unixbox.fr -s 01 -v opendkim-genkey: generating private key opendkim-genkey: private key written to 01.private opendkim-genkey: extracting public key opendkim-genkey: DNS TXT record written to 01.txt # chown -R opendkim:opendkim /etc/opendkim/keys/
Quelques remarques sur les commandes et les options utilisées.
- La commande
opendkim-genkey
génère une paire de clés privée (xy.private
) et publique (xy.txt
). - L’option
-d
spécifie le domaine pour lequel la clé est valable. - L’option
-b 2048
indique la génération d’une clé de 2048 bits. Dans la configuration par défaut,opendkim-genkey
génère une clé de 1024 bits, ce qui est généralement considéré comme insuffisant. D’un autre côté, l’infrastructure des serveurs mail actuels ne supporte pas une clé d’une taille supérieure à 2048 bits. - L’option
-D
spécifie le répertoire (directory) qui contiendra la paire de clés. - L’option
-s
définit un sélecteur pour identifier la clé. Si vous voulez utiliser quelque chose de plus parlant que01
, vous pouvez mettre la date sous la forme20240118
. - Enfin, l’option
-v
(verbose) demande àopendkim-genkey
de nous informer un minimum sur ce qui se passe sous le capot.
À présent, je peux afficher la clé publique pour mon premier domaine slackbox.fr
:
# cat /etc/opendkim/keys/slackbox.fr/01.txt
01._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtIDc0nRKax
M4ZTk3JvYIO7z/l2K3moKYatah0ngagAxNt47ahkE+wJU0y3+MILl+Mkkhu
u79nhay6s83k7P6CkZyPS9IOLxXp36FOJqyN0xYDaYADRJIK22ykjt59M4O
X/zWuHtpkpoZPJ53I5T0S/JQmbkubKnUSfSOLF70gfLisPKHUR2BseQi45k
oEuCgruc6pqo1qn8Du"
"ypufBef/pVS+2wmEnm8yUTgVkuP+2M8UPLjJJTISrDOZUiRb8opqmiig
akBp1pJz1yk4UlBz+qqp0jxqhNHvfBHzsuzmr6ol0eLAC1IFQvEa0ZM3b5g
P+BzuBOKclFKFHAO1QIDAQAB" ) ; ----- DKIM key 01 for slackbox.fr
J’effectue un copier/coller du résultat vers le fichier zone /var/named/zone.slackbox.fr
de mon serveur DNS en essayant au mieux de garder le résultat lisible :
Je fais de même avec la clé publique de mon domaine unixbox.fr
:
# cat /etc/opendkim/keys/unixbox.fr/01.txt
Là aussi, j’effectue un copier/coller du résultat dans le fichier zone correspondant de mon serveur DNS, en l’occurrence /var/named/zone.unixbox.fr
.
Lorsque vous modifiez la configuration de votre zone DNS, n’oubliez pas d’incrémenter le numéro de série de la zone et de recharger la configuration de BIND. Je le mentionne ici parce que c’est une erreur aussi fréquente que banale.
À partir de là, je peux déjà tester mes clés DKIM :
# opendkim-testkey -d slackbox.fr -s 01 # opendkim-testkey -d unixbox.fr -s 01
Puisque tout est OK, j’active et je démarre le service OpenDKIM :
# systemctl enable opendkim --now
Il ne nous reste plus qu’à connecter Postfix et OpenDKIM. Pour ce faire, nous allons ajouter la stance suivante à /etc/postfix/main.cf
:
# SMTP restrictions smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_rhsbl_helo dbl.spamhaus.org, reject_rhsbl_reverse_client dbl.spamhaus.org, reject_rhsbl_sender dbl.spamhaus.org, reject_rbl_client zen.spamhaus.org, reject_unauth_destination # Milter applications milter_default_action = accept milter_protocol = 6 smtpd_milters = inet:127.0.0.1:8891 non_smtpd_milters = $smtpd_milters
Là aussi, quelques remarques sur les directives utilisées.
- Le mot milter est une contraction de mail filter.
milter_default_action = accept
signifie que Postfix doit accepter les e-mails même si le filtre en question est mal configuré ou autrement défectueux.smtpd_milters
concerne les e-mails envoyés via le protocole SMTP, alors quenon_smtpd_milters
désigne les messages locaux.
Il nous reste à régler un problème de permissions en ajoutant l’utilisateur système postfix
au groupe système opendkim
:
# usermod -aG opendkim postfix
Redémarrer Postfix pour prendre en compte les modifications :
# systemctl restart postfix
Pour tester le bon fonctionnement de notre installation, nous avons le choix entre plusieurs possibilités. La manière la plus simple consiste à envoyer un e-mail à l’adresse check-auth@verifier.port25.com
, qui nous renvoie un rapport détaillé au bout de quelques secondes :
DMARC
Une fois que SPF et DKIM fonctionnent correctement sur le serveur, il ne reste plus qu’à activer DMARC (Domain-based Message Authentication, Reporting & Conformance). La procédure est aussi simple que pour SPF dans la mesure où il suffit d’ajouter un simple enregistrement TXT
à votre serveur DNS. Cet enregistrement annonce publiquement que votre serveur mail supporte SPF et DKIM et indique la procédure à suivre avec les e-mails qui contiennent votre nom d’hôte et votre adresse d’expéditeur, mais qui n’ont pas été envoyés par votre serveur et/ou dont la signature DKIM est incorrecte.
Jetons un œil sur la configuration DMARC des quatre fournisseurs de malbouffe logicielle messagerie que j’ai cités au tout début de cet article :
$ host -t TXT _dmarc.hotmail.com _dmarc.hotmail.com descriptive text "v=DMARC1; p=none; rua=mailto:rua@dmarc.microsoft;ruf=mailto:ruf@dmarc.microsoft;fo=1:s:d" $ host -t TXT _dmarc.apple.com _dmarc.apple.com descriptive text "v=DMARC1; p=quarantine; sp=reject; rua=mailto:d@rua.agari.com; ruf=mailto:d@ruf.agari.com;" $ host -t TXT _dmarc.gmail.com _dmarc.gmail.com descriptive text "v=DMARC1; p=none; sp=quarantine; rua=mailto:mailauth-reports@google.com" $ host -t TXT _dmarc.yahoo.com _dmarc.yahoo.com descriptive text "v=DMARC1; p=reject; pct=100; rua=mailto:d@rua.agari.com; ruf=mailto:d@ruf.agari.com;"
Avant même de jeter un oeil sur la documentation de DMARC, un peu de linguistique intuitive nous permet de comprendre les bases de la syntaxe ainsi que les différentes politiques des fournisseurs :
- Tous les enregistrements commencent par
v=DMARC1
. - Yahoo rejette carrément tous les e-mails sans SPF et DKIM.
- Hotmail et Google sont beaucoup plus permissifs dans leur approche.
- La directive
rua
permet de spécifier l’adresse mail qui recevra éventuellement les rapports détaillés des serveurs mail qui utilisent DKIM et auxquels votre serveur envoie des e-mails. Elle est facultative, et vous pouvez très bien vous en passer.
J’édite le fichier /var/named/zone.slackbox.fr
et j’ajoute un enregistrement DMARC à mon serveur DNS :
_dmarc IN TXT "v=DMARC1; p=none; sp=quarantine"
Ce n’est pas évident de garder un minimum de lisibilité dans tout ce fatras, entre la syntaxe à coucher dehors de BIND et la salade cryptographique générée par OpenDKIM :
Je recharge la configuration de BIND sans oublier d’incrémenter le numéro de la zone, et j’effectue la même opération pour mon domaine unixbox.fr
.
À partir de là, tous mes utilisateurs peuvent sereinement envoyer des e-mails vers tous leurs contacts qui hébergent leur messagerie chez Hotmail, Apple, Google ou Yahoo sans crainte de voir leurs missives finir au paradis des octets ou dans le dossier Spam.
La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce blog ? Offrez un café au rédacteur en cliquant sur la tasse.
1 commentaire
Bruno · 20 janvier 2024 à 9 h 12 min
Bonjour,
Il est sans doute préférable d’utiliser un socket UNIX plutôt que TCP pour opendkim. Il manque l’installation et la configuration d’opendmarc (peut-être pour un prochain article ?)
Attention aussi à l’utilisation de spamhaus qui bloque beaucoup trop d’adresses (zen)…