Installer un système de mail complet et sécurisé

Benjamin Pineau, ben@reynerie.yi.org

v0.2, 29 Avril 2002


Ce document détaille le processus d'installation d'un serveur de mail le plus complet possible, sur la base de postfix et Washington imap. Le postfix supportera le SSL (TLS), l'authentification SMTP (SMTP AUTH), fera du relais sélectif, filtrera les spams via RBL et filtrera les virus. Le wu-imap fera du pop3, de l'imap, supportera le SSL l'authentification par APOP, Cram MD5 et Digest MD5. Pour finir on y adjoindra un petit webmail. Mots-clés : Postfix AMaViS virus imap SSL TLS SMTP AUTH squirrelmail courrier électronique.

1. Introduction

2. Installation de la librairie SASL

3. Installation de Postfix

4. Créer et signer des certificats pour le SSL

5. Configuration de Postfix

6. Créer les tables et les aliases

7. Installer un scanner antivirus

8. Installer WU IMAP Server

9. Installer le webmail



1. Introduction

1.1 Argument

Ne vous fourvoyez pas : je ne donnerai pas d'explications détaillées ; la doc des logiciels et des protocoles y pourvoira bien mieux. J'indique une série de commandes qui fonctionne sur mes systèmes.

L'objectif est d'installer un serveur de mail avec postfix, de permettre un relais sélectif, filtrant les spams, permettant l'authentification par SMTP AUTH et/ou certificats SSL, permettant le chiffrement par TLS (SSL) et filtrant les virus. On installera aussi un serveur imap/pop3 supportant les méthodes d'authentification sécurisées (cram md5, apop) et le SSL, et un webmail en php.

Problématique du relais
Pour résumer, dites vous qu'un des problèmes importants du SMTP est la gestion du relais. Un serveur smtp bien configuré relaye en général les mails :

La seconde méthode est surtout adaptée aux providers qui veulent relayer leurs clients : ils connaissent déjà toutes les adresses IP qu'ils leurs attribuent. En revanche, cette méthode est insuffisante si l'on veut relayer un certain nombre de machines dont on ne peut pas savoir l'adresse IP à l'avance.
Un serveur SMTP ne doit surtout pas relayer les mails envoyés par un inconnu vers une destination tierce, sans quoi il deviendrait rapidement un outil de torture aux mains des spammers, et serait "black listé" par un grand nombre d'organisations. En effet de nombreux serveurs smtp sont configurés pour refuser de relayer tout mail venant d'un serveur ouvert à tout vents (un "open relay"), grâce à des listes (les dites "blacklists") répertoriant ces serveurs.
Nous verrons comment éviter d'être un relais ouvert tout en permettant à certains utilisateurs d'envoyer du courrier (grâce au protocole d'authentification SMTP et/ou aux certificats SSL), et comment utiliser, nous aussi, les listes anti-spam.

SSL/TLS et SMTP-AUTH
Le SSL permet donc d'authentifier des utilisateurs de façon sûre. En outre, grâce à lui, les échanges sont chiffrées, donc plus confidentielles.
Le SMTP AUTH permet, grâce à la librairie SASL, d'utiliser un couple login/mot de passe pour authentifier les utilisateurs du servie SMTP. Notez que la librairie SASL est difficile à chrooter, et au moment de configurer le fichier master.cf, il faudra, malheureusement, éviter de chrooter les daemons.
Chacune de ces deux méthodes d'authentification est suffisante, mais proposer les deux est souvent intéressant.
Il existe une autre méthode d'authentification, largement utilisée bien qu'il s'agisse d'un bricolage : le pop-before-smtp. Je décrirai cette technique et son implémentation dans postfix dans une version ultérieure de ce document.

Conventions
Voici les conventions adoptées ici:
lignes commençant par "%" : commandes à exécuter sous une uid non privilégiée
lignes commençant par "#" : commandes à exécuter en root (ou, selon le contexte, commentaire)
Et pour les exemples d'échanges serveur/client:
"<": envoi du client.
">": réponse du serveur.

Et voici un exemple typique de session smtp "à la main":

< ben@ici$ telnet localhost 25
> Trying 192.168.1.3...
> Connected to po.reynerie.yi.org.
> Escape character is '^]'.
> 220 reynerie.yi.org ESMTP Plaisir Des Dames
< EHLO mydomain.com
> 250-reynerie.yi.org
> 250-PIPELINING
> 250-SIZE 20480000
> 250-ETRN
> 250-STARTTLS
> 250-AUTH LOGIN PLAIN DIGEST-MD5 CRAM-MD5
> 250-AUTH=LOGIN PLAIN DIGEST-MD5 CRAM-MD5
> 250 8BITMIME
< MAIL FROM: <ben@truc.org>
> 250 Ok
< RCPT TO: <ben.pineau@machin.com>
> 250 Ok
< DATA
> 354 End data with <CR><LF>.<CR><LF>
< From: ben@reynerie.yi.org
< To: ben.pineau@ifrance.com
< Subject: un exemple
<
< voila le contenu de mon mail d'exemple
< .
> 250 Ok: queued as B01B64045
< quit
> 221 Bye
> Connection closed by foreign host.
Vous pourrez utiliser une méthode similaire pour tester votre configuration.

1.2.1 Préparation

1.2.1 Récupérer les sources

Voilà une méthode rapide pour tout récupérer :

% wget ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/cyrus-sasl-1.5.27.tar.gz
% wget ftp://ftp.grolier.fr/pub/mirrors/ftp.porcupine.org/postfix-release/official/postfix-20010228-pl08.tar.gz
% wget ftp://ftp.aet.tu-cottbus.de/pub/postfix_tls/pfixtls-0.7.13-20010228-pl08-0.9.6b.tar.gz
% wget ftp://ftp.cac.washington.edu/imap/imap.tar.Z
% wget http://prdownloads.sf.net/squirrelmail/squirrelmail-1.2.2.tar.gz
% wget http://freshmeat.net/redir/amavis/223/url_tgz/amavis-0.2.1.tar.gz
Vous n'êtes pas obligé d'utiliser les mêmes versions des logiciels, ni cette méthode pour les récupérer. Ce dont vous avez besoins, c'est : la librairie SASL de Cyrus; postfix et le patch TLS correspondant à la version choisie, imapd (la version de l' université de Washington convient bien), et squirrelmail.

1.2.2 Créer les comptes utilisateurs

Ajouter les groupes postdrop et postfix.
Créer l'utilisateur postfix (groupe postfix).
Créer l'utilisateur maildeliver.

Exemple :

#useradd -g nogroup -s /no/shell maildeliver
#groupadd postdrop
#groupadd postfix
#useradd -g postfix -s /no/shell postfix

2. Installation de la librairie SASL

2.1 Installation

Cette librairie est nécessaire pour le SMTP AUTH.

% tar xvzf cyrus-sasl-1.5.27.tar.gz
% cd cyrus-sasl-1.5.27/
% ./configure --enable-login --disable-krb4 --disable-gssapi --disable-anon --with-pwcheck
% make
# make install
# ln -s /usr/local/lib/sasl/ /usr/lib/sasl
# echo 'pwcheck_method: sasldb' > /usr/local/lib/sasl/smtpd.conf

(Attention, c'est bien "pwcheck_method: " et pas "pwcheck_method = ")

2.2 Ajout des utilisateurs à la base sasldb

Le fichier /etc/sasldb contient une liste d'utilisateurs et de mots de passe ; il sera utilisé par postfix pour le SMTP AUTH.
Pour ajouter un couple user/passwd au fichier /etc/sasldb.db, utiliser le logiciel saslpasswd (il s'est installé avec la lib SASL). Cf. la page de man. Par exemple :

# saslpasswd -c -u mondomaine.com exampleuser
Notes:
Voici un exemple de script pour automatiser tout ça. Il utilise passook, un petit logiciel qui génère des mots de passes. Il sauvegarde les mots de passes ajoutés au sasldb dans /root/passwd_users/pass.$user.tmp :
#!/bin/sh
#chez moi les vrais users sont ceux qui ont bash pour shell et une home dans /home :
for user in `grep "/home/.*/bin/bash" /etc/passwd | cut -d : -f 1`
  do
     echo -en "---\nSMTP\nuser: $user mot de passe : " >> /root/passwd_users/pass.$user.tmp
     passook $user | tee -a /root/passwd_users2/pass.$user.tmp | \
                  saslpasswd -c -p -u reynerie.yi.org $user
done

Postfix doit avoir droit de lecture sur le fichier de mots de passe sasl ; il vaudrait mieux qu'il soit le seul :
# chown postfix:nogroup /etc/sasldb*; chmod 600 /etc/sasldb*

3. Installation de Postfix

3.1 Installation

% tar xvzf pfixtls-0.7.13-20010228-pl08-0.9.6b.tar.gz
% tar xvzf postfix-20010228-pl08.tar.gz
On ajoute le patch pour le support SSL/TLS :
% patch -p0 < pfixtls-0.7.13-20010228-pl08-0.9.6b/pfixtls.diff
% cd postfix-20010228-pl08
Commande à adapter aux répertoires d'include et de lib pour openssl et sasl sur votre système :
% make makefiles CCARGS="-DHAS_SSL -I/usr/local/ssl/include -DUSE_SASL_AUTH -I/usr/local/include" AUXLIBS="-L/usr/local/ssl/lib -L/usr/local/lib -lssl -lcrypto -lsasl"
Ou, sous OpenBSD 3.0:
% make makefiles CCARGS="-DHAS_SSL -I/usr/include/ssl/ -DUSE_SASL_AUTH -I/usr/local/include" AUXLIBS="-L/usr/lib/ -L/usr/local/lib -lssl -lcrypto -lsasl"
# make install
Accepter les options proposées, sauf pour set gid [n]? : répondre "postdrop" et pas "no" ou "yes".
(cf. le README dans les sources de postfix au sujet des problèmes de sécurité de la méthode sans sgid).
# mkdir /var/spool/mail
# chmod 1777 /var/spool/mail/
S'assurer que le binaire pointé par le lien /usr/sbin/sendmail soit bien le "sendmail" de postfix (si vous avez opté pour l'installation par défaut, c'est /usr/lib/sendmail).

3.2 Une configuration minimale

Si vous avez déjà un smtpd en production sur la machine, sans doute préférerez vous le laisser tourner pendant vos tests : éditer master.cf et remplacez :

smtp inet n - n - - smtpd
par
1027 inet n - n - - smtpd

Le postfix n'écoutera que les requêtes arrivant sur le port 1027, laissant l'autre smtpd faire son boulot habituel sur le port 25. Vous pourrez remettre la ligne "smtp inet ..." quand vous jugerez votre configuration au point, et, en attendant, faire vos tests avec des telnets sur le port 1027.

Voici la configuration minimale du fichier /etc/postfix/main.cf (à ajuster à votre réseau) :

myhostname = mamachine.mondomaine.com
mydomain = mondomaine.com
myorigin = $mydomain
mynetworks = 192.168.1.0/24, 127.0.0.0/8
mydestination = $myhostname, $mydomain, localhost.$mydomain

Il est aussi bienvenu d'augmenter le niveau de debug durant les tests: Mettre dans main.cf, par exemple :

debug_peer_level = 2
debug_peer_list = $mydomain, 192.168.1.2, 127.0.0.1, 192.168.1.3

3.3 Premier test du service smtp


Assurez vous que les lignes suivantes soient présentes (et dé-commentées) dans /etc/services :
smtp 25/tcp mail
smtps 465/tcp # smtp secure, over TLS/SSL
Tester :
% postfix start
et faites quelques envois de mails.
Regardez les logs. Wietse Wienema recommande ceci :
% egrep '(reject|error|warning|fatal|panic):' /var/log/maillog

4. Créer et signer des certificats pour le SSL

Précisons à ce point qu'un certificat auto signé, ça manque de sérieux. Netscape ou outlook, entre autres, vont vraisemblablement afficher un message de mise en garde lors de la première connexion au site (tant que vous n'aurez pas intégré votre certificat de CA parmi les autorités de confiance de votre client). Mais la signature d'un CA reconnu par microsoft coûte si cher ...

Voir aussi: http://www.dtcc.edu/cs/admin/notes/ssl/ et http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/doc/myownca.html

On prépare le terrain :

% mkdir /tmp/certs && cd /tmp/certs
Trouver openssl.cnf (peut etre dans /usr/local/ssl/ ou dans /etc/openssl/ par exemple) et le sauvegarder dans le répertoire courant :
% cp /path/to/openssl.cnf .
Editer ./openssl.cnf et changer (uniquement ! ne pas toucher au reste du fichier):
On crée une arborescence de répertoires où seront stockés les fichiers du CA (Certificate Authorithy) et les informations relatives :
% mkdir -p CA/newcerts
% touch CA/index.txt
% echo '01' > CA/serial

4.1 Certificats et clef de CA pour le serveur

On génère un certificat (et une clef) de CA (toujours depuis le répertoire /tmp/certs) :

% openssl req -new -x509 -nodes -config ./openssl.cnf -keyout ./CA/CAkey.pem -out ./CA/CAcert.pem -days 3650
Exemple de réponses saisies :
Country Name (2 letter code) [AU]:FR
State or Province Name []: Haute-Garonne
Locality Name (eg, city) []:Toulouse
Organization Name []:Reynerie ltd.
Organizational Unit Name (eg, section) []:
Certificate Service []: Certificate Service
Common Name (eg, YOUR name) []:Reynerie Ltd.
Email Address []:ben@reynerie.yi.org
On teste la validité du certificat de CA :
% openssl x509 -purpose -in ./CA/CAcert.pem -noout

4.2 Certificat et clef pour Postfix

On génère la requête de certificat pour le serveur :

% openssl req -new -nodes -config ./openssl.cnf -keyout key.pem -out sign_request.pem -days 3650
Exemple de réponses saisies. Attention ! il faut que le Common Name du certificat soit le nom canonique du serveur smtp (ici mydomain.com):
Country Name (2 letter code) [AU]:FR
State or Province Name (full name) [Some-State]:Haute-Garonne
Locality Name (eg, city) []:Toulouse
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Test server
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:mydomain.com
Email Address []:ben@mydomain.com
A challenge password []:
An optional company name []:
On signe la requête de certificat serveur avec le certificat de CA :
% openssl ca -config ./openssl.cnf -policy policy_anything -out cert.pem -days 3650 -infiles sign_request.pem
On teste le certificat du serveur :
% openssl x509 -purpose -in cert.pem -noout
On se retrouve avec trois fichiers utiles à postfix : On installe tout ça :
# cp cert.pem key.pem CA/CAcert.pem /etc/postfix/
# chown root /etc/postfix/key.pem; chmod 400 /etc/postfix/key.pem
Sauvegarder le répertoire ./CA (dans la home de root par exemple) : Il nous servira à faire d'autres certificats (pour les clients et/ou pour d'autres services). Il contient entre autres la clef privée du CA qu'il faut protéger en lecture :
# chown root:root ./CA/CAkey.pem
# chmod 0400 ./CA/CAkey.pem
La requête de certification (sign_request.pem) est maintenant inutile, on peut l'effacer.

4.3 Certificats et clefs pour les clients

a) authentification du client par certificats :

On peut faire des certificats pour authentifier les clients.
Ça donnera un 'verified ok' dans les headers des mails :

% openssl req -new -nodes -config ./openssl.cnf -keyout client_sign_request.pem -out client_sign_request.pem -days 3650
% openssl ca -config ./openssl.cnf -cert /etc/postfix/CAcert.pem -policy policy_anything -out client_cert.pem -infiles client_sign_request.pem
On empaquette aussi le certificat et la clef dans un format permettant l'intégration dans un navigateur/MTA :
% openssl pkcs12 -export -nodes -in client_cert.pem -inkey client_sign_request.pem -certfile /etc/postfix/CAcert.pem -name "Name" -out client.p12

Envoyer tout ça à son destinataire pour qu'il l'intègre dans son client smtp (les client*.pem, le certificat du serveur et client.p12).
Si nous voulons authentifier de la même manière (et oui, nous le voulons ;) les clients dont les certificats ne sont pas signés de notre main, nous devons faire ce qui est indiqué à la fin de la section 5.1

b) relais sélectif par authentification par certificat :

Si on veut aussi faire du relais sélectif (autoriser les clients à être relayés s'il présentent leur certificat), reste à faire ceci :

Faire une empreinte digitale du certificat du client :

% openssl x509 -fingerprint -in client_cert.pem -noout > client_fingerprint
On crée un fichier /etc/postfix/certs_clients_a_relayer contenant ceci :
41:6R:8E:45:BA:B2:A2:1C:F0:70:71:69:8F:3F:33:DB client.domaine.ou.user
La première partie est ce qu'on obtient dans le client_fingerprint. La deuxième partie, c'est n'importe quoi, postmap ayant besoin de 2 champs par lignes. Il est cependant judicieux d'y mettre le domaine ou nom d'user à qui correspond le fingerprint. On peut bien sûr ajouter autant de fingreprints qu'on veut à ce fichier, à raison de un par ligne.
Anticipons un peu sur la partie configuration : il nous faudra faire ceci :
# postmap /etc/postfix/certs_clients_a_relayer
ajouter à main.cf :
relay_clientcerts = hash:/etc/postfix/certs_clients_a_relayer
et ajouter
permit_tls_clientcerts
Dans une (ou plus) des smtpd_*_restrictions du main.cf pour autoriser le relais des clients certifiés. Voir la section configuration des restrictions plus bas.

5. Configuration de Postfix

Vim6 est particulièrement pratique pour éditer les fichiers main.cf et master.cf de postfix : la coloration syntaxique aide beaucoup.
La commande "postfix check" permet de tester la syntaxe de la configuration (et quelques autres choses). Il est donc recommandé de lancer cette commande après chaque modification des fichiers de configuration.
La commande "postconf" affiche toute les variables de configurations, et leur valeur actuelle, et l'option "-n" (postconf -n), n'affiche que les variables dont la valeur a été modifiée (par rapport aux valeurs par défaut) dans vos fichiers de conf.
La commande "postalias /etc/postfix/aliases" reconstruit la base d'alias (/etc/postfix/aliases.db) après qu'on ai modifié la version flat texte (/etc/postfix/aliases).
"postmap /etc/postfix/unfichier" idem que postalias mais pour les autres fichiers externes (access etc.).

5.1 Configuration de Postfix pour le TLS

Voici un exemple de conf. Simple mais fonctionnel : (dans main.cf)

smtp_use_tls = yes
smtpd_use_tls = yes

# certificats :
# on peut aussi utiliser des certificats différents
# pour le client smtp et le serveur smtpd
smtpd_tls_key_file = /etc/postfix/key.pem
smtp_tls_key_file = /etc/postfix/key.pem
smtpd_tls_cert_file = /etc/postfix/cert.pem
smtp_tls_cert_file = /etc/postfix/cert.pem
smtpd_tls_CAfile = /etc/postfix/CAcert.pem
smtp_tls_CAfile = /etc/postfix/CAcert.pem

#
smtp_tls_note_starttls_offer = yes
smtpd_tls_loglevel = 1
smtp_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_ask_ccert = yes
smtpd_tls_session_cache_database = sdbm:/etc/postfix/smtpd_scache
smtp_tls_session_cache_database = sdbm:/etc/postfix/smtp_scache
smtpd_tls_session_cache_timeout = 3600
smtp_tls_session_cache_timeout = 3600
smtpd_tls_auth_only = no
smtp_tls_note_starttls_offer = yes

#Dans certs_clients_a_relayer, ajouter l'empreinte digitale du certificat
#des clients qu'on veut relayer. Si le CA ayant signé le certificat
#client n'est pas le même que celui qui a signé le certificat du
#serveur, il faut le rajouter à la suite (le concaténer à) CAcert.pem.
#Cf. plus haut, dans la section 4.3
relay_clientcerts = hash:/etc/postfix/certs_clients_a_relayer

Quelques options de configuration supplémentaires :

5.2 Tester le SMTP sur SSL

Un telnet localhost 25 suivi d'un "ehlo localhost" devrait faire apparaître (entre autres) la ligne : 250-STARTTLS

Tester le wrapped ssl (smtps, port 465) à la main grâce à la commande openssl :

% openssl s_client -connect localhost:465 -state -debug
[...]
220 reynerie.yi.org ESMTP Plaisir Des Dames
EHLO ici
etc... (la connexion se poursuit comme une connexion en clair)

5.3 Configuration du SMTP AUTH

1) Configuration du smtpd pour qu'il authentifie les clients

Ajouter dans main.cf:

smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $mydomain
Précisions : la valeur de "smtpd_sasl_local_domain" doit correspondre au "realm" annoncé lors de la création de la base /etc/sasldb. C'est cette valeur qu'il faut passer à l'option "-u" de la commande "saslpasswd". "broken_sasl_auth_clients" permet de contourner un bug des vieilles versions d'Outlook Express.

2) Pour que postfix puisse utiliser sasl comme client smtp

Donc d'authentifier auprès d'autres serveurs smtp-auth vers lesquels il relaye (et qui, bien entendu, nous fournissent un couple login/pass pour le smtp-auth), il faut définir une base de mot de passe par domaines et l'indiquer dans la conf: (dans main.cf)

smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noplaintext, noanonymous

5.4 Tests du SMTP AUTH

Créez un compte sasl pour les tests (cf. plus haut l'utilisation de saslpasswd).
Produire, à partir des données de ce compte, une chaîne MIME pour les tests :

printf "nom_user\0nom_user\0mot_de_passe" | mmencode
ou bien :
perl -MMIME::Base64 -e 'print encode_base64("username\0username\0password");'
Nous donne une chaîne du type : "ZXhhbXBsZXVzZXIAZXhhbXBsZXVzZXIAdG90bw==" qui nous servira pour nous authentifier "à la main" (telnet localhost 25) par la méthode "plain" :
ben@ici$ telnet pi 25
<Connected to pi.reynerie.yi.org.
<Escape character is '^]'.
<220 reynerie.yi.org ESMTP Plaisir Des Dames
>EHLO ici
<250-pi.reynerie.yi.org
<250-PIPELINING
<250-SIZE 10240000
<250-ETRN
<250-STARTTLS
<250-AUTH LOGIN PLAIN DIGEST-MD5 CRAM-MD5
<250-AUTH=LOGIN PLAIN DIGEST-MD5 CRAM-MD5
<250 8BITMIME
>AUTH PLAIN ZXhhbXBsZXVzZXIAZXhhbXBsZXVzZXIAdG90bw==
<235 Authentication successful
>MAIL FROM: <toto@couac.com>
<250 Ok
>RCPT TO: <ben@hotmail.org>
<250 Ok
>DATA
<354 End data with <CR><LF>.<CR><LF>
[...]

5.5 Configuration des restrictions, anti-spam

En premier lieu, j'ajoute ceci à main.cf :

header_checks = regexp:/etc/postfix/header_check_filters
smtpd_helo_required = yes
allow_untrusted_routing = no
disable_vrfy_command = yes

Ensuite on s'occupe des smtpd_*_restrictions. Ces restrictions concernent les diverses étapes de la session smtp. "smtpd_helo_restrictions" pour contrôler ce qui se passe durant le "EHLO" (ou HELO), "smtpd_client_restrictions" concerne les valeurs de l'adresse ip/nom de domaine réel du client (qui n'est pas forcément l'utilisateur qui envoie le mail, mais peut être un relais quelconque), "smtpd_sender_restrictions" applique des contrôles au moment du "MAIL FROM:" et "smtpd_recipient_restrictions" au moment du "RCPT TO:".

À chaque étape de la connexion smtp, on peut appliquer les contrôles concernant les étapes précédentes mais non l'inverse. Par exemple au moment des "smtpd_recipient_restrictions" on peut tester la valeur du hostname indiquée dans le HELO, mais au moment du HELO on ne peut pas contrôler l'existence du domaine indiqué lors du "RCPT TO:" puisqu'on ne le connaît pas encore.
C'est pourquoi il est judicieux de mettre toutes les restrictions à la dernière étape, c'est à dire dans "smtpd_recipient_restrictions", puisque c'est le moment où l'on dispose de toute la batterie de restrictions.
Les restrictions sont testées dans l'ordre indiqué, de gauche à droite ; dès qu'une condition de restriction est vérifiée, le processus s'arrête, et la requête smtp est rejetée ou acceptée. Voici ma conf :

#smtpd_helo_restrictions =  
#smtpd_client_restrictions = 
#smtpd_sender_restrictions = 

smtpd_recipient_restrictions = 
   reject_unknown_sender_domain, 
   reject_unknown_recipient_domain, 
   permit_mynetworks, 
   permit_sasl_authenticated,
   permit_tls_clientcerts, 
   reject_unauth_destination, 
   check_recipient_access regexp:/etc/postfix/access_by_recipient_regexp, 
   check_recipient_access hash:/etc/postfix/access_by_recipient_hash, 
   check_sender_access    regexp:/etc/postfix/access_by_sender_regexp, 
   check_sender_access    hash:/etc/postfix/access_by_sender_hash, 
   check_client_access    hash:/etc/postfix/access_by_client_hash, 
   reject_unauth_pipelining, 
   reject_invalid_hostname, 
   reject_non_fqdn_hostname, 
   reject_maps_rbl, 
   reject_unknown_client, 
   permit 
Ce qui signifie, dans l'ordre:
Pour pouvoir utiliser les blacklists RBL, il nous faut, quelque part dans main.cf :

maps_rbl_domains =
  blackholes.mail-abuse.org,
  relays.mail-abuse.org,
  outputs.orbz.org,
  relays.ordb.org,
  relays.osirusoft.com,
  zta.birdsong.org,
  spammers.v6net.org
C'est une liste de serveurs RBL que postfix interrogera pour chaque client afin de savoir s'il est un relais (trop) ouvert.

5.6 Autres astuces de configuration

5.6.1 Limiter les ressources

Un utilisateur mal intentionné dispose de nombreuses techniques pour saturer les ressources de votre machine ou simplement du service SMTP (on parle de "Déni de Service", ou DoS : envoi d'un très grand nombre de mails simultanément, de très gros mails ...
Postfix, gloire à lui, permet de gérer ce problème de façon très fine. Je vous recommande de recopier le contenu du fichier /etc/postfix/sample-resssouces dans main.cf et de positionner les différentes variables à votre convenance.
Il est particulièrement important de limiter la taille des messages et la taille des mailbox (variables "mailbox_size_limit" et "message_size_limit").

5.6.2 Être MX secondaire (back up) d'un domaine

Le service SMTP, plus que tout autre, exige une continuité parfaite. Vous ne pouvez pas vous permettre de perdre du courrier. Une solution existe, cependant, pour pallier aux éventuelles défaillances d'un système SMTP. Elle consiste à indiquer, dans la configuration des zones de votre domaine, plusieurs serveurs SMTP avec un ordre de préférence. Celui ayant la meilleure préférence est le vrai serveur SMTP de ce domaine. Dans le cas où cette machine serait indisponible, les MTA désirant vous envoyer du courrier se rabattront sur le serveur de préférence inférieure (MX secondaire, puis MX tertiaire si le secondaire est indisponible etc.). Ces serveurs "secondaires" sont simplement des machines acceptant de relayer le courrier pour votre domaine vers le SMTP primaire.
Pour être MX (Mail eXchanger) secondaire, il suffit que vous ajoutiez ceci à main.cf :

relay_domains = $mydestinations, mondomaine1.com, mondomaine2.com (etc...)
Dès lors, le DNS hébergeant les divers domaines (dans l'exemple: domaine1.com et domaine2.com) pourra indiquer le nom de votre serveur smtp comme DNS secondaire.
Ce qui nous donne des entrées comme ceci dans une zone named :
IN MX 10 leursmtp1.com
IN MX 20 monsmtp.com
Dans ce cas, si le serveur smtp primaire (leursmtp1.com) est injoignable, les mails atterrirons temporairement chez vous (monsmtp.com). Votre postfix essaiera de les envoyer au smtp primaire (leursmtp1.com) à intervalles réguliers, jusqu'à ce que celui-ci soit à nouveau accessible. On peut aussi faire un MX tertiaire (MX 30 ...) etc.

5.6.3 Gérer plusieurs domaines

Il vous faudra lire la page de man "virtual".

Nb: Il est aussi possible de stocker ses virtual_maps dans des base de données (mysql, ...).

5.6.4 Installer une mailing-list

Il y a une méthode simple mais basique : créer un alias dans /etc/postfix/aliases et y ajouter les adresses intéressées.
La seconde méthode, plus sophistiquée consiste à installer majordomo. Lisez la faq de postfix et la doc de Majordomo.

5.6.5 Masquerade

Nous voulons que le courrier envoyé hors du réseau local aient la forme user@mondomaine.com plutôt que user@host, user@autredomaine.net ou autres.
Il suffit de préciser dans /etc/postfix/main.cf :

append_dot_mydomain = yes
append_at_myorigin = yes
masquerade_domains = $mydomain
La FAQ de postfix nous indique les deux astuces suivantes :

5.6.6 Liaison intermittente

Si vous n'êtes pas connectés en permanence à internet, il faut ajuster votre conf.
D'après la FAQ postfix.
Nous voulons que tout les emails sortant semblent provenir de user@my-isp.com, mais que certains mails pour le réseau local gardent leur forme (et soient délivrés localement) :
Dans main.cf :

myorigin = my-isp.com
virtual_maps = hash:/etc/postfix/virtual
Et dans /etc/postfix/virtual :
root root@localhost
postmaster postmaster@localhost
user3 user3@localhost
Et bien sûr, lancer "postmap /etc/postfix/virtual" et "postfix reload".
Ensuite, on fait router tout le mail sortant par le SMTPD de notre ISP; on empêche les tentatives d'envoi automatiques, et les requêtes DNS :
relayhost = smtp.my-isp.com # en fait, indiquer ceci sous forme d'ip numérique car disable_dns... ci-dessous
defer_transports = smtp
disable_dns_lookups = yes
Et voilà. Chaque fois que nous serons connectés, nous pourrons vidanger la queue de postfix par un /usr/sbin/sendmail -q.

Voire http://www-dt.e-technik.uni-dortmund.de/~ma/postfix/dialup.html pour plus de subtilité.

6. Créer les tables et les aliases

Créer les tables d'access suivantes, même si vous n'en avez pas l'usage dans l'immédiat.
Ne pas oublier, après chaque modification d'un de ces fichiers, de faire un "postmap /le/fichier" (sauf pour le fichier d'alias qui prends plutôt un "postalias /etc/postfix/aliases").

1) /etc/postfix/access_by_recipient_hash :

#un exemple de fichier de filtres d'acces par recipient
#recipient = adresse de destination du mail
# (telle qu'indique dans le "RCPT TO:")
#peut être utilise dans les 'smtpd_*restrictions' de main.cf
#par la directive :
#check_recipient_access hash:/etc/postfix/access_by_recipient_hash
#
#lancer postmap /etc/postfix/access_by_recipient_hash après changement

#rejeter selon l'adresse mail :
winmoney@spammer.com REJECT

#rejeter selon le domaine :
freesexpictures.com REJECT

#accepter selon le domaine :
#reynerie.yi.org OK

#rejeter selon l'utilisateur :
winmorefreesexpictures@ REJECT

2) /etc/postfix/access_by_recipient_regexp :

#un exemple de filtre de recipients par regexps
#recipient = adresse de destination du mail
# (telle qu'indiqué dans le "RCPT TO:")
#peut être utilise dans les smtpd_*restrictions de main.cf
#par la directive :
#check_recipient_access regexp:/etc/postfix/access_by_recipient_regexp
#
#lancer postmap /etc/postfix/access_by_recipient_regexp apres changement.
#
#si votre règle contient des ':', ne pas s'inquiéter des messages :
#'record is in "key: value" format; is this an alias file?'

/^to: .*@enculedespammeur\.com$/ REJECT
/[@!%].*[@!%]/ 550 Please use user@domain address forms only.

# always allow mail to postmaster and abuse (said Ralf Hildebrandt)
/postmaster@/ OK
/abuse@/ OK

3) /etc/postfix/access_by_sender_hash :

#un exemple de fichier de filtres d'acces par sender
#sender = adresse mail de l'envoyeur (telle qu'indiquee dans
# le "MAIL FROM:")
#peut être utilise dans les 'smtpd_*restrictions' de main.cf
#par la directive :
#check_sender_access hash:/etc/postfix/access_by_sender_hash
#
#lancer postmap /etc/postfix/access_by_sender_hash après changement

#rejeter selon l'adresse mail :
winmoney@spammer.com REJECT

#rejeter selon le domaine :
freesexpictures.com REJECT

#accepter selon le domaine :
#reynerie.yi.org OK

#rejeter selon l'utilisateur :
winmorefreesexpictures@ REJECT

4) /etc/postfix/access_by_sender_regexp :

#un exemple de filtre de sender par regexps
#sender = adresse de provenance du mail
# (telle qu'indique dans le "MAIL FROM:")
#peut être utilise dans les smtpd_*restrictions de main.cf
#par la directive :
#check_sender_access regexp:/etc/postfix/access_by_sender_regexp
#
#lancer postmap /etc/postfix/access_by_sender_regexp après changement.
#
#si votre règle contient des ':', ne pas s'inquiéter des messages :
#'record is in "key: value" format; is this an alias file?'

/mechant@enculedespammeur\.com/ REJECT

# par domaine : préfère utiliser la table
# access_by_sender_hash qui est plus rapide
#/@enculedespammeur\.com/ REJECT

5) /etc/postfix/access_by_client_hash :

#un exemple de fichier de filtres d'accès par clients.
#client = domaine/ip du client smtp connecte a postfix.
# par conséquent, ne peut pas servir a filtrer par adresse email
# mais seulement par domaine.
#peut être utilise dans les 'smtpd_*restrictions' de main.cf
#par la directive :
# check_client_access hash:/etc/postfix/access_by_client_hash
#
#lancer postmap /etc/postfix/access_by_client_hash après chaque changement.

#rejeter selon le domaine :
freesexpictures.com REJECT

#accepter selon le domaine :
#reynerie.yi.org OK

6) /etc/postfix/header_check_filters :

#un exemple de filtre de headers par regexps
#utilise dans main.cf par la directive :
#header_checks = regexp:/etc/postfix/header_check_filters
#
#lancer postmap /etc/postfix/header_check_filters après changement.
#
#si votre règle contient des ':', ne pas s'inquiéter des messages :
#'record is in "key: value" format; is this an alias file?'

/^from: .*@enculedespammeur\.com$/ REJECT
/^to: .*@enculedespammeur\.com$/ REJECT

7) /etc/postfix/aliases :

#lancer postalias /etc/postfix/aliases après modif
# Basic system aliases -- these MUST be present.
MAILER-DAEMON: postmaster
postmaster: root

# General redirections for pseudo accounts.
bin: root
nobody: root
postfix: root

# Well-known aliases -- these should be filled in!
# root:
# operator:


# Standard aliases defined by rfc2142
# address to report network abuse (like spam)
abuse: postmaster

# uncomment this for msgs:
# msgs: "|/usr/bin/msgs -s"
zoub: ben, ben@somedomain.com, machin@chose.com

7. Installer un scanner antivirus

7.1 Installation

Il existe plusieurs interfaces pour piloter les antivirus via postfix : avcheck et amavis en particulier. Je n'ai essayé qu'amavis ; il a l'avantage de supporter un plus grand nombre d'antivirus, car il s'occupe lui même de décoder les MIME (ce que tout les antivirus ne font pas d'eux mêmes).
Il vous faudra aussi installer des antivirus. Débrouillez vous. Je n'ai eu aucun problème avec H+BEDV AntiVirX, Sophos sweep et Trend InnoculateIT 4.
Entre autres, amavis à besoin de l'utilitaire (préhistorique) arc. Dans le Makefile de celui-ci, j'ai dû préciser SYSTEM = -DBSD=1 alors même que j'utilisai un linux
Bref, après avoir installé la térachiée de softs et modules perl pré-requis par amavis (cf. le README), voici ce que j'ai fait :

% cd amavisd-snapshot-20010714/
# useradd -g nogroup -s /no/shell vscan
% ./configure --prefix=/usr/local/antivirus/amavis --enable-postfix --enable-smtp --with-sophos-ide=/usr/local/antivirus/sophos_sweep/sav/ --with-smtp-port=10025 --with-amavisuser=vscan --enable-syslog
Les options du configure dépendent bien sûr des antivirus que vous avez installé.
Si vous n'avez pas installé les antivirus dans leur emplacement par défaut et qu'ils ne sont pas détectés par le configure, faites des liens symboliques aux endroits nécessaires (fiez vous aux "checking for XYZ ... /usr/local/bin/XYZ") et relancez le configure.
# mkdir -p /var/amavis/virusmails
Si vous n'avez pas précisé au configure, l'utilisateur d'amavis est "vscan" :
# chown -R vscan /var/amavis/
# chmod -R 700 /var/amavis

7.2 Configuration

Éditez le fichier /etc/amavisd.conf, remplacez $QUARANTINE = "/var/virusmails"; par $QUARANTINE = "/var/amavis/virusmails"; et modifiez le reste à votre convenance ...
Éditez le fichier /etc/postfix/master.cf et ajoutez :

vscan unix - n n - 10 pipe user=vscan argv=/usr/local/antivirus/amavis/sbin/amavis ${sender} ${recipient}
localhost:10025 inet n - n - - smtpd -o content_filter=

Éditez le fichier main.cf et ajoutez :

content_filter = vscan:

7.3 Lancement

Lancez amavisd :

# amavisd
# chown vscan /var/amavis/amavisd.sock
# postfix start
Sur ma machine, un bug de amavisd m'obligerait a rectifier le propriétaire de la socket /var/amavis/amavisd.sock à chaque lancement de amavisd si je n'avait (dans /usr/local/sbin/amavisd) ajouté une ligne contenant:
chown 1056, 0, $socketname; # 1056 est l'uid de l'user vscan sur ma machine
juste après la ligne :
listen (Server, SOMAXCONN) || die "listen failed: $!"
dans /usr/local/sbin/amavisd. Dorénavant, ne pas oublier de toujours lancer amvisd avant postfix.
ie: lancement de postfix :
amavisd && postfix start
arret de postfix :
postfix stop && killall amavisd
Modifiez vos scripts d'init en conséquence...

7.4 Mises à jours

À titre d'exemple : pour la mise à jour des fichiers de signature d'antivirus de Sweep et de Inoculate IT, je m'y prend ainsi :

#!/bin/sh

# Sophos Sweep
cd /usr/local/antivirus/sophos_sweep/sav/
wget -N http://www.sophos.com/downloads/ide/356_ides.zip
unzip -q -o 356_ides.zip

# Inoculate IT
cd /usr/local/antivirus/Trend_inoculate_it_4.0
wget -N ftp://ftp.ca.com/pub/getbbs/linux.eng/inoctar.LINUX.Z
wget -N ftp://ftp.ca.com/pub/getbbs/linux.eng/linux.txt
tar xvzf inoctar.LINUX.Z
chmod 755 *

#pas de mise à jour pour H+BEDV AntiVir quand on a pas de licence

8. Installer UW IMAP Server

J'ai choisi la version imapd de washington (UW IMAP Server, imap-2001a) parcequ'elle est la seule (à ma connaissance) à implémenter simultanément imap, pop3, le chiffrement par SSL ou connexion + STARTTLS, l'autentification apop ou cram, qu'elle est supportée par les principaux systèmes de webmail (installée par défaut sur la debian dit Linuxmag), et qu'elle contient des headers nécessaires à php.

8.1 Installation

Assurez vous d'avoir installé OpenSSL dans /usr/local/ssl, puis

% tar xvzf imap.tar.Z && cd imap-2001a/
% make slx SSLTYPE=unix #pour linux sans pam
Ou bien "% make lnp SSLTYPE=unix" pour un linux avec pam etc ... (cf. le fichier doc/BUILD)
# cp ipopd/ipop3d /usr/local/sbin/
# cp imapd/imapd /usr/local/sbin/
# cp c-client/c-client.a /usr/local/lib
# cp c-client/rfc822.h c-client/mail.h c-client/linkage.h /usr/local/include/

On peut réutiliser les certificats générés/signés pour postfix :
Creez un fichier /usr/local/ssl/cert.pem vide.
Copiez y la partie de /etc/postfix/key.pem comprise entre -----BEGIN RSA PRIVATE KEY----- et -----END RSA PRIVATE KEY-----.
À la suite, copiez y le certificat de postfix (partie de /etc/postfix/cert.pem comprise entre -----BEGIN CERTIFICATE----- et -----END CERTIFICATE-----)

# chmod 600 /usr/local/ssl/certs/cert.pem
# ln -s /usr/local/ssl/certs/cert.pem /usr/local/ssl/certs/ipop3d.pem
# ln -s /usr/local/ssl/certs/cert.pem /usr/local/ssl/certs/imapd.pem

8.2 Mots de passe

On crée un fichier /etc/cram-md5.pwd de mots de passe en clair pour l'authentification par APOP ou CRAM-MD5 contenant, par ex:

# CRAM-MD5 authentication database
# Entries are in form
# Lines starting with "#" are comments

bill hubba-hubba
hillary nysenator
monica beret
Une fois ce fichier défini, le mot de passe pop/imap devra toujours être celui indiqué ici (et non celui de /etc/shadow), qu'on utilise ou non l'apop, le cram-md5 ou autre.

Un petit script pour automatiser tout ça. (utilise lui aussi passook, le générateur de mots de passe tordus) :

#!/bin/sh
for user in `grep "/home/.*/bin/bash" /etc/passwd | cut -d : -f 1`
  do
  echo -en "---\nPOP et APOP\nuser: $user mot de passe :" >> /root/passwd_users/pass.$user.tmp
  echo -en "$user\t" >> /etc/cram-md5.pwd
  passook | tee -a /root/passwd_users/pass.$user.tmp >> /etc/cram-md5.pwd
done

Ne pas oublier de faire :

# chown postfix:root /etc/cram-md5.pwd
# chmod 600 /etc/cram-md5.pwd

8.3 Tests

Avoir ceci dans /etc/inetd.conf (les 'imapd' et 'ipop3d' en fin de ligne sont importants) :

pop3 stream tcp nowait root /usr/sbin/tcpd /usr/local/sbin/ipop3d ipop3d
imap stream tcp nowait root /usr/sbin/tcpd /usr/local/sbin/imapd imapd
pop3s stream tcp nowait root /usr/local/sbin/ipop3d ipop3d
imaps stream tcp nowait root /usr/local/sbin/imapd imapd
Et ajouter ou décommenter dans /etc/services :
pop3 110/tcp
pop3s 995/tcp
imap 143/tcp
imaps 993/tcp
Puis faire un
# killall -1 inetd
On teste le pop sur SSL :
% openssl s_client -connect localhost:pop3s -state
<+OK POP3 v2001.78 server ready <5838.3c35bff4@localhost>
>user ben
<+OK User name accepted, password please
>pass monpassword
<+OK Mailbox open, 144 messages
>list
Un petit script reynerie-made pour tester l'apop :
#!/usr/bin/perl -wT
use strict;
my $server = "localhost";
my $user = "username";
my $pass = "mon mot de passe tel qu'indiqué dans /etc/cram-md5.pwd";

use Net::POP3;
use Digest::MD5 qw(md5_hex);
my $apop = Net::POP3->new("$server") or print "Serveur injoignable\n";
defined($apop->apop("$user","$pass")) or print "user ou pass invalide.\n";
my $messages = $apop->list or die "Can't get list of undeleted messages $!\n";
foreach (keys %$messages) { print @{$apop->top($_,0)} };

9. Installer le webmail

Avoir php compilé avec le support imap.

% tar squirrelmail-1.2.2.tar.gz mv squirrelmail /some/where/webmail
% cd /some/where/webmail
Si vous utilisez apache et qu'il tourne sous nobody, groupe nobody :
# mkdir data attachments && chown -R nobody:nobody data attachments
% chmod 730 attachments
Ajouter ceci dans la cron de root, à executer de temps en temps :
rm `find /some/where/webmail/attachments -atime +2 | grep -v "\." | grep -v _`
Ajouter ceci à httpd.conf
Alias /webmail "/some/where/webmail"
 <Directory "/some/where/webmail">
   php_value session.use_cookies 1
   php_value session.save_path /tmp/php_sessions
   AllowOverride None
   Order allow,deny
   Allow from all
</Directory>
% cd /some/where/webmail
% ./configure
- dans "Organisation preferences", mettre la langue par défaut : fr (et ajustez le reste à votre convenance)
- "Server Settings" : mettre la réponse qui va de soi, pour "Domain", et
 		IMAP Server          : localhost
		IMAP Port            : 143
		Use Sendmail/SMTP    : SMTP
		SMTP Server        : localhost
		SMTP Port          : 25
		Authenticated SMTP : false
		Server               : uw
		Invert Time          : false
		Delimiter            : /
- "Folder Defaults" : "Default Folder Prefix : mail/", laisser le reste tel quel
- "General Options" :
	Default Charset        : iso-8859-1
	Data Directory         : ../data/
	Attachment Directory   : ../attachment/
Pour le reste, faites au feeling. Vous pouvez, en particulier, installer des plugins. Cf. la doc et le site de squirrelmail.