Richard Dern

Installation de son propre serveur mail

Le quatrième article de la nouvelle rubrique va donc traiter de l’installation de son propre serveur mail, élément indispensable de la chaîne de communication. Il existe déjà de nombreux tutoriels sur Internet, parfois très bien faits, parfois incomplets ou inadaptés. Je ne prétends pas que mon article sera mieux que les autres, j’espère seulement qu’il trouvera son public.

Notre serveur mail devra être sécurisé : nous ferons appel au chiffrement, ainsi qu’à diverses applications permettant de filtrer spam et virus, le plus efficacement possible, sans pour autant bloquer les correspondances légitimes (il m’est arrivé que certaines personnes utilisant un serveur SMTP wanadoo (sic) se retrouvent bloquées par mon serveur, à cause d’un non respect du protocole SMTP…).

Nous utiliserons le serveur SMTP postfix, aux côtés duquel tournera le serveur IMAP dovecot. Le filtrage sera confié à Spamassassin, amavis et clamav. Nous aurons recourt à une base de données de type MySQL. Même si vous ne gérerez qu’un seul domaine, virtualiser les utilisateurs et les domaines n’est pas plus consommateur de ressources : MySQL (ou tout autre serveur de bases de données, j’aurai pu traiter de postgreSQL s’il ne me manquait pas de l’expérience) sera installé tôt ou tard, autant l’utiliser tout de suite. Et si par la suite vous acquérez un autre domaine et que vous vouliez proposer un service mail pour ce domaine, vous n’aurez pas de migration fastidieuse à effectuer.

Lorsque debconf vous demandera un mot de passe pour MySQL (et par extension, chaque fois que vous devrez saisir un mot de passe dans les prochains articles), vous devriez considérer utiliser un générateur de mot de passe. En utilisant un tel outil, vous pourrez générer des mots de passe complexes, de la longueur et de la complexité que vous voulez.

Sous debian donc, on installe les paquets suivants :

apt-get install amavisd-new arj bzip2 cabextract clamav clamav-freshclam clamav-daemon cpio dovecot-imapd gzip lha mysql-server p7zip pax postfix postfix-mysql postfix-pcre ripole rpm spamassassin tar unrar-free unzip xz-utils zip zoo

Outre postfix, dovecot, l’anti-virus et l’anti-spam, on installe également quelques utilitaires appelés par amavis/clamav pour analyser les pièces jointes aux futurs mails qui seront envoyés ou reçus par votre serveur. On passe ensuite à la configuration de MySQL.

MySQL

debconf vous a probablement demandé de choisir un mot de passe pour l’utilisateur root (celui de MySQL). Vous devez maintenant créer un nouvel utilisateur pour la première base de données que nous allons créer, et qui sera exploitée par notre serveur mail.

mysql -u root -pVotreMotDePasse

Notice : -p

Saisissez alors les commandes suivantes, en remplaçant NouveauMotDePasse par un nouveau mot de passe, différent de celui de root (là encore, pensez à utiliser le générateur de mots de passe) :

CREATE USER 'MailServer'@'localhost' IDENTIFIED BY 'NouveauMotDePasse';
GRANT USAGE ON * . * TO 'MailUser'@'localhost' IDENTIFIED BY 'NouveauMotDePasse';
CREATE DATABASE IF NOT EXISTS `MailServer` ;
GRANT ALL PRIVILEGES ON `MailServer` . * TO 'MailServer'@'localhost';

Nous avons créé un nouvel utilisateur nommé MailServer, et une base de données dans laquelle il a tout privilège. Créons ensuite la structure :

USE MailServer;
CREATE TABLE `access_sender` (
 `source` varchar(128) CHARACTER SET utf8 NOT NULL DEFAULT '',
 `access` varchar(128) CHARACTER SET utf8 NOT NULL DEFAULT '',
 `created` datetime NOT NULL,
 `modified` datetime NOT NULL,
 `active` tinyint(1) NOT NULL DEFAULT '1',
 UNIQUE KEY `source` (`source`)
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Virtual Sender Restrictions';
CREATE TABLE `aliases` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `source` varchar(255) CHARACTER SET utf8 NOT NULL,
 `destination` varchar(255) CHARACTER SET utf8 NOT NULL,
 PRIMARY KEY (`id`)
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE `domains` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(255) CHARACTER SET utf8 NOT NULL,
 PRIMARY KEY (`id`)
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE `users` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `email` varchar(255) CHARACTER SET utf8 NOT NULL,
 `password` varchar(32) CHARACTER SET utf8 NOT NULL,
 PRIMARY KEY (`id`)
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
quit;

Nous avons créé respectivement la table qui contiendra les adresses emails toujours autorisées à nous envoyer quelque chose, quelle que soit la politique de filtrage de notre postfix, la table contenant les futurs alias, celle contenant les domaines et enfin celle qui contiendra nos utilisateurs. La base de données est configurée, nous pouvons passer à la suite.

Postfix

Pour que Postfix utilise la base de données que l’on vient de créer, il faut créer quelques fichiers de configuration que nous allons placer dans le répertoire /etc/postfix/mysql :

/etc/init.d/postfix stop
mkdir /etc/postfix/mysql

Créez ensuite les fichiers suivants (n’oubliez pas de renseigner à chaque fois la variable password avec le mot de passe que vous avez attribué à l’utilisateur MailServer) :

cd /etc/postfix/mysql
nano alias.cf
user = MailServer
password =
hosts = 127.0.0.1
dbname = MailServer
query = SELECT destination FROM aliases WHERE source='%s'
nano domains.cf
user = MailServer
password =
hosts = 127.0.0.1
dbname = MailServer
query = SELECT 1 FROM domains WHERE name='%s'
nano email2email.cf
user = MailServer
password =
hosts = 127.0.0.1
dbname = MailServer
query = SELECT email FROM users WHERE email='%s'
nano maps.cf
user = MailServer
password =
hosts = 127.0.0.1
dbname = MailServer
query = SELECT 1 FROM users WHERE email='%s'
nano senders_whitelist.cf
user = MailServer
password =
hosts = 127.0.0.1
dbname = MailServer
query = SELECT access FROM access_sender WHERE source='%s' AND active = '1'

Nous venons simplement de créer les fichiers permettant de communiquer avec les tables créées précédemment. Modifions ensuite la configuration principale de postfix, à commencer par le fichier main.cf. Nous allons créer une nouvelle configuration en partant de rien, on va donc déplacer le fichier d’origine et en créer un nouveau :

cd ../
mv main.cf main.cf.orig
nano main.cf

Copiez-y ensuite la configuration suivante :

mynetworks = 127.0.0.0/8

# Dovecot settings
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1

# MySQL settings
virtual_mailbox_domains = mysql:/etc/postfix/mysql/domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql/maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql/alias.cf,mysql:/etc/postfix/mysql/email2email.cf

# SASL
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

# TLS
smtp_tls_CAfile = /scripts/certificate_authority/ca.crt
smtpd_tls_CAfile = /scripts/certificate_authority/ca.crt
smtpd_tls_cert_file = /scripts/certificate_authority/exemple.fr.crt
smtpd_tls_key_file = /scripts/certificate_authority/exemple.fr.key
smtpd_tls_received_header = yes
tls_random_source = dev:/dev/urandom
smtp_tls_security_level = may
smtpd_tls_security_level = may
smtp_use_tls = yes
smtpd_use_tls = yes
smtpd_tls_auth_only = no
#smtpd_tls_wrappermode = yes
smtpd_tls_loglevel = 1

# Filtering
content_filter = smtp-amavis:[127.0.0.1]:10024
receive_override_options = no_address_mappings

# Restrictions
unknown_address_reject_code = 554
unknown_hostname_reject_code = 554
unknown_client_reject_code = 550
unverified_sender_reject_code = 554
smtpd_helo_required = yes
strict_rfc821_envelopes = yes

smtpd_recipient_restrictions =
    reject_non_fqdn_sender,
    reject_unknown_sender_domain,
    reject_non_fqdn_recipient,
    reject_unknown_recipient_domain,
    permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination,
    check_helo_access pcre:/etc/postfix/helo_checks.pcre,
    reject_invalid_helo_hostname,
    reject_non_fqdn_helo_hostname,
    check_sender_access mysql:/etc/postfix/mysql/senders_whitelist.cf,
    reject_rbl_client zen.spamhaus.org

Important : main.cf

Il faut créer le fichier helo_checks.pcre. En utilisant les expressions rationnelles, cela permettra à postfix d’opérer un filtrage sur la commande helo du protocole SMTP.

nano helo_checks.pcre
/^localhost$/            550 Don’t use localhost
/^(base\.)?(exemple\.fr|exemple2\.fr)$/ 550 Don’t use my own domain/hostname
/^\[?88\.190\.15\.133\]?$/
   550 Spammer comes to me \
       Greets me with my own IP \
       His mail I shall not see.
/^[0-9.-]+$/
   550 Your software is not RFC 2821 compliant: \
       EHLO/HELO must be a domain or an \
       address-literal (IP enclosed in brackets)

On modifie ensuite le fichier master.cf :

nano master.cf

Dé-commentez la ligne (située en début du fichier) :

smtps inet n - - - - smtpd

Et rajoutez les lignes suivantes :

dovecot unix - n n - - pipe
    flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d ${recipient}
smtp-amavis unix - - n - 2 smtp
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20
127.0.0.1:10025 inet n - n - - smtpd
    -o content_filter=
    -o smtpd_restriction_classes=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o smtpd_data_restrictions=reject_unauth_pipelining
    -o smtpd_end_of_data_restrictions=
    -o mynetworks=127.0.0.0/8
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
    -o local_header_rewrite_clients=

Ces lignes servent à interfacer dovecot et amavis avec postfix. Il nous reste encore à créer les certificats.

/scripts/certificate_authority/make_request postfix mail.exemple.fr

Notice : Common Name

mail.exemple.fr

Signez ensuite le certificat :

/scripts/certificate_authority/sign_request postfix mail.exemple.fr

La configuration de postfix étant terminée, on s’occupe des filtres.

Filtres

/etc/init.d/amavis stop
/etc/init.d/clamav-daemon stop
/etc/init.d/clamav-freshclam stop
adduser clamav amavis
adduser amavis clamav

Important : amavis

clamav

clamav

amavis

On édite ensuite la configuration de amavis :

nano /etc/amavis/conf.d/15-content_filter_mode

Dé-commentez les lignes dans ce fichier pour qu’il ressemble à ceci :

use strict;

@bypass_virus_checks_maps = (
   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);

@bypass_spam_checks_maps = (
   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

1;  # ensure a defined return

Puis :

nano /etc/amavis/conf.d/20-debian_defaults

Vers la ligne 68, assurez-vous d’avoir les directives de configuration suivantes :

$final_virus_destiny      = D_DISCARD;  # (data not lost, see virus quarantine)
$final_banned_destiny     = D_BOUNCE;   # D_REJECT when front-end MTA
$final_spam_destiny       = D_BOUNCE;
$final_bad_header_destiny = D_PASS;     # False-positive prone (for spam)

On bloque ainsi totalement les virus, mais on laisse passer le spam (qui sera tagué par la suite) pour éviter de supprimer du courrier légitime.

On continue :

nano /etc/amavis/conf.d/50-user
use strict;

#
# Place your configuration directives here.  They will override those in
# earlier files.
#
# See /usr/share/doc/amavisd-new/ for documentation and examples of
# the directives you can use in this file
#

$sa_spam_subject_tag = '***** SPAM ***** ';
$spam_quarantine_to  = undef;
$sa_tag_level_deflt  = undef;
$final_spam_destiny=D_PASS;

@lookup_sql_dsn = (
    ['DBI:mysql:database=MailServer;host=127.0.0.1;port=3306',
     'MailServer',
     'MotDePasse']);

$sql_select_policy = 'SELECT name FROM domains WHERE CONCAT("@",name) IN (%k)';

#------------ Do not modify anything below this line -------------
1;  # ensure a defined return

On peut maintenant démarrer les services :

/etc/init.d/amavis start
/etc/init.d/clamav-daemon start
/etc/init.d/clamav-freshclam start

Dovecot

/etc/init.d/dovecot stop
cd /etc/dovecot

Configurons tout d’abord la connexion au serveur MySQL :

mv dovecot-sql.conf dovecot-sql.conf-orig
nano dovecot-sql.conf
driver = mysql
connect = host=127.0.0.1 dbname=MailServer user=MailServer password=MotDePasse
default_pass_scheme = PLAIN-MD5
password_query = SELECT email AS user, password FROM users WHERE email='%u'

Comme d’habitude, pensez à changer le mot de passe, et mettez celui de l’utilisateur MySQL MailServer. Enregistrez puis fermez, avant de modifier la configuration principale :

mv dovecot.conf dovecot.conf-orig
nano dovecot.conf
base_dir = /var/run/dovecot
protocols = imaps managesieve

ssl = yes
ssl_cert_file = /scripts/certificate_authority/dovecot/mail.exemple.fr.crt
ssl_key_file = /scripts/certificate_authority/dovecot/mail.exemple.fr.key
ssl_key_password = MotDePasse

mail_location = maildir:/var/vmail/%d/%n/Maildir

mail_uid = vmail
mail_gid = vmail

mail_privileged_group = mail

protocol imap {
}

protocol managesieve {
    login_executable = /usr/lib/dovecot/managesieve-login
    mail_executable = /usr/lib/dovecot/managesieve
}

protocol lda {
    postmaster_address = postmaster@exemple.fr
    auth_socket_path = /var/run/dovecot/auth-master
    mail_plugins = sieve
}

auth_executable = /usr/lib/dovecot/dovecot-auth

auth default {
    mechanisms = plain login

    passdb sql {
        args = /etc/dovecot/dovecot-sql.conf
    }

    userdb static {
        args = uid=5000 vid=5000 home/var/vmail/%d/%n
    }

    user = root

    socket listen {
        master {
            path = /var/run/dovecot/auth-master
            mode = 0600

            user = vmail
            group = vmail
        }
        client {
            path = /var/spool/postfix/private/auth
            mode = 0660
            user = postfix
            group = postfix
        }
    }
}

plugin {
    sieve=/var/vmail/%d/%n/Maildir/sieve/.dovecot.sieve
    sieve_dir=/var/vmail/%d/%n/Maildir/sieve
    sieve_global_path = /etc/sieve/sieve.global
}

Lorsque nous allons générer le certificat et la clé à utiliser avec dovecot, vous aurez la possibilité de créer une clé sans mot de passe. Si vous choisissez de créer une clé sans mot de passe, commentez la ligne ssl_key_password = MotDePasse. Dans le cas contraire, indiquez le mot de passe utilisé lors de la génération du certificat.

Quelques répertoires vont devoir être créés :

mkdir /etc/sieve
mkdir /var/vmail

On génère les certificats :

/scripts/certificate_authority/make_request dovecot mail.exemple.fr
/scripts/certificate_authority/sign_request dovecot mail.exemple.fr

On créé ensuite l’utilisateur vmail :

addgroup vmail --gid 5000
adduser --system --disabled-password --no-create-home --disabled-login --uid 5000 --gid 5000 vmail
chown -R vmail:vmail /var/vmail

On peut désormais redémarrer dovecot :

/etc/init.d/dovecot restart

Nous avons configuré dovecot pour utiliser le plugin sieve/managesieve. Cela nous permettra plus tard de mettre en place des filtres pour la messagerie.

Créons tout de même le fichier de configuration de base pour sieve, dont le rôle va être simplement de déplacer le spam dans le bon répertoire :

nano /etc/sieve/sieve.global
require ["fileinto"];
# rule:[Spam]
if header :contains "Subject" "***** SPAM *****"
{
    fileinto "Spam";
}

Quelques tests

Installez le paquet telnet si vous ne l’avez pas déjà :

apt-get install telnet
telnet localhost 25
ehlo exemple.fr
quit

Vous devriez avoir une sortie console qui ressemble à ceci :

Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 minerva.localdomain ESMTP Postfix
ehlo exemple.fr
250-minerva.localdomain
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

Procédez de même avec le port 465, la sortie doit être la même.

Pour tester le serveur IMAP, nous devons créer un premier domaine, puis un premier utilisateur du domaine :

mysql -u root -pMotDePasse
USE MailServer;
INSERT INTO domains (name) VALUES ('exemple.fr');
INSERT INTO users (email, password) VALUES ('test@exemple.fr', MD5('MotDePasse'));
quit;

On peut ensuite tester le serveur IMAP :

openssl s_client -connect localhost:993

La dernière ligne affichée devrait ressembler à ceci :

* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE AUTH=PLAIN AUTH=LOGIN] Dovecot ready.

Suite à quoi, écrivez :

A LOGIN test@exemple.fr MotDePasse

La fin de la ligne suivante devrait afficher “Logged in”. Concluez la session avec :

a5 LOGOUT

Nous testerons plus tard les anti-virus et anti-spam. Pour l’heure, nous avons une dernière chose à régler.

Firewall

nano /scripts/firewall

Entre les lignes :

##### Configuration personnalisée #####

Et :

##### Fin : Configuration personnalisée #####

Rajoutez les lignes suivantes :

${IPT} -A SERVICES -p tcp --dport 25 -j ACCEPT
${IPT} -A SERVICES -p tcp --dport 465 -j ACCEPT

Ce sont les deux ports à ouvrir pour que votre serveur SMTP puisse communiquer avec l’extérieur (et vice-versa).

Important : ```text ${IPT} -A SERVICES -p tcp –dport 993 -j ACCEPT


Cette commande permet d'ouvrir le port 993, qui est le port attribué au serveur IMAP sécurisé.
Nous n'utiliserons donc pas le port habituel, le 143.

## DNS

Dernière étape de l'installation de notre serveur mail, la modification de la configuration de notre serveur DNS pour sa prise en compte.
On édite donc le fichier de définition de notre zone :

```bash
nano /etc/bind/db.exemple.fr

Et on rajoute à la fin (sans oublier de modifier l’identifiant de l’enregistrement !) :

		IN	MX	10	mail.exemple.fr.
mail		IN	A		1.1.1.1

Et on redémarre bind :

/etc/init.d/bind9 restart

C’est aussi simple que ça !

La prochaine étape consistera à installer un serveur web sécurisé, et quelques applications utiles, dont un client de messagerie pour jouer avec le serveur mail que l’on vient d’installer.

Échanger autour de ce texte

Si vous souhaitez réagir publiquement, un fil dédié vous attend.

Ouvrir le fil de discussion

Taxonomies

Tags