Table des matières

Configuration d'un serveur de courriers

Cette page est en cours de réécriture.

Description d’une méthode d’installation d’un serveur de courriel Postfix, sur une distribution Linux Debian (Buster) possédant déjà une configuration avec un serveur DNS (BIND) et une base de données MySQL (MariaDB), avec les éléments suivants :

Installation de paquets

Il est conseillé d’avoir installé et configuré rkhunter.

apt update && apt-get upgrade
apt purge exim4 exim4-base exim4-config exim4-daemon-light
apt install postfix postfix-mysql postfix-policyd-spf-python postgrey dovecot-core dovecot-imapd dovecot-lmtpd dovecot-mysql dovecot-sieve dovecot-antispam opendkim opendkim-tools amavisd-new clamav-daemon monit opendmarc spamassassin spamc mailutils

Pendant l'installation de Postfix, il faudra choisir “internet site”, entrer comme nom du système FQDN de courrier la valeur de la commande hostname -f ou si elle renvoie juste le nom du serveur entrer la valeur complète avec le nom de domaine, cela ressemblera à hostname.domaine.tld ou à domaine.tld.

Sous Debian 10 (Buster), Monit n'est plus disponible dans les dépôts,

voir Install monit in Debian 10 (buster) et cette page pour l'installation des backports.

Définition du "hostname"

La machine doit avoir un nom de machine et de domaine complet, cela est à définir dans le fichier /etc/hosts :

127.0.0.1	localhost
127.0.1.1	hostname.domaine.eu	hostname

Pour tester la configuration :

root@hostname:~# hostname -s
hostname
root@hostname:~# hostname -d
domaine.eu
root@hostname:~# hostname -f
hostname.domaine.eu

Mais aussi la zone PTR de recherche inversée doit être configurée, la commande dig -x doit renvoyer la valeur de hostname -f.

Configuration additionnelle

Les ports TCP 25, 465, 587 et 993 du firewall doivent être ouvert.

Installation et configuration de phpMyAdmin

Pour Debian et Ubuntu il existe un paquet dans les dépôts, cependant, au moment où j'écris cette page, il existe un bug dans l'installation. J’ai donc choisi d'installer la dernière version à partir des sources.

Vérifier les sources

Pour vérifier l’intégrité des fichiers (somme de contrôle et signature GPG), le détail est expliqué ici.

Création d’un serveur virtuel Apache2

VirtualHost sur le port 80

Je crée un VirtualHost sur le port 80, j'ajouterai ensuite une redirection sur le port 443, mais avant de décommenter RewriteRule il me faudra générer un certificat SSL.

<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com
        ServerName pma.hostname.domaine.eu
        ServerAlias pma.hostname.domaine.eu
        ServerAdmin webmaster@domaine.eu
        DocumentRoot /var/www/pma
        RewriteEngine On
        #RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [redirect=301]
 
        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn
 
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
 
</VirtualHost>

Création d’un certificat avec Let’s Encrypt

certbot certonly --webroot -w /var/www/pma -d pma.hostname.domaine.eu --email webmaster@domaine.eu --rsa-key-size 4096

VirtualHost sur le port 443

La directive RewriteRule peut maintenant être décommentée, ensuite il faut créer un VirtualHost afin d'utiliser SSL. J'utilise ici une configuration restrictive, il faudra peut-être une configuration plus souple (voir Server Side TLS ) si de nombreux clients doivent se connecter.

<IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerName pma.hostname.domaine.eu
        ServerAlias pma.hostname.domaine.eu
        ServerAdmin webmaster@domaine.eu
 
        DocumentRoot /var/www/pma
 
        <Directory />
                Options SymLinksIfOwnerMatch
                AllowOverride None
                Require all denied
        </Directory>
 
        <Directory /var/www/pma/>
                Options -Indexes -FollowSymLinks +MultiViews
                AllowOverride All
                # restreindre l'accés à certaines adresses IP
                Require ip 0.0.0.1 0.0.0.2
        </Directory>
 
        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
        <Directory "/usr/lib/cgi-bin">
                AllowOverride None
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Require all denied
        </Directory>
 
        ErrorLog ${APACHE_LOG_DIR}/error.log
 
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn
 
        CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined
        Alias /doc/ "/usr/share/doc/"
        <Directory "/usr/share/doc/">
                Options Indexes MultiViews FollowSymLinks
                AllowOverride None
                Require ip 127.0.0.0/255.0.0.0 ::1/128
        </Directory>
 
        # enable HTTP/2, if available
        Protocols h2 http/1.1
        #   SSL Engine Switch:
        #   Enable/Disable SSL for this virtual host.
        SSLEngine on
        # The CRIME attack uses SSL Compression, we need to disable that
        SSLCompression off
        SSLProtocol +TLSv1.3 -TLSv1.2 -TLSv1.1 -TLSv1 -SSLv3 -SSLv2
        SSLCipherSuite TLSv1.3  TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
        SSLHonorCipherOrder on
        SSLSessionTickets off
        SSLUseStapling On
        # SSLStaplingCache must be exist in /etc/apache2/mods-available/ssl.conf,
        # see https://itigloo.com/security/how-to-configure-ocsp-stapling-on-apache-http-server/
        # SSLOpenSSLConfCmd is supported by version 2.5 and later
        # SSLOpenSSLConfCmd DHParameters  /etc/ssl/private/dh4096.pem
        SSLCertificateFile      /etc/letsencrypt/live/pma.hostname.domaine.eu/cert.pem
        SSLCertificateKeyFile   /etc/letsencrypt/live/pma.hostname.domaine.eu/privkey.pem
        <IfModule mod_headers.c>
                Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"
                Header always set X-Content-Type-Options "nosniff"
                Header always set X-Frame-Options "DENY"
                Header always set X-XSS-Protection "1; mode=block"
                Header set Content-Security-Policy-Report-Only "default-src 'self'"
        </IfModule>
 
        #   Certificate Authority (CA):
        #   Set the CA certificate verification path where to find CA
        #   certificates for client authentication or alternatively one
        #   huge file containing all of them (file must be PEM encoded)
        #   Note: Inside SSLCACertificatePath you need hash symlinks
        #         to point to the certificate files. Use the provided
        #         Makefile to update the hash symlinks after changes.
        #SSLCACertificatePath /etc/ssl/certs/
        SSLCACertificateFile /etc/letsencrypt/live/pma.hostname.domaine.eu/fullchain.pem
 
</VirtualHost>
</IfModule>

Configuration

La configuration se fait via le fichier config.inc.php, voir cette page. Pour configurer $cfg['blowfish_secret'], voir la documentation. Pour générer le secret, la commande suivante peut-être utilisée ou tout autre générateur de code, 32 caractères est un minimum.

openssl rand -base64 64

Authentification à deux facteurs

Pour activer le double facteur, voir la page sur le double-facteur puis suivre les instructions de la documentation pour installer les tables de stockage.

mysqldump -u root --events --routines --triggers --lock-tables --all-databases > /srv/backups/mysqldump/MySQLDatap-`date +"%Y%m%d"`.sql
cd /var/www/pma/sql
mysql < create_tables.sql -u root

Et pour toute version de MariaDB :

mysql -u root
root@localhost [(none)]>  CREATE USER 'pma'@'localhost' IDENTIFIED VIA mysql_native_password USING 'pmapass';
root@localhost [(none)]>  GRANT SELECT, INSERT, UPDATE, DELETE ON `<pma_db>`.* TO 'pma'@'localhost';

En cas d’erreur :

root@localhost [(none)]>  CREATE USER 'pma'@'localhost' ;
root@localhost [(none)]>  SET PASSWORD FOR 'pma'@'localhost' = PASSWORD('00000000');
root@localhost [(none)]>  GRANT SELECT, INSERT, UPDATE, DELETE ON `<pma_db>`.* TO 'pma'@'localhost';

Mise à jour

Ne jamais extraire une nouvelle version de phpMyAdmin par-dessus une version déjà existante. Toujours supprimer d’abord les anciens fichiers en ne conservant que la configuration. De cette manière, vous ne laisserez pas de fichiers vieux ou périmés dans le répertoire, ce qui peut avoir de sérieuses implications de sécurité et provoquer divers dysfonctionnements, voir https://docs.phpmyadmin.net/fr/latest/setup.html#upgrading-from-an-older-version.

Configuration de la base de données

Pour un meilleur prompt MySQL il faut ajouter dans le fichier .profile la variable suivante :

# Display username, hostname and current database name in the mysql prompt
export MYSQL_PS1="\u@\h [\d]> "

Mais surtout il faut exécuter ces commandes pour la création de la base de données :

mysql -u root -p
CREATE DATABASE db_mail;
CREATE USER "nom_utilisateur"@"localhost";
SET PASSWORD FOR 'nom_utilisateur'@'localhost' = PASSWORD('00000000');
GRANT ALL PRIVILEGES ON db_mail.* TO 'nom_utilisateur'@'localhost' IDENTIFIED BY '00000000';
FLUSH PRIVILEGES;
use db_mail;

Pour ensuite créer les tables avec la commande :

mysql -h localhost -u root -p db_mail < db-mail.sql

Le premier tableau contiendra les domaines que nous utiliserons avec le serveur de messagerie, ensuite le concont contiendra les utilisateurs et leur mot de passe, enfin la dernière table contiendra les alias de messagerie :

db-mail.sql
USE db_mail;
CREATE TABLE `domain` (
	id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	name VARCHAR(64) NOT NULL
) ENGINE = InnoDB DEFAULT CHARSET=utf8;
 
CREATE TABLE `user` (
	id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	domain_id INT UNSIGNED NOT NULL,
	`user` VARCHAR(64) NOT NULL,
	password VARCHAR(128) NOT NULL,
	CONSTRAINT UNIQUE_EMAIL UNIQUE (domain_id,USER),
	FOREIGN KEY (domain_id) REFERENCES DOMAIN(id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET=utf8;
 
CREATE TABLE `alias` (
	id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	domain_id INT UNSIGNED NOT NULL,
	SOURCE VARCHAR(64) NOT NULL,
	destination VARCHAR(128) NOT NULL,
	FOREIGN KEY (domain_id) REFERENCES DOMAIN(id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET=utf8;

Postfix doit savoir comment accéder à cette base, créons les fichiers de configuration dans le dossier /etc/postfix/mysql

mkdir /etc/postfix/mysql

Pour que Postfix puisse connaître les adresses emails existantes, nous créons email2email.cf

email2email.cf
hosts = 127.0.0.1
dbname = db_mail
user = nom_utilisateur
password = xxxxxxxx
query = SELECT CONCAT(user.user, '@', domain.name) AS email FROM domain,user WHERE user.domain_id=domain.id AND CONCAT(user.user, '@', domain.name)='%s'

Et pour que Postfix puisse connaître les alias (redirections emails) virtual-alias-maps.cf

virtual-alias-maps.cf
hosts = 127.0.0.1
dbname = db_mail
user = nom_utilisateur
password = xxxxxxxx
query = SELECT destination FROM alias, domain WHERE alias.domain_id=domain.id AND CONCAT(alias.source, '@', domain.name)='%s'

Puis pour que Postfix puisse connaître les domaines gérés virtual-mailbox-domains.cf

virtual-mailbox-domains.cf
hosts = 127.0.0.1
dbname = db_mail
user = nom_utilisateur
password = xxxxxxxx
query = SELECT 1 FROM domain WHERE name='%s'

Enfin pour vérifier si une adresse email est bien gérée par le serveur virtual-mailbox-maps.cf

virtual-mailbox-maps.cf
hosts = 127.0.0.1
dbname = db_mail
user = nom_utilisateur
password = xxxxxxxx
query = SELECT 1 FROM user,domain WHERE user.domain_id=domain.id AND CONCAT(user.user, '@', domain.name)='%s'

Notons que nous ne pouvons pas utiliser “localhost”, car Postfix tourne dans un contexte restreint, il n'a pas le droit d'accéder au socket mysql. Le fait de forcer l'hôte à 127.0.0.1 impôse à Postfix de passer par une connexion TCP. Ensuite assurons-nous que root et postfix soient les seuls à pouvoir accéder à ces fichiers de configuration (ils contiennent des identifiants pour MySQL) :

chgrp -R postfix /etc/postfix/mysql
chmod 750 /etc/postfix/mysql
chmod 640 /etc/postfix/mysql/*.cf

Domaines, utilisateurs et alias

Avec phpMyAdmin, nous nous connectons à la base de données du serveur de courrier db_mail avec notre compte postmaster, puis nous créons notre domaine dans la table domaine (s’il n'existe pas), ensuite dans la table user nous ajoutons un utilisateur en indiquant l’identifiant du domaine et le hash de son mot de passe. Pour obtenir le hash, nous utiliserons la commande :

doveadm pw -s SHA512-CRYPT

Il faut utiliser le retour de cette commande sans la partie {SHA512-CRYPT}, à partir de $6$.

La commande postmap permet de vérifier le fonctionnement :

postmap -q domaine.eu mysql:/etc/postfix/mysql/virtual-mailbox-domains.cf
postmap -q example@domaine.eu mysql:/etc/postfix/mysql/virtual-mailbox-maps.cf
postmap -q alias@domaine.eu mysql:/etc/postfix/mysql/virtual-alias-maps.cf

Configuration de Postfix

Faisons une sauvegarde des fichiers d’origine.

cp /etc/postfix/main.cf /etc/postfix/main.cf.original.bak
cp /etc/postfix/master.cf /etc/postfix/master.cf.original.bak

Création d’un utilisateur et d’un groupe

groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/mail -m -s /bin/false

Création d’un certificat avec Let’s Encrypt

Configurons Postfix pour utiliser TLS avec un certificat Let’s Encrypt :

apt install python3-pip python3-dnslib
pip3 install certbot-dns-standalone
systemctl stop postfix
certbot --non-interactive --agree-tos --email webmaster@domaine.eu certonly \
  --preferred-challenges dns --authenticator certbot-dns-standalone:dns-standalone \
  --certbot-dns-standalone:dns-standalone-address=0.0.0.0 \
  --certbot-dns-standalone:dns-standalone-ipv6-address=:: \
  --certbot-dns-standalone:dns-standalone-port=53 \
  -d mail.domaine.eu --email webmaster@domaine.eu --rsa-key-size 4096
systemctl start postfix

Pour comprendre cette commande, vous pouvez regarder la documentation de Cerbot.

Les fichiers générés se trouvent dans le répertoire /etc/letsencrypt/live/mail.domaine.eu/.

Création des fichiers pour les paramètres DH (Diffie-Helmann)

Ces fichiers s’utilisent dans les paramètres DH (Diffie-Helmann) que le serveur SMTP doit utiliser avec le chiffrement EDH. Ces paramêtres sont smtpd_tls_dh1024_param_file et smtpd_tls_dh1024_param_file, ils se trouvent dans le fichier main.cd de Postfix. Il est possible de générer des paramètres avec des valeurs supérieures à celles par défaut afin d’améliorer la sécurité contre les attaques et pour assurer la compatibilité avec les clients SMTP Exim sous Debian qui nécessitent une longueur de ≥ 2048 bits.

openssl dhparam -outform PEM -out dh2048.pem -rand /dev/urandom 2048
openssl dhparam -outform PEM -out dh512.pem -rand /dev/urandom 512

Attention, les serveurs possèdent souvent une entropie faible, il est préférable de générer ces fichiers sur une machine en possédant. Il faut ensuite donner des droits d'accés faibles à ces fichiers.

chmod 644 dh512.pem dh2048.pem

Configuration du fichier master.cf

Dans le fichier master.cf, il faut décommenter la ligne de smtps et vérifier la présence des options suivantes :

# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       y       -       -       smtpd
#smtp      inet  n       -       y       -       1       postscreen
#smtpd     pass  -       -       y       -       -       smtpd
#dnsblog   unix  -       -       y       -       0       dnsblog
#tlsproxy  unix  -       -       y       -       0       tlsproxy
#submission inet n       -       y       -       -       smtpd
#  -o syslog_name=postfix/submission
#  -o smtpd_tls_security_level=encrypt
#  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_tls_auth_only=yes
#  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
#  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
#  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING

puis ajouter ces lignes à la fin de ce fichier afin de permettre à Postfix de communiquer avec Dovecot :

dovecot   unix  -       n       n       -       -       pipe
  flags=DRhu user=vmail:vmail argv=/usr/bin/sudo /usr/lib/dovecot/deliver -d ${recipient}

Pour fonctionner, ces éléments doivent exécuter des commandes avec les droits root, mais comme pour des raisons de sécurité ils ne doivent pas connaître le mot de passe de ce super-utilisateur nous créons le fichier  /etc/sudoers.d/mail. Si le dossier n’existe pas il faudra installer sudo.

apt install sudo
vi /etc/sudoers.d/mail
mail
Defaults:postfix !syslog
postfix ALL=NOPASSWD:/usr/lib/dovecot/deliver
Defaults:clamav !syslog
clamav ALL=NOPASSWD:/usr/lib/dovecot/deliver
Defaults:dovecot !syslog
dovecot ALL=NOPASSWD:/usr/lib/dovecot/deliver
Defaults:dspam !syslog
dspam ALL=NOPASSWD:/usr/lib/dovecot/deliver
Defaults:vmail !syslog
vmail ALL=NOPASSWD:/usr/lib/dovecot/deliver

Nous devons appliquer des droits à ce fichier :

chmod 0440 /etc/sudoers.d/mail

Configuration main.cf

Le fichier main.cf de configuration Postfix doit contenir ces valeurs :

main.cf
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
 
config_directory = /etc/postfix
disable_vrfy_command = yes
smtpd_helo_required = yes
 
queue_directory = /var/spool/postfix
 
# appending .domain is the MUA's job.
append_dot_mydomain = no
 
# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h
 
readme_directory = no
 
# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on
# fresh installs.
compatibility_level = 2
 
# TLS parameters
smtpd_use_tls=yes
smtpd_tls_auth_only = yes
smtpd_tls_cert_file=/etc/letsencrypt/live/mail.streetdispatch.org/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mail.streetdispatch.org/privkey.pem
smtpd_tls_CAfile=/etc/letsencrypt/live/mail.streetdispatch.org/chain.pem
smtpd_tls_CApath=/etc/ssl/certs
smtpd_tls_mandatory_protocols=!SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_mandatory_exclude_ciphers = eNULL, aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA, CAMELLIA128, CAMELLIA256, 3DES
smtpd_tls_mandatory_ciphers=high
smtpd_tls_protocols=!SSLv2,!SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_exclude_ciphers = eNULL, aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA, CAMELLIA128, CAMELLIA256, 3DES
smtpd_tls_ciphers = high
smtpd_tls_security_level = may
smtpd_tls_dh1024_param_file = /etc/postfix/dh_4096.pem
smtpd_tls_dh512_param_file = /etc/postfix/dh_4096.pem
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_eecdh_grade = ultra
 
tls_eecdh_strong_curve = prime256v1
tls_eecdh_ultra_curve = secp384r1
tls_high_cipherlist=EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!MEDIUM:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA
tls_ssl_options = no_ticket, no_compression, no_renegotiation
tls_preempt_cipherlist = yes
tls_random_source = dev:/dev/urandom
 
smtpd_data_restrictions = reject_unauth_pipelining, permit
smtpd_helo_required = yes
 
smtp_use_tls = yes
smtp_tls_cert_file=$smtpd_tls_cert_file
smtp_tls_key_file=$smtpd_tls_key_file
smtp_tls_CAfile=$smtpd_tls_CAfile
smtp_tls_CApath=/etc/ssl/certs
smtp_tls_mandatory_protocols=!SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_mandatory_exclude_ciphers = MD5, SRP, PSK, aDSS, kECDH, kDH, SEED, IDEA, RC2, RC5, RC4
smtp_tls_mandatory_ciphers = high
smtp_tls_protocols=!SSLv2,!SSLv3, !TLSv1, !TLSv1.1
smtp_tls_exclude_ciphers = MD5, SRP, PSK, aDSS, kECDH, kDH, SEED, IDEA, RC2, RC5, RC4
smtp_tls_ciphers = high
smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtp_tls_note_starttls_offer = yes
smtp_tls_session_cache_timeout = 3600s
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
 
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
 
smtpd_milters =
non_smtpd_milters = $smtpd_milters
milter_protocol = 6
milter_default_action = accept
 
smtpd_recipient_restrictions =
	reject_rbl_client xbl.spamhaus.org,
	reject_rbl_client pbl.spamhaus.org,
	reject_rbl_client sbl.spamhaus.org,
	reject_rbl_client multi.uribl.com,
	reject_rbl_client rbl-plus.mail-abuse.org,
	reject_rbl_client dialups.mail-abuse.org,
	reject_invalid_hostname,
	reject_non_fqdn_hostname,
	reject_non_fqdn_sender,
	reject_non_fqdn_recipient,
	reject_unknown_sender_domain,
	reject_unknown_recipient_domain,
	permit_mynetworks,
	permit_sasl_authenticated,
	permit_auth_destination,
	reject_unauth_destination,
	reject_unverified_recipient,
	permit
 
smtpd_relay_restrictions =
	permit_mynetworks,
	permit_sasl_authenticated,
	defer_unauth_destination
 
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $myhostname
smtpd_sasl_security_options = noanonymous
smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
 
broken_sasl_auth_clients = yes
 
#limit incoming or receiving email rate
smtpd_error_sleep_time = 1s
smtpd_soft_error_limit = 10
smtpd_hard_error_limit = 20
 
myhostname = host.domaine.eu
mydomain = domaine.eu
#myorigin = /etc/mailname
myorigin = $mydomain
mydestination = $myhostname, localhost.$mydomain, mail.$mydomain, lists.$mydomain, host, localhost
mynetworks = 127.0.0.0/8 [:: ffff:127.0.0.0]/104 [::1]/128
relayhost =
relay_domains = lists.domaine.eu
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mailbox_size_limit = 51200000
message_size_limit = 25600000
recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4
maximal_queue_lifetime = 3d
bounce_queue_lifetime = 3d
 
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_mailbox_domains = mysql:/etc/postfix/mysql/virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql/virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql/virtual-alias-maps.cf,mysql:/etc/postfix/mysql/email2email.cf
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1

La variable myhostname doit être définie avec un nom de domaine pleinement qualifié FQDN et le fichier /etc/mailname doit avoir cette même valeur.

Relancer Postfix

systemctl restart postfix

Tester la sécurité des échanges

Pour tester la sécurité de Postfix, il est possible de vérifier avec des outils comme starttls.info

Attention désactiver certains ciphers risquent de provoquer des fallbacks et le passage en clair des données : Disabling Anonymous Diffie Hellman

Configuration de Dovecot

Configuration principale

Depuis la mise à jour vers la version 2.3 plusieurs paramètres sont devenus obsolètes, voir Upgrading Dovecot v2.2 to v2.3

Par défaut sous Debian, Dovecot utilise plusieurs fichiers de configuration dans /etc/dovecot/conf.d. Sauvegardons les fichiers d’origine :

cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.original.bak
cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.original.bak
cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.original.bak
cp /etc/dovecot/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext.original.bak
cp /etc/dovecot/conf.d/10-master.conf /etc/dovecot/conf.d/10-master.conf.original.bak
cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.original.bak
cp /etc/dovecot/conf.d/10-logging.conf /etc/dovecot/conf.d/10-logging.conf.original.bak
cp /etc/dovecot/conf.d/15-mailboxes.conf /etc/dovecot/conf.d/15-mailboxes.conf.original.bak
cp /etc/dovecot/conf.d/15-lda.conf /etc/dovecot/conf.d/15-lda.conf.original.bak
cp /etc/dovecot/conf.d/20-imap.conf /etc/dovecot/conf.d/20-imap.conf.original.bak
cp /etc/dovecot/conf.d/20-lmtp.conf /etc/dovecot/conf.d/20-lmtp.conf.original.bak
cp /etc/dovecot/conf.d/90-sieve.conf /etc/dovecot/conf.d/90-sieve.conf.original.bak
cp /etc/dovecot/conf.d/auth-static.conf.ext /etc/dovecot/conf.d/auth-static.conf.ext.original.bak
cp /etc/dovecot/conf.d/auth-sql.conf.ext /etc/dovecot/conf.d/auth-sql.conf.ext.original.bak

Éditons le fichier :

vi /etc/dovecot/dovecot.conf

et vérifions que cette ligne soit bien décommenter :

!include conf.d/*.conf

ainsi que pour cette ligne :

!include_try /usr/share/dovecot/protocols.d/*.protocol

puis nous paramétrons les fichiers suivant du répertoire /etc/dovecot/conf.d :

10-mail.conf
mail_home = /var/mail/%d/%n
mail_location = maildir:/var/mail/%d/%n
mail_privileged_group = vmail
mail_plugin_dir = /usr/lib/dovecot/modules
mail_plugins =
10-auth.conf
disable_plaintext_auth = yes
auth_mechanisms = plain login
 
#!include auth-deny.conf.ext
#!include auth-master.conf.ext
 
#!include auth-system.conf.ext
!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
#!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
#!include auth-vpopmail.conf.ext
!include auth-static.conf.ext
10-master.conf
service imap-login {
  inet_listener imap {
    port = 0
  }
  inet_listener imaps {
    #port = 993
    #ssl = yes
  }
}
service pop3-login {
  inet_listener pop3 {
    port = 0
  }
  inet_listener pop3s {
    port = 0
  }
}
service auth {
  unix_listener auth-userdb {
    mode = 0600
    user = vmail 
  }
  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
 
  # Auth process is run as this user.
  user = $default_internal_user
}
service imap {
}
service pop3 {
}

Dovecot utilisera les mêmes certificats que Postfix

10-ssl.conf
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.domaine.eu/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.domaine.eu/privkey.pem
ssl_ca = </etc/letsencrypt/live/mail.doamin.eu/chain.pem
ssl_dh=</etc/dovecot/private/dh.pem
ssl_min_protocol = TLSv1.2
ssl_cipher_list = EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!aNULL;
ssl_prefer_server_ciphers = yes

Pour générer le fichier du paramètre Diffie-Hellman j'ai utilisé, sur un ordinateur avec une forte entropie, la commande suivante :

openssl dhparam -outform PEM -out dh4096.pem -rand /dev/urandom 4096
10-logging.conf
log_path = syslog
syslog_facility = mail
auth_verbose = yes
15-mailboxes.conf
namespace inbox {
  inbox = yes
  type = private
    mailbox Drafts {
      auto = subscribe
      special_use = \Drafts
    }
    mailbox Junk {
      auto = subscribe
      special_use = \Junk
    }
    mailbox Sent {
      auto = subscribe
      special_use = \Sent
    }
    mailbox Trash {
      auto = subscribe
      special_use = \Trash
    }
}
15-lda.conf
postmaster_address =postmaster@domaine.eu
20-lmtp.conf
protocol lmtp {
  postmaster_address = postmaster@domaine.eu
  mail_plugins = $mail_plugins sieve
  auth_socket_path = /var/run/dovecot/auth-master
}
90-sieve.conf
plugin {
  sieve = /var/mail/sieve/users/%u.sieve
  sieve_after = /var/mail/sieve/after
  sieve_before = /var/mail/sieve/before
  # After Dovecot v2.3 these settings are deprecated in newer versions
  # https://wiki2.dovecot.org/Pigeonhole/Sieve/Configuration
  # sieve_global_dir = /var/lib/dovecot/sieve/
  # sieve_dir = ~/sieve
  # use sieve_global instead sieve_global_dir
  # sieve_global = /var/lib/dovecot/sieve/
}
auth-static.conf.ext
userdb {
   driver = static
   args = uid=5000 gid=5000 home=/home/vmail/%d/%n allow_all_users=yes
}

Avec cette configuration, les utilisateurs virtuels utiliseront le répertoire /var/mail/$domain/$user/ et l'utilisateur vmail sera le propriétaire. Pour que cela fonctionne, il faudra créer les dossiers des domaines hébergés, mais Dovecot créera ceux des utilisateurs virtuels.

mkdir -p /var/mail/domaine.eu
chown vmail:vmail /var/mail/domaine.eu && chmod 770 /var/mail/domaine.eu

Paramètre MySQL pour Dovecot

Les paramètres de connexion à la base de données se configure dans dovecot-sql.conf.ext :

dovecot-sql.conf.ext
driver = mysql
connect = host=127.0.0.1 dbname=db_mail user=postmaster password=xxxxxxxx
default_pass_scheme = SHA512-CRYPT
user_query = SELECT ('5000') as 'uid',('5000') as 'gid'
password_query = SELECT CONCAT(user.user, '@', domain.name) AS user,user.password FROM user,domain WHERE user.domain_id=domain.id AND CONCAT(user.user, '@', domain.name)='%u'

Pour protéger le fichier :

chown root:root /etc/dovecot/dovecot-sql.conf.ext && chmod 400 /etc/dovecot/dovecot-sql.conf.ext

Configuration de Sieve

Création des dossiers nécessaires au fonctionnement :

mkdir -p /var/mail/sieve/before
mkdir /var/mail/sieve/after
mkdir /var/mail/sieve/users
chown -R vmail:vmail /var/mail/sieve && chmod -R 770 /var/mail/sieve

Si vous voulez avoir des règles spécifiques pour un utilisateur, il faut créer un fichier $user@$domain.sieve dans le dossier de l'utilisateur (example@domaine.eu dans notre cas). Tous les fichiers .sieve dans le dossier before seront utilisés pour tous les utilisateurs virtuels et avant leur configuration individuelle, par contre les fichiers .sieve dans le dossier after seront utilisées après. Créons un fichier spam.sieve dans le répertoire /var/mail/sieve/before avec le contenu suivant qui déplacera tous les messages avec drapeau SPAM dans le dossier Junk :

vi /var/mail/sieve/before/spam.sieve
spam.sieve
require ["envelope", "fileinto", "imap4flags", "regex"];
 
if not header :regex "message-id" ".*@.*\." {
      fileinto "Junk";
}
 
if header :contains "X-Spam-Level" "*****" {
      fileinto "Junk";
}

puis changeons les permissions sur ce fichier :

chown vmail:vmail /var/mail/sieve/before/spam.sieve && chmod 660 /var/mail/sieve/before/spam.sieve
==== Lancement du service ====
Nous pouvons maintenant lancer ce service avec la commande
<code>
systemctl restart dovecot

mais avant il est préférable de lancer dans un autre terminal l'affichage des logs pour voir les éventuelles erreurs de configuration.

tail -f /var/log/syslog

Tester la configuration

En gardant un œil ouvert sur syslog nous effectuons quelques tests

echo "test" | mail -s "Test" root@domaine.eu

Si tout est bien configuré, un email arrive dans la boite et aucune apparaît dans les logs.

Maintenant ouvrons avec Telnet une connexion sur notre serveur SMTP et essayons d'envoyer un courrier sur une adresse qui n'est pas de notre réseau et donc le domaine n'est pas indiqué en paramètre de la variable mydestination du fichier de configuration de Postfix /etc/postfix/main.cf afin de voir si le serveur refuse bien de relayer le courrier comme il doit le faire (rien de pire qu'un SMTP ouvert) pour les domaines non autorisés.

telnet host.domaine.eu 25
Trying xxx.xxx.xxx.xxx...
Connected to host.domaine.eu.
Escape character is '^]'.
220 domaine.eu ESMTP Postfix (Debian/GNU)
EHLO gmail.com
250-domaine.eu
250-PIPELINING
250-SIZE 20480000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
MAIL FROM: <user@gmail.com>
250 2.1.0 Ok
RCPT TO: <mail@yahoo.com>
554 5.7.1 <mail@yahoo.com>: Relay access denied

Essayons maintenant d'envoyer un courrier depuis une de nos adresses configurées sur le serveur vers un domaine non configuré dans Postfix. Nous devons obtenir un refus puisque la configuration autorise l'envoi de courrier que depuis des utilisateurs authentifiés.

telnet host.domaine.eu 25
Trying xxx.xxx.xxx.xxx...
Connected to host.domaine.eu.
Escape character is '^]'.
220 domaine.eu ESMTP Postfix (Debian/GNU)
EHLO domaine.eu
250-domaine.eu
250-PIPELINING
250-SIZE 20480000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
MAIL FROM: <postmaster@domaine.eu>
250 2.1.0 Ok
RCPT TO: <mail@yahoo.com>
554 5.7.1 <mail@yahoo.com>: Relay access denied

Et pour les couches sécurisées, elles peuvent être testées avec ces commandes :

openssl s_client -servername mail.domaine.eu -connect mail.domaine.eu:smtps
openssl s_client -servername mail.domaine.eu -connect mail.domaine.eu:imaps

Configuration de Postgrey

Après l’installation du paquet, nous devons éditer le fichier de configuration /etc/postfix/main.cf afin de modifier la variable smtpd_recipient_restrictions.

main.cf
smtpd_recipient_restrictions =
	reject_rbl_client xbl.spamhaus.org,
	reject_rbl_client pbl.spamhaus.org,
	reject_rbl_client sbl.spamhaus.org,
	reject_rbl_client multi.uribl.com,
	reject_rbl_client rbl-plus.mail-abuse.org,
	reject_rbl_client dialups.mail-abuse.org,
	reject_invalid_hostname,
	reject_non_fqdn_hostname,
	reject_non_fqdn_sender,
	reject_non_fqdn_recipient,
	reject_unknown_sender_domain,
	reject_unknown_recipient_domain,
	permit_mynetworks,
	permit_sasl_authenticated,
	permit_auth_destination,
	reject_unauth_destination,
	reject_unverified_recipient,
	check_policy_service inet:127.0.0.1:10023,
	permit

Puis il faut relancer Postfix en surveillant les logs :

systemctl restart postfix

Configuration de Clamav

Ce sera Amavis-new qui fera le pont entre Postfix et Clamav. Le fichier de configuration /etc/amavis/conf.d/15-av_scanners d’Amavis permet d’utiliser d'autres programmes anti-virus.

La configuration par défaut de ClamAV nous conviendra ; son fichier est /etc/clamav, vous y trouverez plus d’options.

Il faut ajouter l’utilisateur clamav au groupe amavis afin qu’Amavisd-new ait des droits sur les fichiers de ClamAV et inversement :

adduser clamav amavis
adduser amavis clamav

Configuration d’Amavis-new

Amavis servira pour le passage des messages entrants à des filtres comme Clamav et Spamassassin. Il faut ajouter les sections suivantes dans le fichier de configuration /etc/postfix/master.cf :

master.cf
amavis    unix  -       -       -       -       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       -       -       -       -       smtpd
  -o content_filter=
  -o local_recipient_maps=
  -o relay_recipient_maps=
  -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

Ces deux paragraphes permettront la création des points d’accrochage entre le module smtpd de Postfix et le daemon amavisd.

Les options -o indiquées surchargeront éventuellement celles qui seraient données dans main.cf pour les services en question, c'est à dire d'une part smtp-amavis et d'autre part le service smtpd attaché à amavis sur le port 10025.

Ajoutez aussi les deux lignes suivantes immédiatement en dessous du service de transport “pickup” :

master.cf
pickup    unix  n       -       y       60      1       pickup
  -o content_filter=
  -o receive_override_options=no_header_body_checks

Ceci empêchera la classification en tant que pourriel des messages de rapport de pourriels.

De plus, il faut modifier le fichier main.cf pour indiquer à Postfix que smtpd doit se connecter à Amavis, mais il y a juste une ligne à ajouter :

master.cf
content_filter=smtp-amavis:[127.0.0.1]:10024

Les fichiers de configuration d’Amavis sont dans le répertoire /etc/amavis/conf.d.

Pour activer la détection de spam et de virus; il faut ensuite décommenter les lignes utiles dans le fichier /etc/amavis/conf.d/15-content_filter_mode :

15-content_filter_mode
use strict;
 
# You can modify this file to re-enable SPAM checking through spamassassin
# and to re-enable antivirus checking.
 
#
# Default antivirus checking mode
# Please note, that anti-virus checking is DISABLED by 
# default.
# If You wish to enable it, please uncomment the following lines:
 
 
#@bypass_virus_checks_maps = (
#   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
 
 
#
# Default SPAM checking mode
# Please note, that anti-spam checking is DISABLED by 
# default.
# If You wish to enable it, please uncomment the following lines:
 
 
#@bypass_spam_checks_maps = (
#   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);
 
1;  # ensure a defined return

Cependant, il est préférable de copier ces lignes dans le fichier 50-user comme pour toutes modifications des variables de la configuration. Le fichier /etc/amavis/conf.d/20-debian_defaults a son importance, car il contient bon nombre de paramètres de configuration d' Amavis. Dans les grandes lignes, mieux vaut garder cette configuration, sauf que :

En effet, Amavisd-new ne retranscrit les tags de spamassassin que pour les messages à destination des domaines référencés dans la variable (liste) @local_domains_acl.

De plus, la variable $sa_kill_level_deflt définit le score à partir duquel nous sommes surs qu'un message est un spam, et la variable $final_spam_destiny indique quoi faire de ce message dans ce cas.

Dans la configuration par défaut, vous constaterez que si un message obtient un score >= 100, il est « D_BOUNCE » ce qui veut dire qu'il est mis en quarantaine locale et que le destinataire ne reçoit rien. Certes, un score de 100 est assez significatif, mais tout de même, peut-être souhaiterez-vous vous montrer plus libéral.

En cas de refus de tags de la part d'Amavis, de vérifier que le problème ne vient pas de la variable @local_domains_acl. Passer celle-ci avec la valeur @local_domains_acl = ( “.” ); permet d’effectuer le marquage des tags anti-spam quel que soit le domaine de destination.

Enfin, les variables $sa_tag_level_deflt et $sa_tag2_level_deflt influent sur le marquage du message, de même que la variable $sa_spam_subject_tag a un effet direct sur l’esthétique du message délivré.

Voilà à quoi pourrait ressembler le fichier /etc/amavis/conf.d/50-user :

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
#
@local_domains_acl = ( "." );
 
@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);
 
$sa_tag_level_deflt = -9999;     # note minimale pour ajouter les tags X-Spam... à l'en-tête des emails
                                 # ici, nous sommes à peu près surs que le tag sera toujours présent
$sa_tag2_level_deflt = 5.0;      # note minimale pour ajouter le tag X-Spam-Flag: YES
                                 # et modifier l'objet
$sa_kill_level_deflt = 100;      # note à partir de laquelle les mails sont traités comme définis
                                 # par la variable $final_spam_destiny (ici ils sont acceptés)
$sa_spam_subject_tag = '[SPAM]'; # chaine ajoutée à l'objet de l'email
$final_spam_destiny       = D_PASS;
 
# Pour ne pas en dire trop sur les armes employées
$X_HEADER_LINE = "spam & virus filtering at $mydomain";
 
#------------ Do not modify anything below this line -------------
1;  # ensure a defined return

Vérifier la configuration

Pour cela, il faut commencer par relancer les services en observant les logs afin de trouver les éventuelles erreurs :

systemctl restart postfix
systemctl restart amavis

Et de vérifier que les programmes Postfix et Amaivs soit bien à l'écoute :

netstat -tap | grep LISTEN
tcp        0      0 0.0.0.0:submissions     0.0.0.0:*               LISTEN      27299/master               
tcp        0      0 0.0.0.0:smtp            0.0.0.0:*               LISTEN      27299/master                 
tcp        0      0 0.0.0.0:imaps           0.0.0.0:*               LISTEN      597/dovecot         
tcp        0      0 localhost:10023         0.0.0.0:*               LISTEN      13838/postgrey --pi 
tcp        0      0 localhost:10024         0.0.0.0:*               LISTEN      28665/amavisd-new ( 
tcp        0      0 localhost:10025         0.0.0.0:*               LISTEN      27299/master                     

Installation des paquets suggérés

Afin de lire certains formats de fichiers, Amavis suggère l'installation de paquets supplémentaires.

apt install arj cabextract cpio lhasa lzop nomarch p7zip rpm unrar-free unzip zip

Configuration de Spamassasin

Les alternatives

Paquets facultatifs

Il existe des paquets facultatifs qui s’intègrent avec Spamassassin pour une meilleure détection des spams :

apt install pyzor razor

Puis :

user@host:~# su - amavis -s /bin/bash
$ razor-admin -create
$ razor-admin -register

Activation du service

Dans le fichier de configuration est /etc/default/spamassassin :

spamassassin
CRON=1

puis :

systemctl start spamassassin

Configuration

Sauvegardons le fichier original de la configuration local.cf avant de modifier les paramètres :

cp /etc/spamassassin/local.cf /etc/spamassassin/local.cf.original.bak
local.cf
rewrite_header Subject [SPAM]
report_safe 1
required_score 5.0
use_bayes 1
bayes_auto_learn 1

Nous pouvons redémarrer les services SpamAssassin et Postfix :

systemctl restart postfix
systemctl restart amavis
systemctl restart spamassassin

Vérifier le fonctionnement

Pour vérifier si cela fonctionne, envoyez-vous un e-mail d’un autre fournisseur et vous devriez voir des en-têtes plus ou moins semblables aux suivantes :

X-Virus-Scanned: Debian amavisd-new at host.domaine.eu
X-Spam-Flag: NO
X-Spam-Score: 0.001
X-Spam-Level:
X-Spam-Status: No, score=0.001 tagged_above=-9999 required=5
	tests=[HTML_MESSAGE=0.001] autolearn=ham autolearn_force=no

Configurer SPF

Permettre à votre serveur d’envoyer pour votre domaine

SPF (Sender Policy Framework) est un mécanisme qui confirme que l’IP de votre serveur est autorisé à envoyer des e-mails pour votre domaine. Techniquement, il est un enregistrement DNS TXT qui ressemble à ceci :

domaine.eu.     IN      TXT     "v=spf1 mx ip4:0.0.0.1 ~all"

Cet enregistrement DNS permet aux autres serveurs de messagerie de savoir que les serveurs qui possèdent un enregistrement MX pour mon domaine sont également autorisés à envoyer des e-mails. Pour plus d’informations sur la syntaxe SPF, vous pouvez consulter la documentation officielle. Sans un enregistrement SPF correctement configuré, les autres serveurs de messagerie pourraient considérer vos courriers comme un SPAM ou carrément les laisser tomber.

SPF Record pour les courriers entrants

Maintenant que nous avons mis en place notre propre enregistrement SPF, nous allons configurer Postfix pour vérifier que d’autres serveurs de messagerie puissent communiquer avec nous comme nous avons fait. Avant tout, nous allons ajouter les deux lignes suivantes à la fin de /etc/postfix-policyd-spf-python/policyd-spf.conf :

policyd-spf.conf
Header_Type = AR
Authserv_Id = hostname.domaine.eu

Pour connaître les différentes options, il existe la commande :

man policyd-spf.conf

Puis nous éditons le fichier master.cf :

master.cf
policy-spf  unix  -       n       n       -       -       spawn
     user=nobody argv=/usr/bin/policyd-spf

Ensuite nous modifions dans le fichier /etc/postfix/main.cf la section smtpd_recipient_restrictions pour ajouter la ligne de check_policy_service comme nous le voyons ci-dessous ainsi qu’un paramètre policy-spf_time_limit :

main.cf
smtpd_recipient_restrictions =
	reject_rbl_client xbl.spamhaus.org,
	reject_rbl_client pbl.spamhaus.org,
	reject_rbl_client sbl.spamhaus.org,
	reject_rbl_client multi.uribl.com,
	reject_rbl_client rbl-plus.mail-abuse.org,
	reject_rbl_client dialups.mail-abuse.org,
	reject_invalid_hostname,
	reject_non_fqdn_hostname,
	reject_non_fqdn_sender,
	reject_non_fqdn_recipient,
	reject_unknown_sender_domain,
	reject_unknown_recipient_domain,
	permit_mynetworks,
	permit_sasl_authenticated,
	permit_auth_destination,
	reject_unauth_destination,
	reject_unverified_recipient,
	check_policy_service unix:private/policy-spf,
	check_policy_service inet:127.0.0.1:10023,
	permit
 
policy-spf_time_limit = 3600s

Placez le service de politique après reject_unauth_destination afin d’éviter que des réponses inattendues du service de politique ne fassent de votre système un relais ouvert (ceci est recommandé pour tous les services de politique). En outre, placez le service de politique après avoir autorisé les expéditeurs locaux. Vous souhaitez que le SPF ne vérifie que le courrier entrant provenant d’Internet, et non le courrier sortant de vos utilisateurs.

Nous pouvons maintenant relancer le service :

systemctl restart postfix

Notre serveur peut maintenant vérifier les enregistrements SPF d’un autre serveur de messagerie. Pour vous assurer que cela fonctionne, envoyez-vous un e-mail depuis un autre fournisseur et vous devriez voir l’en-tête suivant :

Authentication-Results: myserver.domaine.eu; spf=pass (sender SPF authorized)
[...] receiver=example@domaine.eu)

OpenDKIM

DKIM (DomainKeys Identified Mail) est un mécanisme qui valide l'identité du nom de domaine d'un email par une authentification cryptographique. Bien que non obligatoire, la mise en place DKIM améliore les chances que les courriers envoyés à partir de votre serveur ne sont pas marqués comme SPAM par d'autres fournisseurs. Avec cette configuration, OpenDKIM vérifiera également la clé pour les e-mails entrants.

Configuration

Sauvegardons le fichier original de configuration :

cp /etc/opendkim.conf /etc/opendkim.conf.original.bak

Puis nous configurons /etc/opendkim.conf :

opendkim.conf'
AutoRestart             Yes
AutoRestartRate         10/1h
UMask                   0002
Syslog                  yes
SyslogSuccess           Yes
LogWhy                  Yes
 
OversignHeaders         From
AlwaysAddARHeader       yes
 
Canonicalization        relaxed/simple
 
ExternalIgnoreList      refile:/etc/postfix/dkim/TrustedHosts
InternalHosts           refile:/etc/postfix/dkim/TrustedHosts
KeyTable                refile:/etc/postfix/dkim/KeyTable
SigningTable            refile:/etc/postfix/dkim/SigningTable
 
Mode                    sv
PidFile                 /var/run/opendkim/opendkim.pid
SignatureAlgorithm      rsa-sha256
 
UserID                  opendkim:opendkim
 
Socket                  local:/var/spool/postfix/opendkim/opendkim.sock

Puis nous devons créer les dossiers nécessaires :

mkdir -p /etc/postfix/dkim/keys/domaine.eu/

Nous créons maintenant /etc/postfix/dkim/TrustedHosts, ce fichier contiendra les hôtes et les domaines pour lesquels OpenDKIM devra signer les emails :

TrustedHosts
localhost
127.0.0.1
::1
domaine.eu

Nous créons ensuite /etc/postfix/dkim/KeyTable, ce fichier indiquera à OpenDKIM la clé qu'il devra utiliser pour chaque sélecteur.

KeyTable
mail._domainkey.domaine.eu domaine.eu:mail:/etc/postfix/dkim/keys/domaine.eu/mail.private

Et enfin le fichier /etc/postfix/dkim/SigningTable, ce fichier indiquera à OpenDKIM quel sélecteur il devra utiliser pour chaque domaine.

SigningTable
*@domaine.eu mail._domainkey.domaine.eu

Nous générons ensuite une paire de clefs (publique/privé) pour notre domain :

cd /etc/postfix/dkim/keys/domaine.eu/
opendkim-genkey -s mail -d domaine.eu

Parmi les deux fichiers créés mail.private contient la clef privée et mail.txt contient la clef publique, changeons les permissions :

chown -R opendkim: /etc/postfix/dkim/keys
chmod -R 700 /etc/postfix/dkim/keys
chmod 400 /etc/postfix/dkim/keys/domaine.eu/*

Intégration Postfix

La dernière chose que nous avons à faire est de configurer Postfix pour qu'il puisse communiquer avec OpenDKIM. Nous créons ce dossier

mkdir /var/spool/postfix/opendkim
chown opendkim: /var/spool/postfix/opendkim
adduser postfix opendkim

Puis nous éditons le fichier /etc/postfix/main.cf pour ajouter :

main.cf
smtpd_milters = unix:/opendkim/opendkim.sock

Nous pouvons relancer ces services :

systemctl restart opendkim
systemctl restart postfix

Intégration DNS

Pour que DKIM fonctionne, nous devons configurer un enregistrement TXT DNS dans la zone du domaine. Ce record a été générée automatiquement par OpenDKIM dans le fichier mail.txt mentionné précédemment :

mail._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkJq0CW3tl2XHZ1CN5XdbqRDU7KfXOJ70nlwI09bHmDU63/Yz3J5rl863S0t2ncVHfIudZANj0OaiJe5HRR7WCsjuNIhQFfPFGIWLNClpxqdQVQURI38sAGeyn7Ed/Cor1AiWABzFWzel0kvXILw8K/NTzxaAPeSa9ttwQEgSmowIDAQAB" ; ----- DKIM key mail for domaine.eu

Tout ce que vous devons faire est de copier et de coller cet enregistrement dans notre fichier de zone DNS. Pour vous assurer que OpenDKIM fonctionne, vous pouvez envoyer un email vide à check-auth@verifier.port25.com et vous devriez recevoir une réponse avec le contenu suivant:

==========================================================
Summary of Results
==========================================================
SPF check:          pass
DomainKeys check:   neutral
DKIM check:         pass
Sender-ID check:    pass
SpamAssassin check: ham

L'utilisation de mail-tester.com vous aidera aussi à vérifier la configuration SPF et DKIM.

OpenDMARC

DMARC (Domain-based Message Authentication, Reporting & Conformance) standardisation des mécanismes d'authentification SPF et DKIM. Il permet au propriétaire d'un nom de domaine d'indiquer que son email est protégée par SPF et/ou DKIM et ce que les autres fournisseurs doivent faire avec les e-mails qui ne passent pas ces contrôles.

Configuration

Sauvegardons le fichier de la configuration d'origine :

cp /etc/opendmarc.conf /etc/opendmarc.conf.original.bak
rm /etc/opendmarc.conf
gunzip /usr/share/doc/opendmarc/opendmarc.conf.sample.gz
cp /usr/share/doc/opendmarc/opendmarc.conf.sample /etc/opendmarc.conf
opendmarc.conf
AutoRestart             true
AutoRestartRate         10/1h
UMask                   0002
Syslog                  true
 
AuthservID              hostname.domaine.eu
TrustedAuthservIDs      hostname.domaine.eu
IgnoreHosts             /etc/postfix/dkim/TrustedHosts
 
RejectFailures          false
 
UserID                  opendmarc:opendmarc
PidFile                 /var/run/opendmarc.pid
Socket                  local:/var/spool/postfix/opendmarc/opendmarc.sock

Intégration avec Postfix

Créons ce dossier :

mkdir /var/spool/postfix/opendmarc
chown opendmarc: /var/spool/postfix/opendmarc
adduser postfix opendmarc

Puis modifions le fichier de configuration /etc/postfix/main.cf de Postfix :

main.cf
smtpd_milters = unix:/opendkim/opendkim.sock, unix:/opendmarc/opendmarc.sock

Nous pouvons en relancer ces services (toujours en regardant les logs) :

systemctl restart opendmarc
systemctl restart postfix

Pour vérifier le fonctionnement, vous devriez voir dans les en têtes de vos messages entrants :

Authentication-Results: host.domaine.eu; dmarc=pass header.from=gmail.com

Intégration DNS

DMARC, comme SPF et DKIM, est basé sur les enregistrements DNS TXT.

_dmarc IN TXT "v=DMARC1; p=none; rua=mailto:postmaster@domanaine.eu; ruf=mailto:postmaster@domanaine.eu"

Cela indique à d'autres fournisseurs de ne pas rejeter ou mettre vos emails en quarantaine en cas d'échec de la vérification FPS ou DKIM échouer mais d'envoyer un rapport quotidien de ces vérifications au postmaster@domanaine.eu. Pour plus d'informations sur la syntaxe DMARC, voici un article de Google.

Monit

Monit est un daemon qui surveille d'autres daemons et vérifie qu'ils soient lancés, en cas de crash il les redémarre automatiquement. Il n'est pas lié à un serveur de messagerie et il est assez facile à mettre en place. Sauvegardons le fichier de la configuration d'origine :

cp /etc/monit/monitrc /etc/monit/monitrc.original.bak

Puis éditions la configuration pour adapter ces valeurs et décommenter ces paramètres, les autres valeurs par défauts et actives peuvent être laissées comme telles :

monitrc
set daemon 30
set logfile syslog facility log_daemon
 
set httpd port 2812 and
use address localhost
allow localhost
 
set mailserver localhost
with timeout 30 seconds
using hostname myserver.domaine.eu
 
set mail-format { from: monit@domaine.eu }
set alert root@domaine.eu
include /etc/monit/conf.d/*

Puis nous créons le fichier /etc/monit/conf.d/mail avec le contenu suivant :

mail
check process postfix
  with pidfile "/var/spool/postfix/pid/master.pid"
  start program = "/bin/systemctl start postfix"
  stop program = "/bin/systemctl stop postfix"
  alert monit@domaine.eu
  group mail
 
check process dovecot
  with pidfile "/run/dovecot/master.pid"
  start program = "/bin/systemctl start dovecot"
  stop program = "/bin/systemctl stop dovecot"
  alert monit@domaine.eu
  group mail
  depends on postfix
 
check process spamassassin
  with pidfile "/run/spamassassin.pid"
  start program = "/bin/systemctl start spamassassin"
  stop program = "/bin/systemctl stop spamassassin"
  alert monit@domaine.eu
  group mail
  depends on postfix, dovecot
 
check process opendkim
  with pidfile "/run/opendkim/opendkim.pid"
  start program = "/bin/systemctl start opendkim"
  stop program = "/bin/systemctl stop opendkim"
  alert monit@domaine.eu
  group mail
  depends on postfix, dovecot
 
check process opendmarc
  with pidfile "/run/opendmarc/opendmarc.pid"
  start program = "/bin/systemctl start opendmarc"
  stop program = "/bin/systemctl stop opendmarc"
  alert monit@domaine.eu
  group mail
  depends on postfix, dovecot

Donnons de bonne permissions à ce nouveau fichier :

chown root: /etc/monit/conf.d/mail && chmod 600 /etc/monit/conf.d/mail 

Nous pouvons maintenant relancer ce service :

monit reload

Avec la commande monit summary nous vérifions le fonctionnement et obtenons un rapport semblable

The Monit daemon 5.9 uptime: 0m 

Process 'postfix'                   Running
Process 'dovecot'                   Running
Process 'spamassassin'              Running
Process 'opendkim'                  Running
Process 'opendmarc'                 Running

Mailman

Pour gérer des listes de diffusion avec cette configuration, vous pouvez installer Mailman.

Conclusion

Nous avons maintenant un serveur de messagerie correctement configuré. Il pourrait être encore amélioré par la mise en place de détection de greylisting et de virus.

Réferences

Les tutoriaux et les pages d’aide qui furent utilisés pour construire cette page :