[Infra] Auto-hébergement mail : 15 ans de surprises
@ Nicolas | Tuesday, Nov 30, 2021 | 12 minutes de lecture | Mise à jour le Tuesday, Nov 30, 2021

Depuis 15 ans d’auto-hébergement, le service le plus critique que je peux avoir est mon hébergement mails.

En 15 ans, j’ai énormément travaillé ma configuration, et surtout fait évoluer mon infra pour palier aux pépins successifs…

Un peu d’historique

Cet historique me ramène au temps jadis où ça me faisait rêver d’avoir mes boites mails avec mon propre nom de domaine. Quand mes premiers serveurs ont donc commencé à être en ligne, je me suis dit, tentons l’expérience, y’a des choses à apprendre !

Il faut savoir tout de même qu’il y a 15 ans, si mes calculs sont bons, j’avais 15 ans d’expérience en moins…

what

Clairement donc, je ne savais pas du tout dans quoi je mettais les pieds, et j’avais encore moins conscience de la toile d’araignée dans laquelle j’allais me retrouver.

Juste quelques détails techniques

Le but de cet article n’est pas de donner du code ou de la conf, ou d’expliquer en détail le fonctionnement d’un serveur mail ; juste de partager mon expérience et l’évolution de mon infra associée.

Néamoins, juste quelques petites choses à savoir :

Un client mail est un “MUA” (Mail User Agent). Quand on écrit un mail avec on le donne pour expédition au “MTA” (Mail Transfert Agent). Celui-ci le donne au MTA du destinataire (ou plusieurs intermédiaires).

Le MTA du destinataire fournit le mail au “MDA” (Mail Deliver Agent), via différents protocoles (en local, ou via LMTP par exemple). Ce MDA est également joignable pour l’utilisateur récepteur par un MUA via le protocole IMAP ou POP.

mail_scheme

Le MTA est donc le programme qui gère les transferts de mails entre domaines (postfix, via SMTP(S)).

Le MDA gère le stockage des mails et des boîtes (dovecot, via IMAP(s)/POP(s)). Les deux peuvent gérer une authentification, qui peut être commune (c’est quand même plus pratique :p).

Le MUA ne fait que donner l’accès aux deux. Il peut être un logiciel lourd ou une interface web (webmail).

Le transfert des mails entre domaines est basé majoritairement sur des entrées DNS : pour que toto de foo.com puisse envoyer un mail à tata de bar.com, il faut que le MTA de foo.com sache qui est le MTA de bar.com. Il interroge donc le(s) champ(s) DNS “MX” du domaine bar.com.

On peut avoir plusieurs MTA, définis par des priorités (un numéro). Le plus faible sera le premier a être contacté. S’il est injoignable le MTA source tentera le(s) suivant(s).

Qu’est-ce qu’il se passe si aucun MTA ne répond ? C’est à la bonne volonté du MTA source. En général plusieurs tentatives seront faites, et au bout de x heures/jours, le mail sera détruit et l’émetteur sera notifié par retour de mail.

D’autres entrées DNS sont utilisées, plus pour la sécurité. On y reviendra plus tard :p

Une architecture initiale basique

Me voilà donc au départ sur mon serveur (ubuntu-server de mémoire), à monter un serveur SMTP sous Postfix, et tenter un IMAP/POP sur Dovecot.

Dovecot est pour moi une super découverte, bien que la configuration soit tout de même assez épaisse, son organisation en multiples fichiers dans conf.d, et ses commentaires rendent assez facile son paramétrage (bien qu’on ne puisse pas tout deviner).

Par contre, Postfix, m’a fait moins rêver, bien qu’il fonctionne très bien. Soyez juste vigilants sur Postfix, on trouve un peu tout et n’importe quoi sur des forums. La doc officielle n’est pas la plus “lisible” mais elle reste la seule référence à privilégier.

La première des choses à laquelle j’ai du me confronter était déjà de comprendre la différence dans postfix entre le SMTP qui reçoit les mails et celui qui les envoie, et de commencer à jongler sur les différents ports 25/587/465, sans oublier la dépendance aux certificats… Et oui pas de letsencrypt à cette époque !

Egalement, un peu d’auto-formation sur le fonctionnement des mails (champs MX tout ça, tout ça..) et c’est parti.

Gentillement mais surement donc, quelques entrées DNS plus tard, j’ai pu avoir au moins un IMAP/SMTP en autosigné qui fonctionne, et j’ai commencé la découverte.

Le premier conseil que je peux donner c’est : les logs c’est la vie. Au premier abord les logs mails sont un peu lourds, mais en fait ils sont très complets et on y suit très bien le workflow de l’arrivée d’un mail au MTA jusqu’à son stockage par le MDA.

Deuxième conseil, telnet c’est parfait pour le mail. Rien de tel que de connaitre les infos telnet pour envoyer un mail en console à son serveur SMTP pour débuguer.

Un petit exemple :

telnet monserveursmtp.mondomaine.tld 25
Connected to monserveursmtp.mondomaine.tld.
Escape character is '^]'.
220 monserveursmtp.mondomaine.tld ESMTP Postfix
helo domaineclient.tld
250 monserveursmtp.mondomaine.tld
mail from: <monexpediteur@mondomaineclient.tld>
250 2.1.0 Ok
rcpt to: <mondest@mondomaine.tld>
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
subject: Ceci est un test
le corps du mail
et on termine par un point sur une ligne
.

Ceci permet de bien suivre dans les logs l’arrivée du mail, puis sa transmission au Dovecot.

Bon, je n’ai pas commencé à filer mes adresses partout, trop peu confiance en mon infra au départ. Il fallait donc laisser mûrir le sujet :D

Premières galères

Je compare souvent les mails à une partie de foot. Vous avez plein de serveurs SMTP qui sont sur le terrain, et des mails qui se passent entre eux. Le problème c’est que si un SMTP ne répond pas ou répond n’importe quoi, le mail part en dehors du terrain et c’est foutu.

On tombe donc dans le fait qu’on ne sait peut-être pas qu’on a raté un mail :p

Dans mon cas, il faut savoir que mon MTA, postfix, était donc derrière ma box SFR à la maison.

  • Première chose, pour éviter le spam, beaucoup d’opérateurs bloquent le port 25 en entrée et/ou sortie. Certains peuvent l’autoriser en sortie si on l’active dans la box.
  • Deuxième chose, beaucoup de MTA de destination n’aiment pas trop être contactés par un MTA venant d’une IP dynamique.

Je me suis donc retrouvé dans plusieurs cas :

  • mes mails restent dans la queue et ne partent pas : le port 25 est bloqué en sortie
  • mes destinataires reçoivent mon mail comme spam : la réputation de mon IP publique n’est pas bonne
  • mes mails sont rejetés par le MTA distant : idem
  • je reçois du spam (Tu veux agrandir ton … ) : mon postfix est trop ouvert

Il y a plusieurs choses à faire pour éviter d’être considéré comme SPAM.

Du DKIM

Le but est de signer les mails sortants avec une clé, et de déclarer la publique sur les DNS. Ainsi, lorsque le MTA distant le reçoit, il fait une requête DNS sur le champ TXT DKIM du domaine source, et compare la clé publique qui s’y trouve avec celle reçue dans le mail.

Tout simplement car on considère que l’administrateur d’un serveur mail a forcement la main sur la zone DNS associée ; et surtout, car n’importe qui peut envoyer un mail et changer les entêtes pour se faire passer pour un autre domaine emetteur.

Pour Postfix, j’utilise OpenDKIM qui est à connecter comme “milter”, et qui fait très bien le job.

Du SPF

Le but du SPF est d’éviter qu’un autre MTA envoie des mails avec votre domaine. Dans ce champ DNS au type “SPF” on indique quels sont les entrées A, MX ou IP spécifiques autorisées à envoyer des mails.

Le MTA destination va donc faire une requête à la réception du mail pour valider que le MTA source est dans la liste. Ceci permet de valider que c’est bien votre SMTP à vous qui émet des mails avec votre domaine.

Un antispam

Pour éviter de recevoir du spam, il y a plusieurs axes :

  • durcir postfix pour faire des vérifications à l’arrivée d’un mail : on peut lui dire par exemple d’exclure tout mail provenant d’un nom de domaine qui n’existe pas
  • demander à postfix de vérifier la réputation de l’IP qui arrive
  • faire scanner les mails par un antispam (rspamd ou spamassassin)
  • être taré comme moi et faire un script bash qui recherche tous les soirs le smtp qui m’a fourni un SPAM via les logs, et le balancer en IPTABLES DROP pendant quelques jours :D (si si…)

Ces quelques règles m’ont rapidement permis d’avoir un système qui fonctionne, est qui est, correctement toléré malgrès mon IP publique.

Rajout de domaines

Un domaine c’est cool, plusieurs c’est mieux.

J’ai rajouté donc une couche d’un outil type vimbadmin, qui permet de créer des domaines, des alias, et des comptes, le tout dans une base de données. Postfix et Dovecot interrogent donc cette base pour avoir les comptes existants.

Bien évidemment, cette base ne doit pas être joignable sur internet, ni la console de vimbadmin. Enfin on peut, mais personnellement je ne le ferais pas.

Encore des galères

Vous avez déjà déménagé ? En général, c’est chouette, les cartons, le tri, etc..

Mais quand t’es un geek, il faut prévoir :

  • d’avoir internet à l’arrivée
  • pouvoir couper tes machines pour une durée indéterminée

Sauf que n’oublions pas, nos mails sont nos petits joueurs de foot. Si Toto est dans les vestiaires pendant le match, il ne reçoit pas le ballon.

fail_socker

Première chose donc, je suis parti dans l’idée d’avoir au moins un MX de backup. Son but est d’être le dernier de la liste des MX, et de prendre le mail en dernier recours, et de le garder dans sa mailq indéfininement. Il tente juste de le réémettre au MX principal fréquemment.

L’avantage c’est que le mail est considéré comme transmis par le MTA de l’émetteur, et il arrive sur une zone que je contrôle.

J’ai donc monté un MTA seul sur une machine supplémentaire, chez un hébergeur au cas où.

Au passage, la possibilité d’avoir une IP publique qui n’est pas associée avec un FAI de particulier, et de pouvoir avoir un reverse DNS propre, m’a poussé dans l’idée de m’en servir aussi de SMTP de sortie. Ainsi donc mon serveur mail distribue les mails au travers de ce relai. Si ce relai n’est pas joignable ponctuellement ce n’est pas grave, le mail à envoyer reste dans la queue de mon serveur de mail, et fini par partir plus tard. Encore moins de spam depuis ce jour, et plus de soucis de réception de mail chez mes correspondants.

Vis-à-vis de mon déménagement, j’ai réfléchi à un moyen de ne pas avoir de coupures sur mes mails, sur la partie MDA. Car c’est bien de recevoir les mails, mais pouvoir les consulter serait une bonne chose. A ce moment mon serveur mail n’était pas une VM, pas marrant donc à sortir et à déplacer sur quelconque machine ailleurs chez un hébergeur, même ponctuellement.

Je me suis donc lancé dans le cluster…

Postfix, à clusteriser n’est pas vraiment un problème. Grace aux champs DNS MX, on peut avoir autant de serveurs SMTP qu’on veut, qui peuvent derrière soit fournir le mail via LMTP à un Dovecot, soit le fournir au MX principal. Pas réellement besoin donc d’un “cluster”. Dovecot, c’est différent car tous les mails y sont stockés. Mais c’est là que la magie opère. Dovecot gère très bien le cluster actif/actif.

Me voilà parti dans la création (via ansible) d’un nouveau serveur mail déporté ponctuellement chez un hébergeur. J’ai ensuite connecté ce MDA Dovecot à mon Dovecot existant, via VPN Wireguard, via une configuration de replica : https://wiki.dovecot.org/Replication En l’espace de quelques minutes, Dovecot sur le nouveau serveur avait synchronisé mes mails depuis l’existant.

Et les comptes ? Et oui les comptes sont en base de données. Donc c’est parti, un cluster Mariadb. J’ai fait simple, le serveur mail “secondaire” est un slave mysql. Je sais donc que la création des comptes doit passer par le premier serveur, mais ce n’est pas un souci.

A ce point c’est donc simple : mon MUA peut atteindre mes mails sur l’un des deux MDA, en mettant le nom du serveur mail associé.

Si quelqu’un m’envoie un mail, mon premier MX est sur mon serveur principal @home. S’il est actif il prend le mail et le donne à son MDA local, qui va le synchroniser tout seul sur le MDA replica.

Si mon premier MX n’est pas joignable, le second sera contacté, qui le prendra et le donnera à son MDA local, qui va tenter aussi de le synchroniser sur le MDA replica.

Si les deux dovecot ne se voient pas, ils se synchroniseront dans les deux sens plus tard (c’est bien fichu).

Le jour de mon déménagement, j’étais donc serein, j’éteins, et ça fonctionne toujours. Je rebranche, et ça reprend.

J’ai pu reprendre mon réplica mail de mon hébergeur et le mettre sur une machine à moi par la suite. Le truc c’est qu’entre temps je n’ai pas pris le temps de le déporter chez une personne de confiance… et ça c’est une erreur.

Quelqu’un a dit fibre ?

A ce nouveau domicile, fibré également, j’ai eu la joie de subir les bétîses de mon FAI : je ne vais pas jeter la faute sur quiconque, mais qui n’a jamais entendu parler des déconnexions intempestives de fibre lorsqu’un nouvel abonné arrive sur le PM et qu’il n’y a plus de place ?

Couplé avec un FAI qui a un support totalement inutile, me voilà donc dans le noir pendant des jours sans perspective d’une réparation (mais j’en ferais surement un autre article, parce que là…).

burn

A ce moment là, mon replica est aussi en local. Un beau replica inutile donc.

Rapidement donc je le déporte, mais, impossible d’avoir un accès en entrée sur internet à cet endroit. J’y avais déjà pensé par le passé, la dépendance à une IP publique dynamique et à des ouvertures de ports dans un routeur FAI peut poser problème.

J’ai donc revu mon infra : j’utilise mon VPS comme point d’entrée pour le MDA et le MTA.

Via une configuration simple HAPROXY, c’est lui qui me redirige vers l’un de mes deux serveurs mails, qui sont eux mêmes joignables via un VPN wireguard. Il faut juste modifier deux trois petites choses dans postfix/dovecot pour gérer haproxy comme proxy (j’en ferai un autre article).

Ceci me permet :

  • de ne plus avoir à jongler sur le nom de domaine de mon IMAP/SMTP
  • de basculer automatiquement sur un serveur joignable sans m’en inquiéter (va falloir juste faire checker les backend haproxy par mon monitoring)
  • de ne plus dépendre d’une IP publique en entrée sur un FAI de particulier
  • de ne plus dépendre d’une ouverture de flux entrant sur un FAI de particulier

Le seul point négatif : mon VPS est mon SPOF. Après, il y a toujours un SPOF. L’avantage c’est que si le VPS tombe, rien ne m’empêche de changer de nom de domaine pour utiliser mon IMAP/SMTP @home. De plus, puisque toute la configuration est dans ansible, je peux en déployer un autre en quelques minutes si besoin.

Au final ça ressemble un peu à ça (bon je suis pas doué en schémas) :

archi-mail

Quelle sera la suite ?

On me dira surement que je m’emmerde un peu à héberger mes mails, mais bon, on ne va pas changer maintenant ? :p

L’avenir en dira plus :D

© 2017 - 2022 Some stuff...

Powered by Hugo with theme Dream.