Authentification SASL dans Postfix

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 :

  1. permit_sasl_authenticated : la requête est autorisée si le client est correctement authentifié
  2. permit_mynetworks : la requête est autorisée lorsque l'adresse IP du client fait partie des réseaux listés dans mynetworks
  3. 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.
  4. 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~~

fr/ressources/dossiers/postfix/authentification_sasl.txt · Last modified: 2011/03/16 01:41 (external edit)
CC Attribution-Noncommercial-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0