Relayage avec identification SMTP - Debian 9.0 Stretch
Rédigé par Marc GUILLAUME | 10 commentairesTraduction de la page : https://workaround.org/ispmail/stretch/relaying-smtp-authentication
Relayage
Votre serveur de mail est presque prêt à l'utilisation. Mais il manque une pièce du puzzle. Vos utilisateurs peuvent déjà récupérer leur courrier, mais ils doivent également pouvoir en envoyer. Les serveurs de mail savent comment envoyer un mail vers un autre serveur, en utilisant les enregistrements MX. Les serveurs destinataires vont joyeusement accepter tout mail destiné à un destinataire existant. Mais cependant les clients de messagerie sont supposés envoyer les mails à leur serveur de mail qui lui va les acheminer sur Internet. Quand Postfix reçoit un mail d'un utilisateur et le transmet à un autre, cette opération est appelée « relayage ». Postfix agit en tant que « relais ».
Mais pourquoi les client de messagerie ne fonctionnent-t-ils pas sur le même mode ? Ne peuvent-ils pas se contenter de chercher l'enregistrement MX et envoyer le mail au serveur destinataire ? Techniquement ils pourraient, oui. Mais les utilisateurs sont souvent chez eux, derrière un ligne DSL. Et ces réseaux d'IP sont habituellement bloqués pour l'envoi de mails. Certains FAI bloquent le port SMTP sur leurs routeurs. Et la plupart des serveurs de réception utilisent des « real-time blacklists » (listes noires en temps réel) pour bloquer les IP DSL. La raison en est que de trop nombreux utilisateurs ont chez eux des PC sous Wind*ws infectés par des virus et envoyant du spam.
Je vais trop vite ? D'accord, passons les différents scénarios en revue un à un.
Les mails entrants
Quand quelqu'un envoit un mail à john@example.org un serveur quelque part sur Internet va envoyer, en utilisant SMTP, le mail à votre serveur. Postfix va regarder s'il est responsable de cette adresse dans le domaine example.org et accepter le mail. John peut alors utiliser POP3 ou IMAP pour récupérer le mail sur le serveur.
Les mails sortants (sans identification)
John est quelque part sur Internet et veut envoyer un mail à lisa@example.com. Votre serveur de mail n'est pas responsable du domaine example.com, il reçoit le mail et le transfère (relaye) vers le serveur qui est responsable des adresse de type …@example.com. Cela peut sembler un scénario sans danger, pourtant votre serveur doit interdire ça :
Pourquoi ? Parce que n'importe qui peut se faire passer pour John et demander à votre serveur de relayer un mail. Si un attaquant (comme un spammer) voulait envoyer des millions de mails de spam au nom de John via votre serveur, alors les autres responsables de serveur vous accuseraient d'être vous même un spammeur en tant qu'opérateur du serveur ayant acheminé le spam. Votre serveur deviendrait ce qu'on appelle un relais ouvert (« open relay »). Ce n'est pas ce que vous voulez, parce qu'alors votre serveur se retrouverait sur toutes les listes noires et vous ne pourriez envoyer de mail à pratiquement plus aucun autre serveur. Donc sans preuve que John est réellement John votre serveur doit rejeter ses mails.
Courrier électronique sortant (avec identification)
Donc, comment John prouve-t-il son identité ? Il doit utiliser le SMTP identifié (« authenticated SMTP »). C'est semblable au cas précédent mais le programme de courrier électronique de John enverra aussi son nom d'utilisateur et son mot de passe.
Bien entendu il faut s'assurer que cette identification se fasse via une connexion chiffrée puisqu'elle transmet le mot de passe de John.
Configuration de “mynetworks” Dans Postfix
En plus de l'utilisation de l'identification SMTP vous pouvez dire à Postfix de toujours relayer les mails pour certaines adresses IP. L'option de configuration mynetworks
contient la liste des réseaux IP ou des adresses auxquelles vous faites confiance. Généralement c'est là que vous déclarez votre propre réseau local. La raison pour laquelle John doit s'identifier dans l'exemple ci-dessus est parce qu'il n'envoit pas son mail depuis votre réseau local.
Si vos utilisateurs utilisent l'interface webmail tournant sur votre serveur de mail ils n'ont pas besoin de s'identifier. Roundcube envoit les mails à « localhost » qui est considéré comme étant de confiance dans la configuration de mynetworks
.
Faites en sorte que Postfix utilise Dovecot pour l'identification
Activer l'identification SMTP dans Postfix est étonnamment facile. Vous avez déjà configuré Dovecot pour l'identification des utilisateurs. Il suffit donc de faire en sorte que Postfix l'utilise en lui disant de demander au serveur Dovecot de vérifier le nom d'utilisateur et le mot de passe. Postfix a juste besoin de quelques configurations supplémentaires. Lancez ces commandes dans le shell :
postconf smtpd_sasl_type=dovecot postconf smtpd_sasl_path=private/auth postconf smtpd_sasl_auth_enable=yes
Ceci active l'identification SMTP et dit à Postfix qu'il peut parler à Dovecot via un fichier de socket situé à /var/spool/postfix/private/auth. Vous souvenez-vous que Postfix tourne dans un répertoire transformé en bac à sable avec chroot ? C'est à dire /var/spool/postfix. Pour cela nous avons configuré Dovecot pour qu'il place un socket dans ce répertoire pour pouvoir communiquer avec Postfix.
Activez le chiffrement
La configuration qui suit active le chiffrement, définit la clé et le certificat et oblige à faire passer l'identification par une connexion chiffrée :
postconf smtpd_tls_security_level=may postconf smtpd_tls_auth_only=yes postconf smtpd_tls_cert_file=/etc/letsencrypt/live/webmail.example.org/fullchain.pem postconf smtpd_tls_key_file=/etc/letsencrypt/live/webmail.example.org/privkey.pem
Note 1 : Dans le passé il se peut que vous ayez configuré smtpd_recipient_restrictions pour limiter le relayage aux utilisateurs identifiés. Postfix de nos jours possède une configuration appelée « smtpd_relay_restrictions » qui traite les demandes de relayage dans la phase « RCPT TO » du dialogue SMTP.
En gros il fonctionne comme la restriction smtpd_recipient_restrictions mais est vérifié avant. Et comme cette restriction smtpd_relay_restrictions a une configuration par défaut tout à fait raisonnable, nous n'avons rien à ajouter pour faire fonctionner l'identification pour le relayage.
Note 2 : Postfix 2.10 a modifié le comportement de toutes les restrictions smtpd_*_restrictions. Si une restriction oblige Postfix à rejeter un email, il attendra jusqu'après la ligne RCPT TO. Voyez la documentation de Postifx pour un exposé des raisons de ce changement.
Le paramètre smtpd_tls_security_level est défini à « may » (ndt : c'est à dire possible) pour permettre les connexions chiffrées quand Postfix reçoit un mail. Cela ne s'applique pas seulement aux utilisateurs envoyant des mails, mais aussi aux serveurs de mail distants quand ils vous envoient des mails. Il serait tentant de modifer cela pour mettre « encryt » ce qui forcerait le chiffrement et rejetterait toute tentative de création d'une connexion SMTP non chiffrée. Mais hélas il reste dans le monde des serveurs de mail qui ne peuvent chiffrer et qui, du coup, ne pourraient vous envoyer de mails. Donc « may » est la valeur appropriée.
Bien que des mails puissent toujours vous être envoyés non chiffrés depuis d'autres serveurs il nous faut nous assurer que les utilisateurs, que ce soit par accident ou par ignorance, ne puissent en aucun cas envoyer leurs mots de passe en clair sur Internet. C'est pourquoi nous forçons l'utilisation du chiffrement pour l'identification par smtpd_tls_auth_only=yes. Nous devrions maintenant être tranquilles.
Comment l'identification SMTP fonctionne-t-elle ?
Êtes-vous curieux de voir comment fonctionne l'identification SMTP dans le détail du protocole ? Regardons comment cela se passe. Dans les versions précédentes de ce guide nous utilisions telnet pour nous connecter au port 25 TCP et parler SMTP. Mais maintenant nous forçons l'utlisation du chiffrement et nous ne pouvons réaliser d'identification SMTP non chiffrée. Voyons déjà la première partie en clair :
telnet localhost smtp
Le serveur vous laisse vous connecter :
Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 220 mail ESMTP Postfix (Debian/GNU)
Envoyez-lui un « hello »
ehlo example.com
Postfix présente une liste des options disponibles durant le dialogue SMTP :
250-mailtest 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-STARTTLS 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN
Laissez-moi vous expliquer brièvement ce que signifient ces lignes :
- PIPELINING
- Il s'agit d'une fonctionnalité destinée à accélérer la connexion SMTP. Normalement un système distant doit attendre une réponse à chaque commande qu'il envoit. Le pipelining autorise le serveur distant à envoyer des paquets de commandes sans attendre la réponse. Postfix va juste mettre ces commandes en attente et les exécuter une à une. Si vous dites à Postfix d'interdire le pipelining il déconnectera le serveur distant quand il essayera d'envoyer des paquets de commandes sans attendre la réponse appropriée. C'est essentiellement une fonction orientée contre les programmes de spam qui ne se comportent pas comme le demande le protocole.
- SIZE 10240000
- Le serveur est autorisé à envoyer des mails jusqu'à une taille de 10 MB. Cette taille a été pendant longtemps une taille maximale courante. Cependant de nos jours 40 MB ou même davantage sont des tailles courantes parce que les tailles de mails n'ont cessé d'augmenter.
Note du traducteur : dans ce cas, pour par exemple une taille de 40 Mo, il faudrait taper la commande :
postconf -e message_size_limit=40960000
- VRFY
- Autorise les serveurs distants à vérifier un nom ou une adresse mail. Par exemple le serveur distant pourrait envoyer une commande VRFY john et votre serveur pourrait répondre 250 John Doe <john@example.org>”. Cela sert à vérifier si une adresse mail accepte du courrier.
- ETRN
- Une commande qu'un serveur distant peut envoyer pour vider la file d'attente de Postfix pour un domaine donné. Elle sert si le système distant a eu des problèmes techniques et n'a pas pu recevoir de mails pendant un assez long délais. A la remise en service il peut lancer une commande ETRN pour demander que votre serveur commence à envoyer les mails en attente pour les domaines qu'il gère. C'est une commande qui n'est pas couramment utilisée.
- STARTTLS
- Informe le serveur distant qu'il doit passer de sa connexion en clair à une connexion chiffrée lorsqu'il reçoit cette commande STARTTLS. Il commencera alors à négocier une connexion TLS chiffrée. Vous pouvez comparer cela à une connexion HTTP qui soudain bascule sur une connexion chiffrée HTTPS. L'avantage est que vous pouvez initier une connexion en SMTP sur le port 25 TCP et n'avez pas à ouvrir un deuxième port comme 465 qui est le port SSMTP (secure SMTP) qui n'accepte que les connexions chiffrées.
- ENHANCEDSTATUSCODES
- Ceci active davantage de codes de retour à trois chiffres liés à différentes situations. Voyez la RFC2034 si vous êtes curieux.
- 8BITMIME
- Dans ses débuts SMTP ne traitait que des caractères codés sur 7 octets. Vous ne pouviez transmettre des caractères comme « Ä » ou « ß » sans utiliser un encodage spécial. 8BITMIME autorise la transmission de mails utilisant des caractères codés sur 8 octets. Encore de nos jours de nombreux mails sont spécifiquement encodés en ISO8859-1 ou en UTF-8.
- DSN
- Active les DSNs (delivery status notifications ou notifications de statut de distribution) qui permettent à l'envoyeur de contrôler les messages que Postfix crée quand un email ne peut être distribué comme prévu.
Cependant il manque ici une ligne importante qui nous autoriserait à envoyer notre nom d'utilisateur et notre mot de passe :
250-AUTH PLAIN LOGIN
Nous avons dit à Postfix de ne permettre l'identification que quand la connexion est chiffrée. C'est pourquoi nous ne proposons pas d'identification lors de cette connexion en clair.
Vous suivez toujours ? C'est bien. Maintenant nous avons besoin d'une connexion chiffrée utilisant TLS. Vous pouvez lancer STARTTLS :
STARTTLS
Et le serveur devrait répondre :
220 2.0.0 Ready to start TLS
Cependant à partir de maintenant les choses se compliquent car il faudrait parler en langage chiffré TLS, qui n'est pas un langage que peuvent parler les humains. Donc arrêtons là en utilisant la commande « QUIT ».
Mais nous pouvons utiliser OpenSSL pour nous aider dans le déchiffrement. Lancez la commande :
openssl s_client -connect localhost:25 -starttls smtp
Vous allez voir beaucoup de lignes s'afficher à l'écran. OpenSSL s'est connecté sur le port 25 TCP et a lancé une commande STARTTLS pour basculer dans une connexion chiffrée. Du coup, tout ce que vous taperez maintenant sera chiffré. Entrez :
ehlo example.com
Postfix va envoyer une liste d'options possibles qui va ressembler à ça :
250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-AUTH PLAIN LOGIN 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN
Maintenant que nous utilisons une connexion chiffrée Postfix propose une méthode d'identification. Du coup envoyons une chaîne d'identification avec un mot de passe encodé en Base64 :
AUTH PLAIN am9obkBleGFtcGxlLm9yZwBqb2huQGV4YW1wbGUub3JnAHN1bW1lcnN1bg==
Le serveur devrait accepter cette identification :
235 2.7.0 Authentication successful
Parfait. Vous êtes identifié par SMTP. Déconnectez-vous de Postfix :
QUIT
Au revoir :
221 2.0.0 Bye
L'identification fonctionne. Bien joué.
Encodage en Base64 des mots de passe
Vous pouvez vous demander où j'ai pris cette longue chaîne incompréhensible qui apparemment contenait l'adresse mail de John et son mot de passe. C'est juste une version encodée (et non chiffrée) en Base64 de la chaîne :
« john@example.org<NULL-BYTE>john@example.org<NULL-BYTE>summersun ».
Une façon de créer cette chaîne est d'utiliser Perl :
perl -MMIME::Base64 -e \ 'print encode_base64("john\@example.org\0john\@example.org\0summersun")';
Une façon plus simple est d'utiliser la commande base64 du shell :
$ echo -n 'john@example.org john@example.org summersun' | base64 am9obkBleGFtcGxlLm9yZyBqb2huQGV4YW1wbGUub3JnIHN1bW1lcnN1bg==
Le port d'envoi
Bien que j'aie toujours mentionné le port 25 comme port SMTP pour relayer les mails il existe une meilleure solution en utilisant le port d'envoi (submission port) sur le port 587 TCP (comme décrit dans la RFC4409). L'idée est d'utiliser le port 25 pour le transport des mails (MTA) de serveur à serveur et le port 587 pour l'envoi de mails (MSA) d'un utilisateur à un serveur. Comme de nombreux utilisateurs utilisent toujours le port SMTP par défaut, il y a de grandes chances pour que vous deviez utiliser les deux ports.
Éditez votre fichier /etc/postfix/master.cf et ajoutez un service pour le port d'envoi comme ceci (n'oubliez pas l'indentation à partir de la deuxième ligne). N'utilisez pas les commandes suggérées en commentaire dans le fichier master.cf, contentez vous de les ignorer.
submission inet n - - - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_sasl_type=dovecot -o smtpd_sasl_path=private/auth -o smtpd_sasl_security_options=noanonymous -o smtpd_sender_login_maps=mysql:/etc/postfix/mysql-email2email.cf -o smtpd_sender_restrictions=reject_sender_login_mismatch -o smtpd_sasl_local_domain=$myhostname -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject
Essentiellement ce nouveau service utilise le démon smtpd qui est la brique logicielle qui répond si vous ouvrez une connexion SMTP sur le port TCP 25. Mais avec quelques options supplémentaires…
- Il indique dans le fichier /var/log/mail.log les connexions au port d'envoi sous l'appellation « postfix/submission/smtpd » (syslog) ;
- rend obligatoire le chiffrement sur ce port (security level) ;
- rend obligatoire l'authetification (sasl) ;
- s'assure qu'un utilisateur identifié ne puisse envoyer de mails que sous son propre nom (sender_login_maps).
Redémarrez le serveur Postfix :
service postfix restart
Vos utilisateurs peuvent maintenant utiliser le port d'envoi (submission port) pour envoyer leurs mails.
Protection contre les adresses d'expéditeur contrefaites
Attendez une minute. Nous pouvons nous assurer qu'un utilisateur ne peut envoyer de mails qu'en utilisant sa propre adresse. C'est bien, mais comment cela fonctionne-t-il ? Jetons un oeil sur cette ligne que nous venons d'ajouter lorsque nous avons ajouté le port d'envoi :
smtpd_sender_login_maps=mysql:/etc/postfix/mysql-email2email.cf
L'option smtpd_sender_login_maps est un « mapping » Postfix avec deux colonnes :
- L'adresse email que l'utilisateur veut utiliser pour envoyer son mails ;
- Le nom d'utilisateur qu'il a utilisé lors de son identification auprès du serveur de mail.
La raison pour laquelle j'utilise le mapping /etc/postfix/mysql-email2email.cf est qu'il convient ici parfaitement. Ce mapping lie l'adresse à elle-même si elle existe. Cela vous trouble ? Regardez la requête SQL qu'utilise le mapping « email2email » :
SELECT email FROM virtual_users WHERE email='%s'
De la sorte, lorsqu'un utilisateur veut faire relayer un mail, Postfix interroge la table virtual_users à la recherche de l'adresse de l'utilisateur. Disons que John veut envoyer un mail depuis son adresse « john@example.org ». Postfix recherchera sans la table virtual_users pour voir si il y a une ligne avec un champ « email » qui contienne cette adresse. Il va en trouver une et récupérer la valeur du champ « email », qui n'est autre, rappelons-le, que l'adresse mail. Postfix s'attend à récupérer comme nom d'utilisateur celui qui a été utilisé pour la connexion. Comme nous utilisons l'adresse email en guise de nom d'utilisateur pour la connexion, ce mapping fonctionne. Si John voulait utiliser une autre adresse d'expéditeur, alors Postfix verrait qu'elle ne correspond pas à ce compte et rejetterait le mail. Votre fichier mail.log comporterait une ligne dans ce genre :
NOQUEUE: reject: RCPT from foo.bar[…]: 553 5.7.1 <forged@email.address>: Sender address rejected: not owned by user john@example.org; from=<forged@email.address> to=<…>
A vous de choisir si vous désirez utiliser l'option smtpd_sender_restrictions de cette façon.