====== Authentification SASL dans Postfix ======
{{tag>postfix sasl tls cyrus smtp}}
Jusque très récemment, je n'avais pas le besoin d'envoyer d'emails depuis autre chose que le webmail de linuxwall. Sauf que, avec le déblocage des accès SMTP/IMAP sur les forfaits Illimitics de SFR, je peux maintenant utiliser mon Windows Mobile 5 (oui oui je sais) pour consulter et envoyer des mails.
Mais pour cela, il faut que Postfix m'y autorise. Hors de question d'ouvrir le relaying sur Postfix, ma règle //mynetworks// restera positionné sur les adresses du réseau local.
La solution, c'est donc d'activer l'authentification des clients, via SASL, et d'autoriser le relaying aux clients authentifiés. C'est parti.
===== SASL, mon amour =====
Dans ce tuto, je part du principe que l'implémentation de Cyrus-SASL est fonctionnelle. Pour ma part, Cyrus-SASL s'appuie sur PAM qui prend comme référentiel LDAP ([[http://wiki.linuxwall.info/doku.php?id=ressources:articles:pam_ldap|voir ici]]).
Toutefois, pour que Postfix et Cyrus-SASL puissent fonctionner ensemble, il faut que ce dernier dispose son socket dans un répertoire de Postfix. Sur ma Debian Lenny, ce répertoire est **/var/spool/postfix/var/run/saslauthd**, alors que le répertoire par défaut du socket saslauthd est **/var/run/saslauthd**.
Il faut donc modifier le fichier **/etc/default/saslauthd**, qui contient les options de lancement du daemon, comme suis :
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd -O /etc/saslauthd.conf"
L'option '-m' correspond à :
-m path
Use path as the pathname to the named socket to listen on for connection requests. This must be an absolute pathname, and MUST NOT include the trailing "/mux".
Note that the default for this value is "/var/state/saslauthd" (or what was specified at compile time) and that this directory must exist for saslauthd to function.
Avec ca, Postfix pourra accèder à saslauthd. Ce chemin correspond à celui utilisé sur Debian Lenny, ca peux changer d'une distrib à l'autre.
Après avoir relancé saslauthd, on voit que les fichiers sont présents dans le nouveau répertoire :
# /etc/init.d/saslauthd restart
Stopping SASL Authentication Daemon: saslauthd.
Starting SASL Authentication Daemon: saslauthd.
# ls -al /var/spool/postfix/var/run/saslauthd/
total 940
drwx--x--- 2 root sasl 4096 mar 14 16:02 .
drwxr-xr-x 3 root root 4096 mar 14 14:09 ..
-rw------- 1 root root 0 mar 14 16:02 cache.flock
-rw------- 1 root root 945152 mar 14 16:02 cache.mmap
srwxrwxrwx 1 root root 0 mar 14 16:02 mux
-rw------- 1 root root 6 mar 14 16:02 saslauthd.pid
===== Let's rock Postfix =====
Comme toujours avec Postfix, la conf se situe dans le fichier **main.cf**.
Ce que je souhaite mettre en place ici, c'est une authentification obligatoire lorsque le client ne se trouve pas sur un réseau autorisé.
==== Restrictions ====
La première chose à faire est de transcrire cela dans la politique de Postfix, via la directive //smtpd_recipient_restrictions// (la directive est [[http://www.postfix.org/postconf.5.html#smtpd_recipient_restrictions|définit ici]]). Cette directive définit les contrôles d'accès que Postfix applique à la commande **RCPT TO** envoyée par un client.
smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination,check_policy_service inet:127.0.0.1:60000
Je vous recommande __vivement__ la lecture de la documentation de cette fonction, car son utilisation est lourde d'implications sur la sécurité d'un serveur mail, et il faut donc en comprendre le mécanisme.
La règle importante : "Restrictions are applied in the order as specified; the first restriction that matches wins."
Donc, dans le détail, ce que nous venons de déclarer veut dire :
- permit_sasl_authenticated : la requête est autorisée si le client est correctement authentifié
- permit_mynetworks : la requête est autorisée lorsque l'adresse IP du client fait partie des réseaux listés dans //mynetworks//
- reject_unauth_destination : rejette la requête à moins que Postfix ne soit le destinataire ou le relais du message. Ceci est vérifié de deux facons, soit le domaine dans la requête **RCPT TO** est listé dans //relaydomains//, soit il est listé dans //mydestination//.
- check_policy_service : détermine, si besoin, le serveur qui sera interrogé pour vérifier l'adéquation du message avec la politique. En l'occurence, c'est [[http://postgrey.schweikert.ch/|PostGrey]] qui est derrière.
==== SMTP AUTH ====
Bien, maintenant on peut attaquer le coeur du sujet : SMTP AUTH. Cette méthode est décrite dans la [[http://tools.ietf.org/html/rfc4954|RFC 4954]].
La RFC définie un mot clé, AUTH, qui peut être utilisé par un client. Il prend comme premier argument la méthode SASL qui sera utilisée pour l'authentification.
__ATTENTION__: lorsque saslauthd se base sur PAM, seules les méthodes PLAIN et LOGIN sont utilisables. Les autres méthodes provoqueront un message du type :
SASL DIGEST-MD5 authentication failed: authentication failure
A la connexion d'un client, le serveur Postfix annonce les méthode AUTH qu'il supporte. Dans notre cas, on veut donc PLAIN et LOGIN car ce sont les seuls supportés par PAM. La configuration dans le main.cf va donc donner :
# vim main.cf
[...]
smtpd_sasl_auth_enable = yes
smtpd_sasl_path = smtpd
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $mydomain
smtpd_sasl_authenticated_header = yes
smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination,check_policy_service inet:127.0.0.1:60000
Un peu d'explication :
* smtpd_sasl_auth_enable: active l'authentification SASL pour le daemon smtpd
* smtpd_sasl_path: détermine l'emplacement du fichier contenant les paramètres SASL. La construction de ce chemin est la suivante : le chemin par défaut est **/etc/postfix/sasl/[VARIABLE].conf** . En déclarant 'smtpd', on s'attend donc a trouver un fichier 'smtpd.conf' dans ce répertoire. Nous reviendrons sur ce fichier ultérieurement.
* smtpd_sasl_security_options: c'est une restriction sur les méthodes SASL qui seront autorisées. Ici, on interdit les méthodes de type anonyme.
* smtpd_sasl_local_domain: le nom du domaine d'authentification SASL
* smtpd_sasl_authenticated_header: fait apparaitre le status d'authentification dans le header de l'email envoyé
* et enfin, les restrictions que nous avons vu précédemment.
Concernant le fichier **smtpd.conf**, ce dernier est des plus simpliste :
# SASL method for postfix
pwcheck_method: saslauthd
mech_list: PLAIN LOGIN
Je ne m'attarde pas dessus. Maintenant, il faut recharger la nouvelle configuration de postfix :
root@zerhuel:/etc/postfix# postfix reload
postfix/postfix-script: refreshing the Postfix mail system
root@zerhuel:/etc/postfix# tail -n 2 /var/log/mail.info
Mar 14 17:13:48 zerhuel postfix/postfix-script[28246]: refreshing the Postfix mail system
Mar 14 17:13:48 zerhuel postfix/master[23006]: reload configuration /etc/postfix
Tout va bien.
==== Le test ====
__Avant de tester__, il reste une dernière subtilité. Si, comme moi, vous avez mis en place STARTTLS ([[http://wiki.linuxwall.info/doku.php?id=ressources:dossiers:postfix:smtp_tls|comme expliqué ici]]), vous avez certainement positionné l'option suivante :
smtpd_tls_auth_only = yes
et, de fait, lorsque vous allez tester votre nouvelle configuration, le serveur ne déclarera pas la méthode AUTH. Pire, il vous enverra voir ailleurs :)
# nc localhost 25
220 smtp.linuxwall.info
ehlo mail
250-zerhuel.linuxwall.info
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
AUTH
504 5.5.4 Encryption required for requested authentication mechanism
quit
221 2.0.0 Bye
Et oui, pas de méthode AUTH sans STARTTLS préalable (quand on fait du PLAIN, c'est indispensable). La solution, pour tester en ligne de commande, est donc de passer par le client SSL de OpenSSL avec l'option //starttls// :
# openssl s_client -connect localhost:25 -starttls smtp
CONNECTED(00000003)
depth=1 /C=FR/ST=France/L=Paris/O=Linuxwall/CN=Linuxwall Certificate Authority Root Certificate/emailAddress=root@linuxwall.info
verify error:num=19:self signed certificate in certificate chain
[BLABLABLA SSL QUI NE NOUS INTERESSE PAS ICI]
Verify return code: 19 (self signed certificate in certificate chain)
---
250 DSN
ehlo mail
250-zerhuel.linuxwall.info
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
quit
221 2.0.0 Bye
read:errno=0
Et cette fois, on voit la méthode **AUTH** apparaitre.
Pour tester l'authentification, prenons un utilisateur qui possède un compte sur le LDAP (et pas ailleurs, ca permet de valider que toute la chaîne fonctionne) : René !
René doit s'authentifier en utilisant une chaine en base 64 contenant son nom d'utilisateur et son mot de passe. On peut générer ca simplement avec Perl :
# perl -MMIME::Base64 -e 'print encode_base64("\0rene\0allerpsg");'
AHJlbmUAYWxsZXJwc2c=
La chaine de sortie doit être utilisée avec la méthode AUTH : **AUTH PLAIN AHJlbmUAYWxsZXJwc2c=**
250 DSN
ehlo mail
250-zerhuel.linuxwall.info
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
AUTH PLAIN AHJlbmUAYWxsZXJwc2c=
535 5.7.8 Error: authentication failed: authentication failure
quit
221 2.0.0 Bye
Arf, c'est dommage, René n'a pas de compte sur mon serveur.... Donc il recoit un code 535.
Si il avait eu un compte, et si l'authentification avait réussie, il aurait recu le code '**235 2.7.0 Authentication successful**'
===== Configuration du client: Thunderbird =====
Mon client mail est thunderbird. Pour configurer ce dernier, il suffit d'aller dans les préférences du compte, puis dans la section "Server SMTP Sortant", et de régler le paramètrage comme suis :
{{ressources:dossiers:postfix:thunderbird_smtp.jpg|}}
===== Et dans les traces ? =====
Lorsqu'un email est envoyé au travers de ce serveur, le destinataire recevra les informations suivantes dans les headers :
Received: from [192.168.1.20] (unknown [192.168.1.20])
(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
(Client CN "Julien Vehent", Issuer "Linuxwall Certificate Authority Root Certificate" (verified OK))
(Authenticated sender: julien@linuxwall.info)
by zerhuel.linuxwall.info (Postfix) with ESMTPSA id AA4A1EBB1A
for ; Sat, 14 Mar 2009 17:47:53 +0100 (CET)
La ligne ajoutée par l'option //smtpd_sasl_authenticated_header// ajoutée plus haut dans la configuration est **Authenticated sender**.
Et sur le serveur, on verra la ligne suivante :
Mar 14 17:47:53 zerhuel postfix/smtpd[29238]: AA4A1EBB1A: client=unknown[192.168.1.20], sasl_method=PLAIN, sasl_username=julien@linuxwall.info
That's all, Folks ;)
~~DISCUSSION~~