MouetteDans 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

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 :

SPF Record Checker

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

AstuceEn 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/KeyTableen 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

InfoDans 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 que 01, vous pouvez mettre la date sous la forme 20240118.
  • 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 :

OpenDKIM DNS

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.

ImportantLorsque 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 que non_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 :

Test DKIM

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"

AstuceCe 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 :

DMARC

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)…

Laisser un commentaire

Emplacement de l’avatar

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *