Coin web de Frédéric Péters

fpeters@0d.be

Emails, la vie en 2020

4 juin 2020, 10:41

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