1ère étape : mise en place de mots de passe chiffrés avec SASL

On part du principe que vous avez déjà un serveur Postfix fonctionnel sur une machine Debian Lenny. Dans notre configuration, tous les clients (même ceux du réseau local) devront s'authentifier en SASL pour envoyer des messages électroniques. Seul les processus de la machine locale pourront se connecter au serveur SMTP sans authentification.

Installez les paquets suivants :

aptitude install libsasl2-modules sasl2-bin

Dans le fichier /etc/postfix/main.cf, ajoutez les lignes suivantes :

# Active l'authentification SASL sur le serveur.
smtpd_sasl_auth_enable = yes
# Options de sécurité SASL.
smtpd_sasl_security_options = noanonymous, 
   noplaintext
# Domaine d'authentification SASL
smtpd_sasl_local_domain = $myhostname
# Nom du fichier de configuration SASL. 
# L'extension .conf est ajoutée automatiquement.
smtpd_sasl_path = smtpd

# Restrictions appliquées aux clients du serveur.
smtpd_client_restrictions = permit_sasl_authenticated, 
   reject

# Restrictions appliquées aux destinataires.
smtpd_recipient_restrictions = permit_mynetworks,
   reject_unauth_destination

Vérifiez que les paramètres suivants sont définis :

myhostname = mail.exemple.net
mydomain = exemple.net
mynetworks = 127.0.0.0/8  192.168.0.0/24

Créez le fichier /etc/postfix/sasl/smtpd.conf et placez-y les lignes suivantes :

pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: digest-md5 cram-md5

Les mots de passe utilisés par SASL sont stockés dans une base de données créée lors de l'installation du paquet. Ajoutez un utilisateur et définissez son mot de passe :

saslpasswd2 -c -u mail.exemple.net -a smtpauth alex

Le nom de domaine indiqué doit correspondre à la valeur du paramètre myhostname définie dans le fichier de configuration de Postfix si smtpd_sasl_local_domain a la valeur $myhostname dans Postfix.

La commande sasldblistusers2 permet d'afficher la liste des utilisateurs enregistrés dans la base de données de SASL, /etc/sasldb2. Cette dernière doit être lisible par Postfix, nous allons donc modifier les autorisations :

chmod root.sasl /etc/sasldb2
adduser postfix sasl

Sur Debian, Postfix est confiné (chrooted) pendant son exécution. Nous allons donc placer la base de données SASL dans la cellule chroot. (Vérifiez ensuite que les autorisations ont bien été préservées, ça peut éviter bien des problèmes.)

cp -p /etc/sasldb2 /var/spool/postfix/etc/sasldb2
ls -l /var/spool/postfix/etc/sasldb2

Redémarrez Postfix et regardez ce qui apparaît dans le journal du système.

/etc/init.d/postfix restart
tail -10 /var/log/syslog

Essayez de dialoguer avec le serveur SMTP en telnet :

telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.exemple.net ESMTP Postfix (Debian/GNU)
EHLO toto.exemple.net
250-mail.exemple.net
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH CRAM-MD5 DIGEST-MD5
250-AUTH=CRAM-MD5 DIGEST-MD5
250 8BITMIME
quit
221 Bye
Connection closed by foreign host.

Vous devriez voir des lignes du type AUTH CRAM-MD5 DIGEST-MD5.

Essayez d'envoyer un message à l'aide d'un client de messagerie, comme Thunderbird. Dans Thunderbird, choisissez Tools > Account settings > Outgoing Server (SMTP), cochez la case Use name and password et indiquez le nom défini précédemment dans le champ User Name (alex, dans cet exemple).

N'activez pas l'option Use secure connexion, puisque nous n'avons pas encore paramétré TSL/SSL.

Envoyez un message et regardez ce qui apparaît dans le journal du système. Si le message est accepté, vous devriez voir des lignes du type :

Jul 29 17:23:15 p400 postfix/smtpd[2217]: 
connect from toto.exemple.net[192.168.0.5]
Jul 29 17:23:15 p400 postfix/smtpd[2217]: 
B4C61316: client=toto.exemple.net[192.168.0.5], 
sasl_method=CRAM-MD5, 
sasl_username=alex@mail.exemple.net

2ème étape : chiffrement des connexions avec TLS

A ce stade, les mots de passe ne circulent plus en clair sur le réseau. Nous allons maintenant utiliser TLS pour chiffrer l'ensemble des connexions.

Nous allons avoir besoin de certificats cryptographiques. Pour éviter d'acheter un certificat à une autorité de certification, on peut créer un certificat de serveur autosigné, ou générer un certificat d'autorité de certification (Certification Authority, CA) et créer ensuite un certificat de serveur signé avec ce certificat de CA. Dans cet exemple, je vais générer un certificat d'autorité, qui nous resservira pour d'autres manipulations dans le suite de ce document. Ces opérations font l'object d'un autre document.

La version de Postfix proposée par Debian Lenny prend en charge TLS. Il n'est plus nécessaire d'installer un paquet spécial, comme à l'époque de Sarge.

aptitude install openssl

Après génération des certificats, on va avoir besoin de deux fichiers :

  • La clef publique du serveur SMTP (appelée certificat).
  • La clef privée de ce serveur.

Je place les clefs dans /etc/postfix/ssl. Elles appartiennent à root (utilisateur) et à postfix (groupe). Seuls l'utilisateur et le groupe peuvent les lire.

/etc/postfix/ssl# ls -l
total 12
-rw-r----- 1 root postfix 3228 jan  7 16:01 mail.exemple.net-cert.pem
-rw-r----- 1 root postfix  887 jan  7 16:01 mail.exemple.net-key.pem

Dans le fichier /etc/postfix/main.cf, ajoutez les lignes suivantes :

# Propose une connexion TLS
smtpd_use_tls = yes
# Impose une connexion TLS
smtpd_enforce_tls = yes
# Interdit l'authentification sans connexion chiffrée.
smtpd_tls_auth_only = yes
# Clé du serveur
smtpd_tls_key_file = /etc/ssl/private/mail.exemple.com-key.pem
# Certificat du serveur
smtpd_tls_cert_file = /etc/ssl/mail.exemple.com-cert.pem
# Ajout des infos TLS dans l'en-tête des messages envoyés
smtpd_tls_received_header = no
# L'ouverture de la connexion TLS apparaît dans le journal
smtpd_tls_loglevel = 1

Dans un client de messagerie, activez le mode TLS. Dans Thunderbird, choisissez Tools > Account Settings > Outgoing Server (SMTP) > Use secure connection: TLS.

Redémarrez Postfix, envoyez un message à l'aide du client de messagerie et regardez dans le journal du système. Vous devriez voir des lignes du type :

Jan  7 16:30:17 p400 postfix/smtpd[4143]: 
connect from toto.exemple.net[192.168.0.5]
Jan  7 16:30:17 p400 postfix/smtpd[4143]: 
setting up TLS connection from toto.exemple.net[192.168.0.5]
Jan  7 16:30:17 p400 postfix/smtpd[4143]: 
Anonymous TLS connection established from 
toto.exemple.net[192.168.0.5]: 
TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)

Si le certificat du serveur de messagerie est autosigné ou est signé par une autorité inconnue (vous-même, par exemple), un message du logiciel de messagerie devrait signaler qu'il ne peut pas être vérifié. Pour faire disparaître ce message, deux solutions : vous pouvez accepter temporairement/définitivement le certificat du serveur, ou importer dans le logiciel le certificat (clé publique) de l'autorité de certification (dans Thunderbird : Tools > Options > Certificates > View Certificates > Authorities > Import).

3ème étape : authentification des clients à l'aide de certificats

Si ça ne vous suffit pas, vous pouvez identifier les clients à l'aide de certificats. Pour commencer, créez ces certificats de client et signez-les avec la clef privée de l'autorité de certification (voir cette documentation).

Importez le certificat de client dans un logiciel de messagerie (dans Thunderbird : Tools > Options > Certificates > View Certificates > Your certificates > Import).

Sur le serveur Lenny, placez le certificat du CA dans le dossier contenant les certificats du serveur SMTP. Bien entendu, Postfix doit y avoir accès en lecture.

-rw-r----- 1 root postfix 1728 jan  7 16:01 exemple-ca-cert.pem

Dans /etc/postfix/main.cf, modifiez le paramètre smtpd_client_restrictions :

smtpd_client_restrictions = permit_tls_all_clientcerts, 
   reject

L'option permit_tls_all_clientcerts autorise le client à envoyer des messages électroniques dès lors que son certificat de client a été authentifié par le serveur. Dans le même fichier, ajoutez les lignes suivantes :

# Fichier de l'autorité de certification
smtpd_tls_CAfile = /etc/postfix/ssl/exemple-ca-cert.pem
# Demander un certificat au client SMTP qui se connecte.
smtpd_tls_ask_ccert = yes
# Quand le chiffrement TLS est obligatoire, le client SMTP doit
# produire un certificat client pour établir la connexion TLS.
smtpd_tls_req_ccert = yes

Redémarrez Postfix. Envoyez un courrier électronique à l'aide de Thunderbird. Un message vous demande de sélectionner le certificat de client à utiliser pour établir la connexion au serveur SMTP. (J'ai l'impression qu'il apparaît au moins une fois par session dans Thunderbird 2, ce qui est un peu agaçant.)

Vérifiez le résultat dans le journal du système :

Jan  7 17:18:30 p400 postfix/smtpd[4540]:
connect from toto.exemple.net[192.168.0.5]
Jan  7 17:18:30 p400 postfix/smtpd[4540]:
setting up TLS connection from toto.exemple.net[192.168.0.5]
Jan  7 17:18:36 p400 postfix/smtpd[4540]:
toto.exemple.net[192.168.0.5]:
Trusted: subject_CN=Nom du client, issuer=Autorité de certification, fingerprint=9A:8F:44:98:4A:6C:5C:6B:CA:34:7C:06:2B:2D:3A:24
Jan  7 17:18:36 p400 postfix/smtpd[4540]:
Trusted TLS connection established 
from toto.exemple.net.net[192.168.0.5]:
TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)

4ème étape : filtrage des certificats des clients

Si ça ne suffit toujours pas, vous pouvez filtrer les certificats autorisés à établir une connexion au serveur SMTP. L'option permit_tls_clientcerts n'autorise que les clients dont le certificat est authentifié et dont l'empreinte figure dans une liste (voir le paramètre relay_clientcerts).

Dans /etc/postfix/main.cf, remplacez le paramètre smtpd_client_restrictions par :

smtpd_client_restrictions = permit_tls_clientcerts,
   reject

Dans le même fichier, ajoutez la ligne :

relay_clientcerts = hash:/etc/postfix/relay_clientcerts
smtpd_tls_fingerprint_digest = sha1

Créez le fichier /etc/postfix/relay_clientcerts et placez-y des lignes au format :

9A:8F:44:98:4A:6C:5C:6B:CA:34:7C:06:2B:2D:3A:24     alex

Seule la première partie est prise en compte. Vous pouvez donc mettre un nom d'utilisateur ou un commentaire dans la 2ème partie.

La première partie de la ligne est la signature (hash MD5 ou SHA1) du certificat du client. Pour calculer ce hash, utilisez la commande suivante :

openssl x509 -noout -fingerprint -sha1 -in client-cert.pem

Générez ensuite une base de données avec la commande :

postmap hash:/etc/postfix/relay_clientcerts

Le fichier relayclientcerts.db est généré. Redémarrez Postfix et vérifiez que vous pouvez envoyer un message avec un client de messagerie, comme Thunderbird, dans lequel un des certificats clients cités a été importé.

Si la signature est rejetée, un message apparaît dans le journal du système :

Jan  7 18:50:53 p400 postfix/smtpd[5018]:
connect from toto.exemple.net[192.168.0.5]
Jan  7 18:50:53 p400 postfix/smtpd[5018]:
setting up TLS connection from toto.exemplenet[192.168.0.5]
Jan  7 18:50:56 p400 postfix/smtpd[5018]:
toto.exemple.net[192.168.0.5]:
Trusted: subject_CN=Nom du client, issuer=Autorité de certification, 
fingerprint=9A:8F:44:98:4A:6C:5C:6B:CA:34:7C:06:2B:2D:3A:00
Jan  7 18:50:56 p400 postfix/smtpd[5018]:
Trusted TLS connection established from 
toto.exemple.net[192.168.0.5]:
TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)
Jan  7 18:50:56 p400 postfix/smtpd[5018]:
NOQUEUE: reject: RCPT from toto.exemple.net[192.168.0.5]:
554 5.7.1 <toto.exemple.net[192.168.0.5]>:
Client host rejected: Access denied; 
from=<expéditeur> to=<destinataire> 
proto=ESMTP helo=<[192.168.0.5]>

On voit ici que la connexion sécurisée TLS est établie correctement, mais qu'ensuite le client est rejeté par le serveur.

Voir aussi le paramètre check_ccert_access, qui permet d'affiner le filtrage selon les clients.

Documentation