SMTP authentifié avec Sendmail : SMTP AUTH sur TLS

Quoi de plus pénible que de changer le serveur SMTP dans la configuration de son client de courrier à chaque changement de réseau (maison → gare → entreprise → café → …) quand on pourrait n'utiliser qu'un seul serveur sur tous les réseaux ? En effet, le port TCP 465 — celui utilisé pour SMTPS — est rarement filtré en sortie. Une fois le client de courrier configuré, il ne devrait donc jamais plus avoir à y toucher.

On va configurer le serveur SMTP Sendmail de notre système favori de sorte qu'il accepte les messages des utilisateurs dûment authentifiés (par SMTP AUTH). Et pour authentifier en clair, on va chiffrer les communications en les encapsulant dans une connexion TLS.

Pour commencer, il nous faut compiler Sendmail avec le support de SASL. SASL est une couche logicielle, un peu comme SSL/TLS, qui fournit l'authentification.

Avant de se lancer, il nous faut donc la bibliothèque SASLv2 et le daemon d'authentification. Télécharger les sources ici : http://asg.web.cmu.edu/sasl/. Pour les utilisateurs de pkgsrc, installer les paquets security/cyrus-sasl et security/cyrus-saslauthd avec le support de PAM ie. ajouter dans /etc/mk.conf la ligne :

PKG_OPTIONS.cyrus-saslauthd+=pam

avant la compilation.

Il nous faut aussi une implémentation SSL/TLS ; OpenSSL étant en général installé sur tout système moderne, je ne m'étends pas.

Quand ces bibliothèques sont compilées et installées, il faut activer dans les sources de Sendmail les deux couches SASLv2 et SSL/TLS : dans devtools/Site/site.config.m4, ajouter les lignes :

dnl SASL stuff
APPENDDEF(`confENVDEF', `-DSASL=2')
APPENDDEF(`conf_sendmail_LIBS', `-lsasl2')
dnl OpenSSL stuff
APPENDDEF(`conf_sendmail_ENVDEF', `-DSTARTTLS')
APPENDDEF(`conf_sendmail_LIBS', `-lssl -lcrypto')

Il faut éventuellement indiquer où se trouvent les bibliothèques :

APPENDDEF(`confINCDIRS', `-I/usr/local/include')
APPENDDEF(`confLIBDIRS', `-L/usr/local/lib')

Ceci préparé, compiler Sendmail as usual avec ./Build.

Pour les utilisateurs de pkgsrc, ajouter les lignes :

PKG_OPTIONS.sendmail+=sasl
PKG_OPTIONS.sendmail+=tls

dans /etc/mk.conf avant de compiler le paquet mail/sendmail.

La bibliothèque :

  • attend un fichier de configuration dans le même répertoire que les fichiers binaires (/usr/pkg/lib/sasl2 pour moi),
  • du nom du daemon concerné (Sendmail.conf ici1))
  • et indiquant quelle méthode utiliser pour vérifier les mots de passe.

Ici, c'est le daemon saslauthd(8) qui va se charger de cette tâche.

$ cat /usr/pkg/lib/sasl2/Sendmail.conf
pwcheck_method: saslauthd

Lancer le daemon saslauthd(8)2) :

# saslauthd -a getpwent -d

Ici on a fait le choix de se reposer sur les systèmes d'authentification fournis par le système (/etc/passwd, Kerberos, S/Key, LDAP, …). On aurait pu inverser et indiquer l'option -a pam pour appeler PAM plutôt.

On configure au passage /etc/pam.d/sendmail pour mémoire mais il sera inutilisé dans notre configuration :

# auth
auth            required        pam_nologin.so          no_warn
auth            include         system

Dans le fichier m4(1) servant à construire le fichier de configuration final sendmail.cf, ajouter les lignes :

TRUST_AUTH_MECH(`EXTERNAL PLAIN LOGIN')dnl
define(`confAUTH_MECHANISMS', `EXTERNAL PLAIN LOGIN')dnl
DAEMON_OPTIONS(`Port=25, Addr=127.0.0.1, Name=MTA')dnl
DAEMON_OPTIONS(`Port=587, Addr=127.0.0.1, Name=MSA')dnl
DAEMON_OPTIONS(`Port=465, Name=TLSMTA, M=sa')dnl

puis reconstruire le fichier sendmail.cf avec m4(1) : les deux premières lignes indiquent aux daemons MTA et MSA de n'écouter que sur l'adresse de bouclage (loopback) sur leur ports respectifs ; la dernière ligne indique au MTA d'écouter aussi sur ses (autres) adresses, sur le port TCP 465, celui dédié par l'IANA à SMTPS.

Toujours pour la création de sendmail.cf, ajouter ces lignes :

define(`confCACERT_PATH', `/etc/mail/certs')dnl
define(`confCACERT',      `/etc/mail/certs/cacert.crt')dnl
define(`confSERVER_CERT', `/etc/mail/certs/host.crt')dnl
define(`confSERVER_KEY',  `/etc/mail/certs/host.key')dnl

et dans /etc/mail/certs, ajouter :

  • le certificat host.crt,
  • la clef privéee host.key (attention aux droits sur le fichier !),
  • la chaîne de certificats racine cacert.crt.

Sendmail saura alors où trouver la clef, le certificat associé et la chaîne de certificats racine.

Dans le fichier access, on gère ce qui doit être authentifié et/ou chiffré :

Srv_Features:localhost.localdomain      A L S
Srv_Features:localhost                  A L S
Srv_Features:127.0.0.1                  A L S
Srv_Features:host                       A L S
Srv_Features:                           a l s X B E p

Try_TLS:example.com                     NO
TLS_Ctl:                                ENCR:128

et le reste du fichier ne change pas (règles OK ou RELAY par exemple).

Dans cet exemple, de l'extérieur, seul le port tcp/465 est accessible. Lors de la connexion, tout passe sur TLS (ligne TLS_Ctl) ; un nom d'utilisateur et un mot de passe sont demandés (dernière ligne Srv_Features). La couche SASL les obtient via le système d'authentification du système.

Les drapeaux pour Srv_Features viennent avec SASL :

  • a propose une authentification, A reste silencieux,
  • l demande une authentification, L s'en passe,
  • s propose StartTLS, S reste silencieux.

Les drapeaux *TLS* viennent avec SSL/TLS : localement (dans notre domaine example.com) pas besoin mais chiffrement nécessaire (au moins 128 bits) pour les connexions externes et désactivation de StartTLS (a sur la dernière ligne Srv_Features).

Voilà, les utilisateurs peuvent maintenant passer systématiquement par le serveur SMTP : les connexions entrantes depuis l'extérieur commencent systématiquement par une négociation TLS puis une authentification SMTP AUTH avant d'accepter un message.

Après ces modifications, penser à reconstruire access.db avec makemap(8) et relancer le daemon MTA. Attention toutefois : le routage ou la livraison des messages reste à faire…

Avec tcpdump(8) et Netcat ou telnet(1), tester pour vérifier que la connexion est chiffrée.

On peut aussi utiliser openssl_s_client(1) pour se connecter :

client$ openssl s_client -connect server:465
...

Vérifier alors dans le journal syslog(3) (voir aussi Supprimer les messages inutiles de Sendmail des journaux syslog(3)) que des lignes :

STARTTLS=server, relay=client [1.2.3.4], version=TLSv1/SSLv3, verify=NO, cipher=DHE-RSA-AES256-SHA, bits=256/256
[...]
AUTH: available mech=LOGIN PLAIN, allowed mech=EXTERNAL PLAIN LOGIN

apparaissent bien (éventuellement augmenter l'option LogLevel au moins à 14 ; cela se fait dans sendmail.cf ou en relançant le daemon avec -OLogLevel=14).

Enfin, vérifier qu'un utilisateur inexistant sur le système ne peut pas envoyer de message et, de même, qu'un utilisateur saisissant un mauvais mot de passe ne pas non plus envoyer de message. Tester avec un client de courrier traditionnel ou utiliser la commande openssl(1) avec la sous-commande s_client ; il suffit de savoir encoder une chaîne login\0password\01234 en Base64.


1)
Attention, il y a bien une majuscule à Sendmail.conf
2)
Penser à activer le daemon au lancement du système : /etc/rc.d et /etc/rc.conf pour les uns, /etc/init.d et ses amis pour les autres, /etc/rc.local pour d'autres…
  • user/pc/sysadmin/sendmail-smtps-auth.txt
  • Dernière modification : 2011/08/29 22:20
  • de pc