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.
Installation des paquets pré-requis
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.
Configurer SASL
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
Configurer Sendmail
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.
Chiffrement SMTP avec TLS
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.
Authentification SMTP chiffrée
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…
Journaux et tests
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.