Emails, la vie en 2020
Ça faisait bien longtemps que je ne m’étais plus vraiment intéressé à ma configuration d’envoi et réception d’emails, ça avait été configuré pour le taf, je l’utilisais aussi pour le perso, de temps en temps je me trouvais juste à aller définir une nouvelle règle SpamAssassin, ou ajouter un domaine particulièrement pénible à une blacklist. Mais ça s’est un peu agité ces derniers temps avec notamment une volonté de DKIM/DMARC, et plutôt que suivre de loin et à l’occasion râler je me suis dit qu’il était peut-être temps de me replonger dans tout ça, et travail pratique, me refaire une configuration perso. (toute la suite Debian 10 (buster), ça a une importance la configuration exim y est particulière).
RĂ©ception (aliases, multi-domaines, antispam)
Bref, j’ai commencé petit, par la réception et l’utilisation simple d’alias pour quelques domaines, ici rien d’inventif, c’est juste une reprise en local de la configuration boulot, un fichier /etc/exim4/conf.d/router/350_exim4-config_vdom_aliases
pour diriger les messages en fonction de fichiers d’aliases,
vdom_aliases: driver = redirect domains = dsearch;/etc/exim4/virtual allow_defer allow_fail data = ${expand:${lookup{$local_part}wildlsearch*@{/etc/exim4/virtual/$domain}}} local_part_suffix = +* local_part_suffix_optional qualify_preserve_domain retry_use_local_part pipe_transport = address_pipe file_transport = address_file
Pour accompagner ça, donc, les fichiers d’alias, exemple /etc/exim4/virtual/0d.be
, avec une tête de fichier d’aliases,
fred: véritable@adresse de réception (...) abuse: fred postmaster: fred (...) fpeters: fred
Pour faire en sorte qu’un message reçu pour fpeters@0d.be au final arrive à mon adresse réelle unique.
Ici, aussi signifier à Exim que ces domaines doivent être considérés locaux, /etc/exim4/conf.d/main/01_exim4-config_listmacrosdefs
,
domainlist local_domains = @:localhost:dsearch;/etc/exim4/virtual:lsearch
Et ouvrir l’exim à l’internet (via dpkg-reconfigure exim4-config
).
Attendre un peu, même pas une heure, et voir que c’est déjà parti pour les « attaques » sur le serveur,
2020-05-27 21:06:05 SMTP protocol error in "AUTH LOGIN" H=(WUehgOMBV) [180.120.208.76] AUTH command used when not advertised
Du coup, là j’adapte un peu le plan et tape dès maintenant fail2ban, en activant les règles Exim, /etc/fail2ban/jail.local
,
[exim] enabled = true
Ça fonctionne et retour au plan, dernière étape pour la réception, modifier les MX renseignés dans la configuration DNS, et voilà ça marche, les emails sont bien reçus et réexpédiés au bon endroit.
Lendemain matin, vu que je suis là sur mon serveur, je peux y aller sur une configuration antispam un peu sévère, installation de SpamAssassin, intégration dans Exim via sa-exim, rien de particulier ici, ça marche vraiment tout seul.
Ajout de règles et augmentation de quelques scores dans /etc/spamassassin/local.cf
.
Expédition (routage local, SPF, DKIM, DMARC)
La suite, c'est envoyer des messages via tout ça, et ça commence par faire en sorte de ne pas tout envoyer par là , uniquement ce qui partirait avec un @0d.be (ou quelques autres) dans le domaine. Comme ma configuration locale passe par un exim local, c’est là que ça peut se jouer, modification de /etc/exim4/conf.d/router/200_exim4-config_primary
pour ajouter un routage particulier,
# send mail with @0d.be in From using mx.0d.be smarthost_0d: debug_print = "R: smarthost(0d) for $local_part@$domain" driver = manualroute domains = ! +local_domains transport = remote_smtp_smarthost condition = ${if match_domain{${domain:$h_From:}}{0d.be}{yes}{no}} route_list = * mx.0d.be::587 byname host_find_failed = ignore same_domain_copy_routing = yes no_more
Et définir le mot de passe adapté dans /etc/exim4/passwd.client
mx.0d.be:identifiant:mot de passe
Voilà pour le local (qui avec un client graphique façon Evolution ou Thunderbird aurait été réglé quelque part dans l’interface), ce n’était pas l’important, qui est la configuration côté serveur.
D’abord assurer que tout ça va bien être chiffré, cette partie est très bien expliquée dans le README.Debian (section « Enabling TLS support for Exim as server »), en gros génération certificats (via exim-gencert) puis MAIN_TLS_ENABLE = true
dans /etc/exim4/conf.d/main/00_local
.
Et autoriser les connexions sur le port 587, pour correspondre à ce qui a été configuré en local, daemon_smtp_ports = 25 : 587
dans le mĂŞme fichier.
Pour permettre l’authentification, direction /etc/exim4/conf.d/auth/30_exim4-config_examples, activation de la section login_server, et gestion simple du couple identifant/mot de passe via /etc/exim4/passwd.
Gestion simple modulo que çe ne passe pas, galère authentification (535 Incorrect authentication data (set_id=...
), peut-être parce que la documentation suggère d’utiliser mkpasswd
pour faire le mot de passe hashé mais l’algo pris par défaut (en local) n’était pas géré (sur le serveur). (mkpasswd --method=help
pour voir ce qui est géré, et peut-être que sa mention dans la page de manuel n'était pas fortuite).
Tout ça en place et désormais les emails partent correctement vivre leur vie, mais c’est juste là encore qu’une reproduction de la même configuration qu’il y a 20 ans (presque) (presque la même configuration, mais aussi presque 20 ans).
Depuis, et c’était dans l’introduction là tout en haut, il y a eu des spammeurs et des réactions, SPF, DKIM, DMARC et cie. Il y a eu il y a quelques années une série d’articles sur la configuration à ce sujet (particulièrement DKIM-signing outgoing mail with exim4 et Tying together SPF and DKIM with DMARC) qui sont utiles pour la compréhension générale, et la mise en place pratique, c’est principalement de là que j’ai travaillé.
Mais mini-information quand même : SPF et DKIM et DMARC sont des informations supplémentaires qui se joignent à un nom de domaine, pour déclarer que
- SPF : les emails de ce domaine doivent avoir été envoyés depuis telles adresses IP;
- DKIM : les emails de ce domaine doivent être signés avec telle clé;
- DMARC : les règles précédentes doivent être considérées.
(la force des premiers « doivent » n'étant en fait déterminés que par ce qui est dans le dernier)
Bon, modification DNS donc pour écrire une entrée SPF, là c’est facile,
@ TXT "v=spf1 a:skuf.0d.be mx ~all" @ SPF "v=spf1 a:skuf.0d.be mx ~all"
Il y a sans doute une raison historique et plus nécessaire à la duplication mais je laisse ça de côté. Donc ça dit que les emails en @0d.be sont associés à l'adresse IP de skuf.0d.be et au MX du domaine. (et comme les deux sont les mêmes, ça pourrait a priori être rétréci, le a:skuf.0d.be dégagé). (cette partie était déjà à peu près en place et je ne m’y suis pas repenché.)
Pour DKIM, le premier article pointé plus haut est un guide plutôt correct, avec juste quelques commandes qui ne marchent plus vraiment, et peut-être une erreur dans le code multi-domaine proposé, ou c’est moi qui ai trop vite copié/collé à un moment, aussi il nomme les fichiers d’une manière au début mais ils changent de nom sans rien dire pour l’exploitation un peu plus loin.
Tout commence par générer les clés :
$ openssl genrsa -out 0d.be.pem 1024 $ openssl rsa -in 0d.be.pem -out 0d.be-public.pem -pubout
Et placer ça dans /etc/exim4/dkim/, avec root:Debian-exim et 0640 comme propriétaires/permissions pour la clé privée.
L’information de la clé publique, il faut donc la copier dans une entrée de la zone DNS,
dkim._domainkey IN TXT "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQK...n3PagNkwIDAQAB"
Retour Ă exim pour la configuration, /etc/exim4/conf.d/main/00_local
,
DKIM_CANON = relaxed DKIM_SELECTOR = dkim # Get the domain from the outgoing mail. DKIM_DOMAIN = ${lc:${domain:$h_from:}} # The file is based on the outgoing domain-name in the from-header. # (c'est ici que je ne suis pas exactement l'article mentionné) DKIM_FILE = /etc/exim4/dkim/${lc:${domain:$h_from:}}.pem # If key exists then use it, if not don't. DKIM_PRIVATE_KEY = ${if exists{DKIM_FILE}{DKIM_FILE}{0}}
Et voilà , emails désormais signés DKIM.
2022 / petit point mise à jour vers Bullseye ici, il y a désormais une mécanique de "tainted files" dans exim et cette configuration la déclenche, façon
2022-01-03 06:06:35 1n4GUL-0016pH-R5 Tainted filename '/etc/exim4/dkim/0d.be.pem'
2022-01-03 06:06:35 1n4GUL-0016pH-R5 unable to open file for reading: /etc/exim4/dkim/0d.be.pem
Ça peut se corriger ainsi,
DKIM_PATH = /etc/exim4/dkim
# The file is based on the outgoing domain-name in the from-header.
DKIM_FILE = ${lc:${domain:$h_from:}}.pem
# If key exists then use it, if not don't.
DKIM_PRIVATE_KEY = ${lookup {DKIM_FILE} dsearch,ret=full {DKIM_PATH}}
Dernier bout la partie DMARC, donc retour zone DNS, pour déclarer qu’il faut prendre au sérieux, ou pas, les différentes règles,
_dmarc IN TXT "v=DMARC1; p=none; fo=1; adkim=s; aspf=s; rua=mailto:postmaster@0d.be"
Ici, p=none
, c’est pour que ça ne soit pas trop pris au sérieux, et fo=1 et rua=... pour recevoir des rapports par emails de la part des serveurs qui reçoivent les emails, pour permettre d’identifier peut-être des envois qui se font légitimement avec @0d.be mais qui ne passent pas par toute cette configuration. (le truc étant de suivre ces rapports, adapter le nécessaire, pour un jour pouvoir passer de p=none
Ă p=reject
).
Pour finir (un bonus sur les listes de diffusion)
Tout ça, contrôler qui peut écrire en @0d.be, est fondamentalement incompatible avec les listes de discussion, dont le cœur est la réexpédition de messages, et avec les politiques de rejet adoptées par certains fournisseurs, il y a eu adaptations, tant côté Sympa que Mailman, pour qu’il y ait réécriture de l’expéditeur, plutôt que voir arriver un message de "Frédéric Péters <fpeters@0d.be>", ça le transforme en "Frédéric Péters (via liste unetelle) <liste@unetelle>".
C’est plutôt pénible je trouve, et quand ça se combine avec la tendance de certaines applications d’emails à tout absorber dans un carnet d’adresse, ça fait des emails perso envoyés à "Frédéric Péters.... <liste@unetelle>". Fail. (dans le même ordre d’idée que les messages envoyés à -owner parce que même raison tout est absorbé)
Mais au-delà de ces erreurs, en tant que simple lecteur de ces messages, ça m’ennuie de ne pas voir la vraie adresse, et là , bonne nouvelle sur le front Sympa, ils la conservent dans l’entête X-Original-From
, elle peut donc être configurée pour être affichée, en plus. Ou via réécriture procmail, le message peut être restauré dans sa gloire originelle,
:0fhw * ^X-Original-From: \/.* | formail -i "From: $MATCH"
Pffiou. (et reste une partie pour la configuration dovecot/IMAP/etc. un autre jour) (et merci aux chatons de rendre tout ça accessible)