Postfix v2.x + MySQL + libsasl v2.x + Cyrus v2.2.x
Dans ce court document, je vais essayer d'aider toi lecteur à pndre en main ces merveilleux mais obscurs logiciels dans le but de monter un service de mail digne de ce nom sur ton serveur chéri.
Dans un pmier temps, nous allons voir comment configurer Postfix pour gérer des domaines virtuels conviviaux avec MySQL.
Ensuite, nous verrons comment configurer Postfix et la libsasl pour authentifier nos utilisateurs et ne pas relayer les mails comme des sales cochons.
Pour finir, on configurera Cyrus pour utiliser tout ça. Et puis peut être même qu'on mettra du SSL au dessus de nos machins.
Vu qu'on est pas riche, on génerera nous même un certificat racine qui servira à signer nos certificats.
Postfix
Mise en place des domaines virtuels
Le but ici est de pouvoir gérer plusieurs domaines de manières indépendante et sans avoir à créer de compte Unix.
Postfix implémente pour ce faire un transport dit "virtual".
Il va donc falloir lui dire, via MySQL, quels sont les domaines dit virtuels, et quels en sont les utilisateurs.
Voici un extrait du fichier de configuration main.cf:
virtual_mailbox_domains = mysql:/etc/postfix/vdomain.cf
virtual_mailbox_maps=mysql:/etc/postfix/vmail.cf
virtual_alias_maps=mysql:/etc/postfix/vmail.cf
Et voici le contenu des fichiers de configuration:
vdomain.cf
virtual_mailbox_domains = mysql:/etc/postfix/vdomain.cf
user=mysql_user
password=mysql_secret
dbname=mail
table=transport
select_field=domain
where_field=domain
hosts=localhost
additional_conditions = and transport = 'virtual'
vmail.cf
user=mysql_user
password=mysql_pass
dbname=mail
table=virtual
select_field=goto
where_field=address
hosts=localhost
Voici les structures des tables MySQL utilisées:
CREATE TABLE `transport` (
`domain` varchar(128) NOT NULL default '',
`transport` varchar(128) NOT NULL default '',
UNIQUE KEY `domain` (`domain`)
) TYPE=MyISAM
CREATE TABLE `virtual` (
`address` varchar(255) NOT NULL default '',
`goto` varchar(255) NOT NULL default '',
UNIQUE KEY `address` (`address`)
) TYPE=MyISAM
Dans un pmier temps, lors de l'arrivée d'un email, Postfix va regarder dans la table domain si un enregistrement ("domain","virtual") existe.
Si ce domaine existe, alors Postfix va rechercher l'email du destinataire dans la table virtual (ici, nous utilisons cyrus pour la delivery, la configuration du transport virtuel est donc limitée) pour savoir dans un pmier si le destinataire existe puis si il s'agit d'un alias.
Plus de détails quant aux domaines virtuels peuvent être trouvés ici: http://x.guimard.free.fr/postfix/index.php?page=VIRTUAL_README.html.
Voilà pour la configuration des domaines virtuels au sein de Postfix.
Authentification SASL
Tant que nous y sommes, nous allons configurer l'authentifcation SASL sur ce dernier. Ainsi, un utilisateur devra necessairement passer par une phase d'authentification avant de pouvoir envoyer un email via notre serveur.
Voici l'extrait du main.cf concernant le SASL:
smtpd_sasl_auth_enable = yes
smtpd_sasl_application_name = smtp
smtpd_recipient_restrictions = permit_mynetworks , permit_sasl_authenticated , reject_unauth_destination
La pmière se passe de tout commentaire.
La librairie SASL permet de définir, un peu à la manière de PAM, des mécanismes différents selon l'application. Une application étant identifiée par son nom, la librairie ira lire le fichier de configuration associé dans /usr/lib/sasl2, /usr/local/lib/sasl2/ ou encore bizarrement sur mon système /etc/postfix/sasl.
Dans notre cas, le fichier lu sera smtp.conf (du nom spécifié dans smtpd_sasl_application_name).
La directive smtpd_recipient_restrictions permet de mettre en place des restrictions au niveau du "RCPT TO". Par défaut, Postfix accepte les mails provenant de son réseau, ou à destination d'un domaine local ou pour lequel il est relai.
Avec la troisième ligne, on précise à Postfix d'autoriser également l'envoi de mails par les utilisateurs authentifier via SASL. Plus d'infos sur cette directive peuvent être consultées ici: http://x.guimard.free.fr/postfix/index.php?page=postconf.5.html#smtpd_recipient_restrictions
J'ai personnelement fais le choix de gérer mes comptes utilisateurs via une base MySQL. Je vais donc décrire la manière de configurer SASL pour utiliser MySQL. Voici le contenu de mon fichier /etc/posfix/sasl/smtp.conf:
pwcheck_method: auxprop
auxprop_plugin: sql
mech_list: CRAM-MD5 DIGEST-MD5 LOGIN PLAIN
sql_engine: sql
sql_user: mysql_user
sql_passwd: mysql_pass
sql_hostnames: localhost
sql_database: mail
sql_select: select password from users where login='%u' and domain='%r'
La libSASL permet par défaut d'utiliser plusieurs méthodes d'authentification:
- pwcheck, utilise le programme du même nom.
- saslauthd, utilise une évolution de pwcheck, saslauthd qui implémente lui même plusieurs mécanismes (sasldb,pam,kerberos ...)
- auxprop, utilise des plugins.
Dans notre cas, l'utilisation de MySQL est implémenté par le plugin sql (pour vérifier que celui ci est bien compilé sur votre installation, regardez le contenu de /usr/(local/)lib/sasl2/, un fichier nommé libsql.so devrait s'y trouver).
Ensuite, la libsasl nous permet de définir quel mecanisme peuvent être utiliser pour l'authentification. Voici une liste non exhaustive de ces derniers:
- PLAIN, le mécanisme le plus simple qui consiste à envoyer le mot de passe en clair.
- LOGIN, non implémenté dans la libsasl du projet Cyrus, ce mécanisme fonctionne à la manière de PLAIN.
- CRAM-MD5, mécanisme de "secret partagé" le serveur propose au client un challenge et vérifie la réponse de ce dernier. Un inconvénient existe: le serveur doit impérativement connaitre le mot de passe (donc impossible de stocker un hash de ce dernier).
- DIGEST-MD5, évolution du mécanisme CRAM-MD5.
Ici, nous privilégions les méthodes basées sur le secret partagé, plus sûres dans le cas de connexion non cryptées. La suite défini les paramètres MySQL. Une petite précision quant à la directive sql_select: SASL fonctionne avec des utilisateurs et des domaines ("realm en anglais"), notion très utile pour les domaines virtuels.
Par exemple, si un utilisateur tente de s'authentifier en utilisant le nom d'utilisateur toto@test.com, la requête MySQL sera:
sql_select: select password from users where login='toto' and domain='test.com'
Voyons maintenant la structure de la table users, utilisée par la libsasl:
CREATE TABLE `users` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(50) NOT NULL default '',
`login` varchar(50) NOT NULL default '',
`domain` varchar(50) NOT NULL default '',
`email` varchar(100) NOT NULL default '',
`password` varchar(50) default NULL,
KEY `id` (`id`)
) TYPE=MyISAM
Le champ name est facultatif et ne sert qu'à stocker le nom de l'utilisateur en cas de mémoire déficiente.
Les autres champs sont assez explicites pour se passer de commentaire, toutefois, si vous souhaitez utiliser les mecanismes CRAM-MD5 ou DIGEST-MD5, n'oubliez pas qu'il est necessaire de stocker les mots de passe en clair.
Une fois tout cela fait, relancez postfix et tenter une session SMTP:
[binarym@trait-plat]:~% telnet psycho-hazard.net 25
Trying 213.41.149.160...
Connected to psycho-hazard.net.
Escape character is '^]'.
220 construct.psycho-hazard.net ESMTP
EHLO SMTP
250-construct.psycho-hazard.net
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-STARTTLS
250-AUTH CRAM-MD5 DIGEST-MD5 LOGIN PLAIN
250 8BITMIME
On constate ici que Postfix sait maintenant gérer l'authentification.
ATTENTION !
Lors de vos tests, il est fort probable que cela ne fonctionne pas. Le serveur SMTP ne vous salue pas et la ligne suivante apparait dans vos fichiers de journaux:
Dec 10 21:54:51 localhost postfix/smtpd[10149]: fatal: no SASL authentication mechanisms
Ne vous inquietez pas, j'ai la solution !
Postfix par défaut est chrooté. C'est à dire qu'au démarrage, postfix fait appel à la fonction C chroot() pour changer sont répertoire racine en /var/spool/postfix. En jettant un oeil dans /var/spool/postfix/lib, on remarque rapidement qu'il n'existe pas de librairie SASL.
Il faut donc y installer la librairie SASL ainsi que ses dépendances.
Voici dans mon cas le contenu de /var/spool/postfix/lib et /var/spool/postfix/usr/lib après résolution de ces dépendances:
[root@rei]:~postfix# find lib usr/lib -ls
146596 4 drwxr-xr-x 2 root root 4096 Dec 20 09:05 lib
146610 28 -rw-r--r-- 1 root root 27304 Oct 13 21:40 lib/libnss_compat-2.3.2.so
146611 0 lrwxrwxrwx 1 root root 22 Dec 20 09:05 lib/libnss_compat.so.2 -> libnss_compat-2.3.2.so
146612 16 -rw-r--r-- 1 root root 15316 Feb 24 2003 lib/libnss_db-2.2.so
146613 0 lrwxrwxrwx 1 root root 16 Dec 20 09:05 lib/libnss_db.so.2 -> libnss_db-2.2.so
146614 16 -rw-r--r-- 1 root root 13976 Oct 13 21:40 lib/libnss_dns-2.3.2.so
146615 0 lrwxrwxrwx 1 root root 19 Dec 20 09:05 lib/libnss_dns.so.2 -> libnss_dns-2.3.2.so
146616 36 -rw-r--r-- 1 root root 34520 Oct 13 21:40 lib/libnss_files-2.3.2.so
146617 0 lrwxrwxrwx 1 root root 21 Dec 20 09:05 lib/libnss_files.so.2 -> libnss_files-2.3.2.so
146618 16 -rw-r--r-- 1 root root 14268 Oct 13 21:40 lib/libnss_hesiod-2.3.2.so
146619 0 lrwxrwxrwx 1 root root 22 Dec 20 09:05 lib/libnss_hesiod.so.2 -> libnss_hesiod-2.3.2.so
146620 32 -rw-r--r-- 1 root root 32480 Oct 13 21:40 lib/libnss_nis-2.3.2.so
146621 0 lrwxrwxrwx 1 root root 19 Dec 20 09:05 lib/libnss_nis.so.2 -> libnss_nis-2.3.2.so
146622 40 -rw-r--r-- 1 root root 39832 Oct 13 21:40 lib/libnss_nisplus-2.3.2.so
146623 0 lrwxrwxrwx 1 root root 23 Dec 20 09:05 lib/libnss_nisplus.so.2 -> libnss_nisplus-2.3.2.so
146649 68 -rwx--x--x 1 root root 64924 Dec 10 20:20 lib/libresolv-2.3.2.so
146650 0 lrwxrwxrwx 1 root root 18 Dec 10 20:20 lib/libresolv.so.2 -> libresolv-2.3.2.so
146651 20 -rwx--x--x 1 root root 18780 Dec 10 20:21 lib/libcrypt-2.3.2.so
146652 0 lrwxrwxrwx 1 root root 17 Dec 10 20:21 lib/libcrypt.so.1 -> libcrypt-2.3.2.so
146653 0 lrwxrwxrwx 1 root root 15 Dec 10 20:21 lib/libnsl.so.1 -> libnsl-2.3.2.so
146654 1220 -rwx--x--x 1 root root 1244080 Dec 10 20:21 lib/libc-2.3.2.so
146655 0 lrwxrwxrwx 1 root root 13 Dec 10 20:21 lib/libc.so.6 -> libc-2.3.2.so
146656 136 -rwx--x--x 1 root root 134464 Dec 10 20:22 lib/libm-2.3.2.so
146657 0 lrwxrwxrwx 1 root root 13 Dec 10 20:22 lib/libm.so.6 -> libm-2.3.2.so
146658 84 -rwx--x--x 1 root root 81127 Dec 10 20:22 lib/libpthread-0.10.so
146659 0 lrwxrwxrwx 1 root root 18 Dec 10 20:22 lib/libpthread.so.0 -> libpthread-0.10.so
146660 0 lrwxrwxrwx 1 root root 11 Dec 10 20:22 lib/ld-linux.so.2 -> ld-2.3.2.so
146661 12 -rwx--x--x 1 root root 9872 Dec 10 20:23 lib/libdl-2.3.2.so
146662 0 lrwxrwxrwx 1 root root 14 Dec 10 20:23 lib/libdl.so.2 -> libdl-2.3.2.so
146663 0 lrwxrwxrwx 1 root root 17 Dec 10 20:23 lib/libcom_err.so.2 -> libcom_err.so.2.1
146664 8 -rwx--x--x 1 root root 5900 Dec 10 20:23 lib/libcom_err.so.2.1
146598 4 drwxr-xr-x 5 root root 4096 Dec 10 22:16 usr/lib
146636 0 lrwxrwxrwx 1 root root 18 Dec 10 20:16 usr/lib/libsasl2.so.2 -> libsasl2.so.2.0.19
146637 88 -r-xr-xr-x 1 root root 84820 Dec 10 20:16 usr/lib/libsasl2.so.2.0.19
1189045 4 dr-xr-xr-x 2 root root 4096 Dec 10 23:38 usr/lib/sasl2
1189046 24 -r--r--r-- 1 root root 21798 Dec 10 20:16 usr/lib/sasl2/libsasldb.a
1189047 4 -r--r--r-- 1 root root 852 Dec 10 20:16 usr/lib/sasl2/libsasldb.la
1189048 0 lrwxrwxrwx 1 root root 19 Dec 10 20:16 usr/lib/sasl2/libsasldb.so -> libsasldb.so.2.0.19
1189049 0 lrwxrwxrwx 1 root root 19 Dec 10 20:16 usr/lib/sasl2/libsasldb.so.2 -> libsasldb.so.2.0.19
1189050 20 -r-xr-xr-x 1 root root 18692 Dec 10 20:16 usr/lib/sasl2/libsasldb.so.2.0.19
1189051 24 -r--r--r-- 1 root root 22168 Dec 10 20:16 usr/lib/sasl2/libsql.a
1189052 4 -r--r--r-- 1 root root 874 Dec 10 20:16 usr/lib/sasl2/libsql.la
1189053 0 lrwxrwxrwx 1 root root 16 Dec 10 20:16 usr/lib/sasl2/libsql.so -> libsql.so.2.0.19
1189054 0 lrwxrwxrwx 1 root root 16 Dec 10 20:16 usr/lib/sasl2/libsql.so.2 -> libsql.so.2.0.19
1189055 24 -r-xr-xr-x 1 root root 22132 Dec 10 20:16 usr/lib/sasl2/libsql.so.2.0.19
146638 0 lrwxrwxrwx 1 root root 24 Dec 10 20:17 usr/lib/libmysqlclient.so.10 -> libmysqlclient.so.10.0.0
146639 216 -r-xr-xr-x 1 root root 214344 Dec 10 20:17 usr/lib/libmysqlclient.so.10.0.0
146640 0 lrwxrwxrwx 1 root root 24 Dec 10 20:17 usr/lib/libmysqlclient.so.12 -> libmysqlclient.so.12.0.0
146641 252 -r-xr-xr-x 1 root root 252264 Dec 10 20:17 usr/lib/libmysqlclient.so.12.0.0
146642 0 lrwxrwxrwx 1 root root 12 Dec 10 20:17 usr/lib/libpq.so.3 -> libpq.so.3.1
146643 132 -r-xr-xr-x 1 root root 127184 Dec 10 20:17 usr/lib/libpq.so.3.1
146644 0 lrwxrwxrwx 1 root root 13 Dec 10 20:19 usr/lib/libz.so.1 -> libz.so.1.2.2
146645 72 -r-xr-xr-x 1 root root 67468 Dec 10 20:19 usr/lib/libz.so.1.2.2
146646 0 lrwxrwxrwx 1 root root 18 Dec 10 20:19 usr/lib/libk5crypto.so.3 -> libk5crypto.so.3.0
146647 140 -r-xr-xr-x 1 root root 138664 Dec 10 20:19 usr/lib/libk5crypto.so.3.0
16307 4 dr-xr-xr-x 3 root root 4096 Dec 10 20:20 usr/lib/i686
32598 4 drwxr-xr-x 2 root root 4096 Dec 10 22:05 usr/lib/i686/cmov
32599 1012 -rw-r----- 1 root root 1029672 Dec 10 22:05 usr/lib/i686/cmov/libcrypto.so.0.9.7
32600 200 -rw-r----- 1 root root 198576 Dec 10 22:05 usr/lib/i686/cmov/libssl.so.0.9.7
146648 200 -r-xr-xr-x 1 root root 198576 Dec 10 21:44 usr/lib/libssl.so.0.9.7
130325 4 dr-xr-xr-x 2 root root 4096 Dec 20 09:05 usr/lib/zoneinfo
130313 0 lrwxrwxrwx 1 root root 14 Dec 20 09:05 usr/lib/zoneinfo/localtime -> /etc/localtime
146665 668 -rw------- 1 root root 678224 Dec 10 22:16 usr/lib/libdb-4.0.so
146666 776 -rw------- 1 root root 789512 Dec 10 22:16 usr/lib/libdb-4.1.so
146667 864 -rw------- 1 root root 876584 Dec 10 22:16 usr/lib/libdb-4.2.so
Un outil utile dans l'installation des différentes librairies est ldd.
Ce dernier permet de visualer à quelle librairies un executable ou une librairie est liée (attention, cela ne concerne que les les librairies liés, non les librairies accédées via dlopen()).
Voici la sortie que produit ldd dans mon cas:
[root@rei]:~postfix# ldd /usr/lib/libsasl2.so.2
libdl.so.2 => /lib/libdl.so.2 (0x2f801000)
libresolv.so.2 => /lib/libresolv.so.2 (0x2f804000)
libc.so.6 => /lib/libc.so.6 (0x2f816000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x10d10000)
Bien evidemment, vérifiez que postfix aie le droit de lire les librairies en question.
Autre problème lié au chroot: si vous configurez Postfix pour utiliser MySQL sur localhost, vieillez bien à ce que mysqld écoute dans /var/spool/postfix/var/run/mysqld/mysqld.sock ou utilisez le réseau.
Pour modifier le socket d'écoute de MySQL, modifiez la section suivante dans le fichier /etc/mysql/my.cnf:
[mysqld]
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/spool/postfix/var/run/mysqld/mysqld.sock
Puis créer un lien symbolique de /var/spool/postfix/var/run/mysqld/mysqld.sock vers /var/run/mysqld/mysqld.sock.
Cyrus IMAPD
Pour la gestion du pop3/imap, j'ai jeté mon dévolu sur Cyrus, riche en fonctionnalités, performant et stable.
Personnellement, je me suis appuyé sur une version 2.2, seule version implémentant actuellement les domaines virtuels.
L'installation varie en fonction de votre distribution mais reste relativement simple.
Cyrus s'appuie sur 2 répertoires pour gérer les emails. Le pmier est utilisé pour stocker les informations relatives aux domaines, aux utilisateurs et aux processus de cyrus. Le second est quant à lui dédié au stockage des emails.
Le répertoire d'administration est crée via le script mkimap fourni avec Cyrus. J'ai pour ma part utilisé /var/imap comme répertoire administratif et /var/spool/imap comme répertoire de stockage des emails.
La suite à l'occasion...
