MouetteDans ce cinquiè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 Hotmail, Apple, Google ou Yahoo. 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 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. (
   2020060102   ; 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       163.172.220.174
ns      IN          A       163.172.220.174
mail    IN          A       163.172.220.174
@       IN          TXT     "v=spf1 mx ~all"
www     CNAME               slackbox.fr.
ftp     CNAME               slackbox.fr.
blog    CNAME               slackbox.fr.

InfoQuelques 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:163.172.220.174 ~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 163.172.220.174

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 163.172.220.174) 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 CentOS, OpenDKIM est fourni par le dépôt EPEL.

$ sudo yum install opendkim

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/
$ sudo cp -v opendkim.conf opendkim.conf.orig
‘opendkim.conf’ -> ‘opendkim.conf.orig’

Éditer /etc/opendkim.conf en modifiant les directives suivantes.

...
##  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
...
##  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

InfoEn règle générale, les articles de blog et autres tutoriels sur OpenDKIM estampillent les clés de la date en cours, comme 20200602._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.

$ sudo 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’
$ sudo 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
$ sudo 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
$ sudo 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 20200602.
  • 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.

$ sudo 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.

$ sudo 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.

$ sudo opendkim-testkey -d slackbox.fr -s 01 -vvv
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: checking key '01._domainkey.slackbox.fr'
opendkim-testkey: key OK
$ sudo opendkim-testkey -d unixbox.fr -s 01 -vvv
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: checking key '01._domainkey.unixbox.fr'
opendkim-testkey: key OK

Puisque tout est OK, j’active et je démarre le service OpenDKIM.

$ sudo 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.

# Applications Milter
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.

$ sudo usermod -a -G opendkim postfix

Redémarrer Postfix pour prendre en compte les modifications.

$ sudo 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.

SPF DKIM

Domain-based Message Authentication, Reporting & Conformance

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 oeil sur la configuration DMARC des quatre fournisseurs de 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:d@rua.agari.com;ruf=mailto:d@ruf.agari.com;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:dmarc_y_rua@yahoo.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"

InfoCe 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 DNS

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.

 


3 commentaires

Nicolas K. · 2 juin 2020 à 14 h 57 min

Vachement sympa cette série d’article, ils ont l’avantage sur la plupart des tutoriels qu’on trouve sur internet d’expliquer clairement l’utilité des options de configuration utilisées. Merci.

    kikinovak · 2 juin 2020 à 16 h 07 min

    Merci pour les fleurs. En règle générale j’essaie d’écrire des articles que mon moi ancien aurait aimé lire. :o)

Berrand · 26 novembre 2020 à 21 h 57 min

Hello,

Merci pour ce tutoriel effectivement très bien détaillé…
Cependant, j’ai une erreur pour laquelle je ne trouve pas de solution.
Aucun des emails envoyés n’est signé.
J’ai systématiquement cette erreur dans les logs postfix :
opendkim[20530]: 19E7E18BAB89: can’t determine message sender; accepting

J’ai cherché avec mon ami GG (par lequel j’ai trouvé cette page) et j’ai essayé beaucoup de pseudo solution sans succès.

Très bonne continuation.

Bertrand

Les commentaires sont fermés.