Table of Contents
Authentification SASL dans Postfix
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 (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 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 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 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 (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 :
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 <julien.vehent@gmail.com>; 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~~