Reprendre en main ses emails

Depuis les révélations d’Edward Snowden et le fameux article du Guardian révélant l’étroite collaboration entre les webmails et les services secrets américains, je me suis mis à chercher une alternative à ces services pour gérer différemment mes emails. Depuis mars 2014, j’ai enfin une adresse email qui m’appartient, qui fonctionne bien. Dans ce billet je vais partager avec vous mon expérience et vous aidez à reprendre en main vos emails !

Obsolète lisez plutôt OpenSMTPD-Dovecot-SpamAssassin

Avant de commencer, je tiens à préciser que ce billet est technique. Nous allons apprendre à configurer des outils comme OpenSMTPD et Dovecot. L'objectif final est de vous permettre d'avoir votre propre serveur mail et de comprendre comment ça marche. Pas à pas, une étape après l'autre, avec des tests entre chaque étape. Voici l'objectif de ce billet. Pour mener à bien cette reprise en main, il va vous falloir:

Un email c'est quoi ?

Un email c'est du texte formaté selon une norme (RFC 5322) qui transite sur internet. Pour envoyer un email on a besoin d'un serveur mail : une machine qui s'occupe d'envoyer notre email à l'autre bout de la Terre. Pour recevoir un email il faut un autre serveur mail. Ces serveurs mails communiquent entre eux avec le protocole SMTP (RFC 5321).

Un serveur mail pour envoyer un email il a besoin d'une adresse email d'origine (contact@example.com), d'un destinataire ({$ email $}) et d'un contenu.

En gros voici les grandes lignes du déroulement d'un envoi d'email:

  • le serveur mail example.com cherche l'adresse IP du serveur mail {$ domain $}
  • il établit une connexion SMTP avec ce serveur mail
  • il converse en SMTP pour transférer l'email
  • il ferme la connexion SMTP

Configurer ses DNS

Pour récupérer l'adresse ip du serveur mail de destination, votre serveur mail va interroger les DNS associées au nom de domaine de l'email. Et plus particulièrement il va chercher à récupérer l'enregistrement MX dans vos DNS.

Pour que la résolution DNS fonctionne, il faut mettre à jour cet enregistrement dans notre gestionnaire de DNS (Ovh, Gandi, Bookmyname, etc). Il faut se connecter à l'interface de gestion et modifier l'enregistrement. Modifier ou ajouter l'enregistrement MX pour qu'il pointe vers mail.{$ domain $}

{$ domain $}.                 300  MX     10 mail.{$ domain $}.

Le . à la fin des nom de domaine indique des noms de domaines absolus. 10 indique la priorité de l'engistrement quand on a plusieurs MX. Le 300 correspond au TTL (Time To Live) de la DNS. 300 correspond à 300 secondes, ce qui est court. A la fin quand tout fonctionne il est conseillé d'augmenter ce TTL pour éviter des déboires comme ceux rencontrés par @N.

Ensuite il faire pointer le sous-domaine mail.{$ domain $} vers l'adresse ip de notre serveur en ajoutant un enregistrement de type A:

{$ domain $}.                 300  MX     10 mail.{$ domain $}.
mail                      300  A      {$ ip $}

D'après les RFC des DNS, un enregistrement de type MX doit pointer vers un sous-domaine, et ensuite ce sous-domaine doit pointer vers une adresse IP. J'utilise la convention mail.{$ domain $} mais vous pouvez utiliser le sous-domaine de votre choix.

Récupérer l'adresse email du serveur mail de destination

Pour être sur que nos DNS sont bonnes, nous allons les interroger avec l'outil dig installé par défaut sur votre machine.

$ dig +noall +answer MX {$ domain $}
{$ domain $}.		300	IN	MX	10 mail.{$ domain $}.

On retrouve notre enregistrement défini précédemment dans nos DNS. Si vous n'avez aucune réponse à cette commande alors il va falloir attendre que vos DNS se propagent.

dig +noall +answer correspond à la commande dig pour obtenir une réponse claire sans fioritures

MX correspond au mail exchanger record (MX record) qui indique dans les DNS le nom de domaine d’un serveur mail. En gros où se trouve le serveur mail associé au nom de domaine.

{$ domain $} nom de domaine pour lequel on veut récupérer le MX

Grâce à la réponse de la première requête dig (mail.{$ domain $}.), on récupère le sous-domaine associé au MX pour savoir vers quelle adresse ip il pointe.

$ dig +noall +answer A mail.{$ domain $}.
mail.{$ domain $}.		107	IN	A	{$ ip $}

Attention à demander l'enregistrement de type A (Adresse record).

Ainsi avec deux résolutions DNS, notre serveur mail d'envoi est capable de connaitre l'adresse ip de votre serveur mail pour votre nom de domaine {$ domain $}.

Choisir son serveur mail

La configuration DNS est terminée :) enfin pour l'instant. Maintenant que l'enregistrement MX pointe vers notre nom de domaine, il est temps de mettre en place notre serveur mail. Quand j'ai cherché à configurer mon propre serveur mail j'ai eu rapidement le choix entre Postfix et Sendmail. J'ai essayé de configurer les deux, avec succès, mais sans vraiment comprendre pourquoi ça fonctionnait. Sendmail tout comme Postfix sont bien trop compliqués à configurer. Or il s'avère qu'une alternative, de la trempe des grands, existe : OpenSMTPD. En quelques mots OpenSMTPD c'est facile à configurer, avec une licence logicielle sympa, écrit en C, fonctionne sur beaucoup de plateformes et avec une attention particulière pour la sécurité et la stabilité. J'ai essayé OpenSMTPD et comparé aux deux autres, c'est le jour et la nuit ! Moins d'administration système, plus sûr, plus simple.

Configurer OpenSMTPD

Opensmtpd va avoir besoin d'un utilisateur pour envoyer les emails ({$ user $}) et d'un hostname configuré correctement (mail.{$ domain $}).

Ajout d'un utilisateur à notre système :

useradd -m -u 5000 {$ user $} -d /home/{$ user $}/

Ajouter un mot de passe à notre utilisateur:

passwd {$ user $}

C'est le mot de passe qui vous permettra de consulter vos emails via le protocole IMAP.

Éditer le fichier /etc/hosts :

127.0.0.1 mail.{$ domain $} mail localhost

Et configurer notre hostname en éditant le fichier /etc/hostname :

mail.{$ domain $}

OpenSMTPD va utiliser le hostname dans sa conversation SMTP avec les autres serveurs mails.

N'oubliez pas de copier certificate.{$ domain $}.crt dans le dossier /etc/ssl/certs/ et private.{$ domain $}.key dans le dossier /etc/ssl/private.

Installer Opensmtpd

Sur ubuntu rien de plus simple:

sudo apt-get install opensmtpd 
Sur freebsd
pkg install opensmtpd

Pendant l'installation il va vous demander le FQDN (Fully qualified domain name) qui correspond à la partie à droite de l'arobase ({$ domain $}) et le nom d'utilisateur sur lequel vont être redirigés les emails root et postmaster. Vous pouvez mettre {$ user $}.

Envoyer un email

Pour envoyer un email, un client mail (thunderbird, mail, etc) communique avec votre serveur mail en SMTP. Votre client mail s'identifie auprès de votre serveur email. Puis avec quelques commandes demande au serveur mail d'envoyer un email. Votre serveur mail communique ensuite à son tour avec le serveur mail de destination en SMTP pour relayer votre email.

On va commencer par préciser à opensmtpd que toutes les personnes authentifiées ou locales, peuvent envoyer un email à n'importe qui. Pour cela on va éditer le fichier /etc/smtpd.conf.

Remplacer le contenu du fichier par :

pki mail.{$ domain $} certificate "/etc/ssl/certs/certificate.{$ domain $}.crt"
pki mail.{$ domain $} key "/etc/ssl/private/private.{$ domain $}.key"

listen on eth0 port 25 hostname mail.{$ domain $} tls pki mail.{$ domain $}
listen on eth0 port 587 hostname mail.{$ domain $} tls-require pki mail.{$ domain $} auth mask-source

accept from local for any relay

recharger le fichier de configuration avec la commande service opensmtpd restart

Les deux premières lignes sont faciles à comprendre: on définit deux pki (Public key infrastructure) une pour la clef privée (key) et une pour le certificat public.

Ensuite on demande à OpenSMTPD d'écouter sur l'interface réseau eth0 sur les ports 25 et 587, pour le hostname mail.{$ domain $}. On utilise le protocole TLS avec les pki définit juste avant. Et on autorise l'authentification avec le mot-clef auth. mask-source permet de cacher le nom de la source de l'email, utile quand on ne veut pas donner trop d'informations. (Merci Vigdis pour l'astuce)

Les serveurs SMTP communiquent entre leurs ports 25. Alors que notre client mail va communiquer en SMTP sur le port 587 en STARTTLS de manière authentifiée et sécurisée. C'est la raison pour laquelle on a deux lignes dans le fichier de configuration.

La dernière ligne précise que toutes les personnes locales à la machine (ou authentifiées) peuvent relayer des emails.

Tester l'envoi d'un email

Pour tester que la communication avec le serveur mail et vérifier que l'authentification fonctionne, on va ouvrir une connexion TLS sur notre serveur mail sur le port 587. Nous allons utiliser l'outil openssl installé par défaut.

L'authentification ne marche que sur une connexion sécurisée.

$ openssl s_client -starttls smtp -connect mail.{$ domain $}:587 -crlf -ign_eof
...
250 HELP

À ce moment le serveur mail attend qu'on lui dise bonjour. On se présente en tapant la commande EHLO suivi d'un identifiant

EHLO moi

Le serveur mail répond bonjour, et liste les commandes disponibles:

EHLO moi
250-mail.{$ domain $} Hello moi [{$ ip$}], pleased to meet you
250-8BITMIME
250-ENHANCEDSTATUSCODES
250-SIZE 36700160
250-AUTH PLAIN LOGIN
250 HELP

Ensuite on s'authentifie en envoyant une chaine de caractère encodé en base 64 avec la concatenation du nom d'utilisateur et du mot de passe avec des séparateurs \000

Pour générer sa clef d'authentification en javascript (ouvrir sa console):

btoa("\000{$ user $}\000{$ password $}")

Sinon vous pouvez rentrer votre mot de passe et copier le résultat encodé



Maintenant vous pouvez vous authentifier auprès de votre serveur SMTP

AUTH PLAIN {$ auth $}

OpenSMTPD répond

235 Authentication succeeded

Maintenant on peut envoyer un email avec les commandes suivantes:

MAIL FROM: <{$ user $}@{$ domain $}>
250 Ok
RCPT TO: <{$ user $}@{$ domain $}>
250 Recipient ok
DATA
354 Enter mail, end with "." on a line by itself
Subject: Test

it works!
.
250 e59bb2aa Message accepted for delivery
quit
221 Bye
read:errno=0

L'email n'arrivera certainement jamais, mais l'envoi fonctionne, passons à la récupération des emails.

Reception SMTP d'un email

Nous allons éditer notre fichier /etc/smtpd.conf une dernière fois:

pki mail.{$ domain $} certificate "/etc/ssl/certs/certificate.{$ domain $}.crt"
pki mail.{$ domain $} key "/etc/ssl/private/private.{$ domain $}.key"

listen on eth0 port 25 hostname mail.{$ domain $} tls pki mail.{$ domain $}
listen on eth0 port 587 hostname mail.{$ domain $} tls-require pki mail.{$ domain $} auth mask-source

accept from local for any relay

table aliases file:/etc/aliases
accept from any for domain "{$ domain $}" alias <aliases> deliver to maildir "~/mails"

recharger le fichier de configuration avec la commande service opensmtpd restart

On rajoute les deux dernières lignes pour la réception des emails, une pour décrire le chemin d'une table d'aliases, et une pour signifier à OpenSMTPD de transférer tous les emails à destination d'{$ domain $} dans le dossier mail de chaque utilisateur décrit dans la table /etc/aliases.

Le fichier /etc/aliases ressemble à ça :

root: {$ user $}
postmaster: root
webmaster: root
contact: {$ user $}

Tous les emails root@{$ domain $}, postmaster@{$ domain $}, webmaster@{$ domain $} et contact@{$ domain $} sont des aliases pour {$ user $}@{$ domain $}. Chaque fois qu'un email est envoyé à un de ces comptes, l'email arrive dans le dossier /home/{$ user $}/mails/

C'est terminé pour la partie serveur mail, 7 lignes de configuration ! Si vous voulez faire évoluer cette configuration et rajouter des fonctionnalités, je vous invite à lire la documentation

IMAP, récupérer ses emails

Pour récupérer ses emails avec son client mail, nous allons utiliser un protocole: l'IMAP (Internet Message Access Protocol). Pour configurer l'IMAP, nous allons utiliser l'outil dovecot.

Pour l'installer sur ubuntu rien de plus simple:

sudo apt-get install dovecot-imapd 
Sur freebsd
pkg install mail/dovecot

Refusez la création d'un certificat, puisque nos certificats existent déjà.

Configurer Dovecot

Je trouve la configuration de Dovecot compliqué à comprendre. Alors j'ai tendance à vider le dossier de configuration la première fois.

rm -rf /etc/dovecot/*
touch /etc/dovecot/dovecot.conf

Pour configurer Dovecot, nous allons éditer le fichier /etc/dovecot/dovecot.conf:


protocols = imap
ssl = yes
ssl_cert = </etc/ssl/certs/certificate.{$ domain $}.crt
ssl_key = </etc/ssl/private/private.{$ domain $}.key
ssl_client_ca_dir = /etc/ssl/certs
mail_location = maildir:~/mails
listen = *

userdb {
  driver = passwd
  args = blocking=no
}

passdb {
  driver = pam
  args = 
}

Je vais pas épiloguer sur cette configuration très longtemps. Notez la présence de nos certificats générés plus tôt. Nous communiquons en ssl. Nous utilisons l'authentification pam pour se connecter à la machine en IMAP seulement.

C'est terminé pour la partie IMAP, 15 lignes de configuration !

Client mail

Voici les informations de connexion à mettre dans votre client mail. Pour consulter ses mails en IMAP :

  • Serveur imap: mail.{$ domain $}
  • Nom d'utilisateur: {$ user $}
  • Mot de passe: {$ password $}
  • Port: 993
  • Utilisez SSL: oui

Pour envoyer des emails en SMTP:

  • Serveur smtp: mail.{$ domain $}
  • Nom d'utilisateur: {$ user $}
  • Mot de passe: {$ password $}
  • Port: 587
  • Utilisez SSL: oui

DNS & SPF

Maintenant que tout fonctionne bien, nous allons augmenter nos TTL sur nos DNS et rajouter une protection de notre nom de domaine : le SPF.

Pour augmenter le TTL, il suffit de changer la valeur de 300 précédemment définit dans nos DNS et de monter cette valeur à 86400 secondes (1 journée) minimum, valeur recommendée par la RFC 1033

Le SPF (Sender Policy Framework) est une protection pour éviter que des personnes envoient des emails avec votre nom de domaine. Il faut donc rajouter un enregistrement TXT dans nos DNS en précisant que seul le serveur mail de oslab.fr a le droit d'envoyer des emails.

{$ domain $}. IN TXT "v=spf1 mx mx:{$ domain $} -all"

Merci

Pour terminer, j'aimerais remercier les lecteurs attentifs et le collectif GIROLL qui m'a permis de tester ce tutoriel en vrai. Si vous avez aimé ce tutoriel, n'hésitez pas à proposer des améliorations en pull request sur github. Il est fort possible qu'il y ait des fautes, n'hésitez pas à me ping sur twitter si tel est le cas.