Dequidt.org - Postfix, Courier Imap & Pop, MySQL et Quota avec filtre AntiSpam et antivirus sous Debian

Postfix, Courier Imap & Pop, MySQL et Quota avec filtre AntiSpam et antivirus sous Debian

Le but de cet howto est d'expliquer comment mettre en place un serveur email complet, supportant plusieurs domaines sous Debian GNU/Linux. Celui-ci sera composé des éléments suivants :

Introduction

Au début, j'utilisais le serveur de courier postfix avec la configuration d'origine utilisant l'authentification unix. J'ai eu besoin de servir plusieurs domaines ainsi que des comptes mails virtuels. En effet, l'utilisation des utilisateurs unix n'est pas adaptée à une configuration multidomaine.

Désormais, je peux administrer facilement mes domaines et comptes email via l'interface Web PHPMyAdmin. Il est aussi possible de créer une interface spécifique à cette gestion par exemple en utilisant php

Prérequis

Il vous faut un système avec un serveur MySQL installé avec si possible un serveur web et PHPMyAdmin pour faciliter l'administration de la BD.

Cette documentation est écrite pour un système Debian GNU/linux

La base de données

Description de la structure

Cette base de données sera structurée dans les 3 tables suivantes :

Creation de la base et de l'utilisateur SQL

Entrez dans l'interface de la base de données :

Il faut tout d'abord créer la base de données (ex : postfix) et les tables qu'elle contient.

CREATE DATABASE `postfix`;
USE postfix;

-- 
-- Structure de la table `domain`
-- 
CREATE TABLE `domain` (
  `domain` varchar(255) NOT NULL default '',
  `actif` tinyint(1) NOT NULL default '1',
  PRIMARY KEY  (`domain`)
) ENGINE=MyISAM COMMENT='Postfix Admin - Domaines Virtuels';

-- 
-- Structure de la table `mailbox`
-- 
CREATE TABLE `mailbox` (
  `email` varchar(255) NOT NULL default '',
  `password` varchar(255) NOT NULL default '',
  `quota` int(10) NOT NULL default '0',
  `actif` tinyint(1) NOT NULL default '1',
  `imap` tinyint(1) NOT NULL default '1',
  `pop3` tinyint(1) NOT NULL default '1',
  PRIMARY KEY  (`email`)
) ENGINE=MyISAM COMMENT='Postfix Admin - Boites Emails Virtuelles';

-- 
-- Structure de la table `alias`
-- 
CREATE TABLE `alias` (
  `source` varchar(255) NOT NULL default '',
  `destination` text NOT NULL,
  `actif` tinyint(1) NOT NULL default '1',
  PRIMARY KEY  (`email`)
) ENGINE=MyISAM COMMENT='Postfix Admin - Alias Virtuels';

Ensuite, les différents services doivent accéder à cette base de données. Pour des raisons de sécurité évidentes, il est nécessaire de créer un utilisateur MySQL qui n'a accès qu'en lecture (SELECT) à la base 'postfix'. Pour l'exemple, celui-ci s'appelera 'postfix' avec comme mot de passe 'pass'. Pour le créer, il suffit de taper les commandes suivantes dans la console MySQL :

GRANT SELECT ON `postfix`.* TO 'postfix'@'%'
IDENTIFIED BY 'pass';

Postfix

Installation

Pour l'instant, Postfix ne supporte pas les quotas en natif. Cependant, le patch VDA offre cette possibilité.

Pour ne pas recompiler postfix en intégrant le patch VDA, nous allons utiliser le dépot de paquets non-officiel pour Debian : http://debian.home-dn.net

Il faut ajouter les lignes suivantes à la liste des dépots de votre serveur dans le fichier /etc/apt/sources.list (vous devez être logué en root pour pouvoir modifier ce fichier) :

#postfix VDA
deb http://debian.home-dn.net/sarge postfix-vda/
Puis il suffit de mettre à jour la liste des paquets et d'intaller les paquets necessaires (en tant que root) :
apt-get update
apt-get install postfix postfix-mysql
L'installateur Debian va demander quel type de configuration vous souhaitez utilisez. Dans notre cas, nous allons choisir "Pas de configuration", afin d'obtenir une configuration vierge.

Configuration

Nous allons configurer le système courier afin que les emails soient conservés dans un seul repertoire : /var/spool/vmail/.

Les boites seront rangés (au format maildir) dans un repertoire du type :

/var/spool/vmail/virtualdomain/virtualmailbox/
Création de l'utilisateur vmail
Ce repertoire sera accessible en lecture et ecriture par un utilisateur nommé vmail (uid:5000,gid:5000) que nous allons créer ainsi :
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/spool/vmail/ -m
Fichier de configuration principal

Le fichier /etc/postfix/main.cf définit les paramètres principaux du serveur postfix, notamment les paramètres des domaines virtuels.

Le fichier ci-après contient une configuration complète de postfix. Si vous avez déjà un tel fichier et que vous souhaitez seulement ajouter le support des domaines virtuel mysql, il faut copier les directives commençant par virtual_...

# /etc/postfix/main.cf
# Configuration Postfix
# espace.fr.to
#

smtpd_banner = $myhostname ESMTP (Debian/GNU)
biff = no
disable_vrfy_command = yes
smtpd_helo_required = yes

# ajoute le domaine aux emails de la distribution locale
# ainsi vous pourrez envoyer des emails sans @domain.priv
# par la commande sendmail
mydomain = domain.priv 
append_dot_mydomain = yes

# Envoi une alerte de dépassement de délai par email
#delay_warning_time = 4h

myhostname = smtp.domain.priv

# domaine de distribution local
mydestination = localhost, localhost.localdomain

# Mettez ici le relais smtp de votre FAI si vous avez des problèmes de blacklist
# à cause de votre IP
relayhost =

# adresseIP/Masque des réseaux locaux (réseaux autorisés pour l'envoi de courier)
mynetworks = 127.0.0.0/8 192.168.0.0/24
inet_interfaces = all

#restrictions d'accès
# adresses d'expédition
smtpd_sender_restrictions =
        permit_mynetworks,
        reject_unknown_sender_domain, #verifie que le domaine existe
        warn_if_reject reject_unverified_sender

# adresses de destination
smtpd_recipient_restrictions =
        permit_mynetworks,
        reject_unauth_destination,
        reject_unknown_recipient_domain,
        reject_non_fqdn_recipient

# client
smtpd_client_restrictions =
        reject_unknown_client,
        permit_mynetworks

virtual_alias_maps = mysql:/etc/postfix/mysql-virtual_aliases.cf,mysql:/etc/postfix/mysql-virtual_aliases_mailbox.cf
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual_domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual_mailboxes.cf
virtual_mailbox_base = /var/spool/vmail/
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000

virtual_create_maildirsize = yes
virtual_mailbox_extended = yes
virtual_mailbox_limit_maps = mysql:/etc/postfix/mysql-virtual_mailbox_limit_maps.cf
virtual_mailbox_limit_override = yes
virtual_maildir_limit_message = "Desole, la boite email de l'utilisateur est pleine, essayez plus tard."
virtual_overquota_bounce = yes

Fichiers de configuration d'accès à la base de données

Si vous avez un peu lu le fichier précédent, vous avez pu constater que nous faisons appel à des fichiers correspondances (mapping). Ces fichiers fournissent les informations permettant à postfix de récupérer la configuration des domaines et emails virtuels dans la base de données crée précédemment.

Vous devez créer les fichiers suivant dans /etc/postfix/ en remplaçant les paramètres par ceux de votre configuration (par exemple : le champ password).
Attention! Dans le champs host, n'utilisez pas 'localhost'. En effet postfix fonctionne en environnement "chrooté" dans le repertoire (/var/spool/postfix), il ne peut donc pas accéder aux fichiers hors de ce repertoire notamment /var/run/mysqld/mysqld.sock. Hors, si vous utiliser 'localhost', postfix va essayer d'accéder à ce fichier socket. Pour résoudre le problème nous faisons passer la connection par une connection TCP utilisant la boucle locale (lo) en utilisant l'addresse ip 127.0.0.1.

# mysql-virtual_domains.cf
hosts = 127.0.0.1
user = postfix
password = pass
dbname = postfix
select_field = 'virtual'
table = domain
where_field = domain
additional_conditions = AND actif=1
# mysql-virtual_mailboxes.cf
hosts = 127.0.0.1
user = postfix
password = pass
dbname = postfix
select_field = CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/')
table = mailbox
where_field = email
additional_conditions = AND actif=1
# mysql-virtual_aliases.cf
hosts = 127.0.0.1
user = postfix
password = pass
dbname = postfix
select_field = destination
table = alias
where_field = source
additional_conditions = AND actif=1
# mysql-virtual_aliases_mailbox.cf
hosts = 127.0.0.1
user = postfix
password = pass
dbname = postfix
select_field = email
table = mailbox
where_field = email
additional_conditions = AND actif=1
# mysql-virtual_mailbox_limit_maps.cf
hosts = 127.0.0.1
user = postfix
password = pass
dbname = postfix
select_field = quota
table = mailbox
where_field = email
Ces fichiers doivent être accessibles seulement par root et par postfix. En effet, ils contiennent le mot de passe en clair d'accès à la base de données. Pour cela il suffit de lancer les commandes suivantes qui change le groupe de ces fichiers par "postfix" et affecte les droits d'accès necessaires :
chgrp postfix /etc/postfix/mysql-virtual_*.cf
chmod u=rw,g=r,o= /etc/postfix/mysql-virtual_*.cf
Validation de la configuration

Redémarrez postfix /etc/init.d/postfix restart et lancer postfix check afin de verifier que vous n'avez fait aucune erreur.

Courier

Installation

Le serveur Courier est composé de plusieurs éléments: Pour installer tout ceci :
apt-get install courier-base courier-authdaemon courier-authmysql courier-imap courier-pop

Configuration

Le démon d'authentification

Il faut modifier le fichier /etc/courier/authdaemonrc pour indiquer à authdaemon qu'il doit utiliser le module mysql.

#authmodulelist="authpam"
authmodulelist="authmysql"

Puis il faut configurer le module authmysql en editant le fichier /etc/courier/authmysqlrc ainsi:

MYSQL_SERVER            localhost
MYSQL_USERNAME          postfix
MYSQL_PASSWORD          pass
MYSQL_DATABASE          postfix
MYSQL_USER_TABLE        mailbox

MYSQL_CRYPT_PWFIELD     password
# MYSQL_CLEAR_PWFIELD    clear

MYSQL_UID_FIELD         5000
MYSQL_GID_FIELD         5000

MYSQL_LOGIN_FIELD       email

MYSQL_HOME_FIELD        "/var/spool/vmail/"

MYSQL_MAILDIR_FIELD CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/')

#Ligne à commenter 
# MYSQL_NAME_FIELD       name

MYSQL_QUOTA_FIELD       quota
Veillez à ne pas mettre d'espace en début de ligne. Courier est très suceptible ;)
Validation de la configuration

Relancez les démons que vous venez de configurer :

/etc/init.d/courier-authdaemon restart
/etc/init.d/courier-imap restart
/etc/init.d/courier-pop restart

Test de la configuration

Pour effectuer nos tests, nous allons créer un compte email 'test' ainsi que le domain 'domain.priv' par les requêtes SQL suivantes :

INSERT INTO `domain` (`domain`,`actif`) VALUES ('test',1);
INSERT INTO `mailbox` (`email`,`password`,`quota`,`actif`,`imap`,`pop`)
       VALUES ('user@domain.priv',ENCRYPT('secret'),0,1,1,1);

Remplissage de la base de données

Pour plus de détail, referez-vous à la structure de la base de données.
Domaines
Pour chaque domaine, inserez une ligne dans la table 'domain' avec le champs actif à 1.
Boites emails
Pour chaque email, inserez une ligne dans la table 'email' avec le champs actif à 1.
Alias
Grâce à la table 'alias', vous pouvez effectuer plusieurs transferts (source->destination) :

Test Postfix

Nous allons envoyer un email à test@domain.priv via la commande telnet :
~$ telnet 127.0.0.1 25
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
220 smtp.domain.priv ESMTP (Debian/GNU)
ehlo domain.priv
250-smtp.domain.priv
250-PIPELINING
250-SIZE 10240000
250-ETRN
250 8BITMIME
mail from: <test@domain.priv>
250 Ok
rcpt to: <user@domain.priv>
250 Ok
250 Ok
data
354 End data with <CR><LF>.<CR><LF>
Voici le premier mail de test.
.
250 Ok: queued as 8ECC524208
quit
221 Bye
Connection closed by foreign host.

Vous pouvez verifier que tout c'est bien dérouler grâce au fichier de log /var/log/mail.log

postfix/smtpd[2036]: connect from localhost.localdomain[127.0.0.1]
postfix/smtpd[2036]: 8ECC524208: client=localhost.localdomain[127.0.0.1]
postfix/cleanup[2067]: 8ECC524208: message-id=<20060923131054.8ECC524208@smtp.domain.priv>
postfix/qmgr[1876]: 8ECC524208: from=<test@espace.fr.to>, size=377, nrcpt=1 (queue active)
postfix/virtual[2076]: 8ECC524208: to=<user@domain.priv>, relay=virtual, delay=0, \
  status=sent (delivered to maildir)

Si vous trouvez la ligne contenant "status=sent (delivered to maildir)", le mail a bien été reçu.

Vérifier alors le contenu du repertoire /var/spool/vmail/ avec la commande find /var/spool/vmail.

/var/spool/vmail/
/var/spool/vmail/domain.priv
/var/spool/vmail/domain.priv/user
/var/spool/vmail/domain.priv/user/tmp
/var/spool/vmail/domain.priv/user/cur
/var/spool/vmail/domain.priv/user/new
/var/spool/vmail/domain.priv/user/new/1159016974.V301I242fe.titan.espace.fr.to
/var/spool/vmail/domain.priv/user/maildirsize

Si celà correpond postfix est bien configuré et fonctionne correctement.

Test Courier

Utlisez votre client de messagerie avec comme utilisateur 'user@domain.priv' et mot de passe 'secret' pour effectuer ce test.
Attention! L'accès imap ou pop echouera si le repertoire de la boite email de l'utilisateur n'existe pas (si vous venez juste d'ajouter l'email dans la base de données). Je vous conseille d'envoyer un email de bienvenue après la création d'une nouvelle boite.

Amavis (facultatif)

Installation

apt-get install amavisd-new clamav clamav-daemon clamav-freshclam lha arj unrar zoo nomarch lzop unzoo bzip2
Les packages lha et unrar font partie du dépot non-free de Sarge.
Lors de l'installation du package clamav-freshclam, debconf va posez 2 questions :

Configuration

Afin que l'antivirus clamav puisse lire les fichiers crées par amavis, il faut ajouter l'utilisateur clamav au groupe amavis : adduser clamav amavis

Ensuite, vous devez modifier le fichier de cofiguration /etc/amavis/amavisd.conf

#ce domaine correspond au domaine local si vous n'avez pas de domaine local utilisez 'localhost'
$mydomain = 'yourdomain.org';

# @bypass_virus_checks_acl = qw( . );  # uncomment to DISABLE anti-virus code
# @bypass_spam_checks_acl  = qw( . );  # uncomment to DISABLE anti-spam code

#amavis doit connaitre les domaines à controler (en effet il controle seulement les mails entrants)
@lookup_sql_dsn = ( [ 'DBI:mysql:postfix;host=127.0.0.1;port=3306', 'postfix', 'pass' ] );
$sql_select_policy =
    'SELECT "Y" as local FROM domains WHERE CONCAT("@",domain) IN (%k) AND actif="1"';

$final_virus_destiny      = D_DISCARD; # (defaults to D_BOUNCE)
$final_banned_destiny     = D_BOUNCE;  # (defaults to D_BOUNCE)
$final_spam_destiny       = D_REJECT;  # (defaults to D_REJECT)
$final_bad_header_destiny = D_PASS;  # (defaults to D_PASS), D_BOUNCE suggested

SpamAssassin (facultatif)

Installation

apt-get install spamassassin libnet-dns-perl libmail-spf-query-perl \
                             libnet-ident-perl libio-socket-ssl-perl libsys-hostname-long-perl \
                             razor pyzor dcc-client

Configuration

Pour améliorer l'analyse des emails par spamassassin, il faut utiliser le démons spamd. Pour cela, modifiez le fichier /etc/default/spamassassin

ENABLED=1

Puis, relancez le démon spamd : /etc/init.d/spamassassin restart

Nous allons utiliser amavis pour appeler le filtre spamasssin. La configuration de Amavis est prête à l'utiliser. Il suffit de modifier quelques lignes dans /etc/amavis/amavisd.conf

# @bypass_virus_checks_acl = qw( . );  # uncomment to DISABLE anti-virus code
# @bypass_spam_checks_acl  = qw( . );  # uncomment to DISABLE anti-spam code
#
# Any setting can be changed with a new assignment, so make sure
# you do not unintentionally override these settings further down!
# @bypass_spam_checks_acl  = qw( . );    # No default dependency on spamassassin

$sa_local_tests_only = 0;

$sa_tag_level_deflt = -1000; # note minimal pour ajouter les tags X-Spam... à l'en-tête des emails
$sa_tag2_level_deflt = 3.5;  # note minimal pour ajouter le tag X-Spam-Flag: YES
                             # et modifier l'objet
$sa_kill_level_deflt = 10;   # note à partir de laquelle les mails sont traités comme définis
                             # par la variable $final_spam_destiny (ici ils sont refusés)
$sa_spam_subject_tag = '***SPAM*** '; # chaine ajouté à l'objet de l'email