Setup un serveur Mail avec OpenSMTPD, Dovecot, Amavis et Mysql sur Debian 9

Tuto complet d'installation d'un serveur mail basé sur OpenSMTPD & cie sur Debian 9.

Setup un serveur Mail avec OpenSMTPD, Dovecot, Amavis et Mysql sur Debian 9

Cet article n'est plus trop d'actualité, les configs de opensmtpd ont changées et Debian n'est plus trop une recommandation pour le faire tourner.
Ainsi je vous recommande de vous tourner vers OpenBSD pour une meilleure experience :)


Le mail, c'est un enfer sur plein de points et beaucoup préfèrent en laisser la gestion à de gros organismes afin de ne pas s’embêter avec...

Problème, ces grands organismes, vous saurez jamais vraiment ce qu'ils font avec vos mails... Suffit qu'il y'ait du contenu sensible ou encore plus drôle, du contenu mal interprété et on voit vite le bordel (coucou GMail...).

Du coup quelles solutions pour éviter de confier ses mails à un tiers de confiance ?
Les héberger soit même sur son propre serveur !

Mais bon comme dit c'est un sacré bazar, mais c'est aussi pour ça que je rédige ce post.

Pourquoi OpenSMTPD au lieu de PostFix ?

Je sais pas vous, mais vous avez essayé de regarder la documentation de PostFix ?
Elle est juste immonde et désolé mais bosser avec des outils avec une doc en carton, sans façon.

OpenSMTPD est serveur SMTP conçu pour être fiable, simple, rapide, et surtout sécurisé (les grands commandements des projets OpenBSD entre autres).

Pour l'instant la team OpenBSD stipule que ce n'est pas encore vraiment prêt à tenir la charge d'énorme domaines niveau trafic, cependant pour des domaines de petites et de moyennes taille, c'est juste parfait !

Ok mais c'est quoi tout le reste ?

Un serveur SMTP suffit pour envoyer et recevoir des mails, cependant il y a pleins d'autres aspects qu'il faut prendre en compte.

Amavis : Servira à signer avec DKIM vos mails et aussi filtrer ce qui rentre.
Dovecot : Pouvoir lire ses mails c'est pratique et il propose IMAP comme protocole.
Mysql : C'est bien beau, mais faut bien stocker les données quelque part, pam étant un peu crade comme solution, mysql est ce qui semble le plus logique.

Pré-requis

Pour commencer, ça paraît évident, mais il vous faut un domaine, prenez ce qui vous conviens chez Gandi ou OVH (ou n'importe quel autre registar).
Verifiez que votre registar / l'organisme qui héberge votre zone dns supporte DNSSEC, c'est très important pour éviter le dns-hijack.

Ensuite le mail étant un sacré bordel, je vous recommande très fortement de dédier une machine virtuelle ou alors une machine complète pour votre serveur mail.
Il est important que celle-ci puisse avoir sa propre IPv4/v6 publique et que vous puissiez changer les reverses dns.

Vous pouvez le faire de manière sûre et certaine chez :

  • OVH / OVH Télécom
  • Online (dédiés)
  • Scaleway (seulement en v4... beurk)
  • Digital Ocean (Blocage du port 25)
  • Vultr
  • Hetzner

Installation de Debian

Si vous le voulez, chiffrer les disques de votre serveur, vous pouvez essayer de suivre le post de Aeris, il le fait sur un dédié Online, mais y a surement moyen de le reproduire chez d'autres hébergeurs.

Sinon, dans le cas contraire, si votre hébergeur propose une installation rapide et que c'est fiable, go.
Autrement, cherchez une iso de Debian (une netinstall ou un dvd, comme vous voulez), montez la, bootez dessus et c'est partit.

Pendant la configuration du réseau, l'installateur demandera le nom d'hôte de la machine et le domaine, une fois murement choisis, notez les de coté, vous en aurez besoin plus tard.

Configurez le layout du clavier, la configuration réseau (si possible faîtes en sorte qu'elle soit statique par sécurité).
Définissez la passphrase pour le compte root, votre nouvel user et sa passphrase.
Pour le partitionnement, faîtes comme vous le sentez, cependant si vous êtes pas certain, choisissez l'option pour débutant et confirmez.

Il vous sera demandé si vous voulez configurer les miroirs réseaux, faîtes oui et choisissez un miroir le plus proche de la localisation de votre serveur.
Ensuite, l’installateur vous proposera une liste de logiciels que vous pouvez installer par défaut, décochez tout sauf "Serveur SSH" et validez.

Validez l’installation de GRUB sur le disque et c'est fini, vous pouvez redémarrer votre serveur.

Configuration de Debian

Parce que la sécurité c'est notre priorité, il est important de bien configurer son serveur avant de déployer quoi que ce soit.

Connectez vous en ssh sur votre machine via l'user que vous avez créé pendant l'installation.
Passez en root avec su -.

Si vous disposez d'une clé SSH, mettez sa clé publique dans ~/.ssh/authorized_keys et désactivez la connexion par mot de passe dans /etc/ssh/sshd_config.

PasswordAuthentication no

Une fois cela fait, on met à jour son système apt update ; apt full-upgrade et une fois fini on redémarre.
(si apt gueule car il a besoin d'un cd/dvd, enlevez la ligne correspondante dans le fichier /etc/apt/sources.list et relancez la commande)

On se reconnecte en ssh, on repasse en root et on installe curl, openssl et ca-certificates :

apt install curl ca-certificates openssl

Ensuite pour sécuriser un peu, vous pouvez utiliser mon script maison.

Pour l'utiliser, voici un petit oneliner des familles :

curl -O https://gist.githubusercontent.com/skid9000/722620878e43ce73fd4e40ba19f300e7/raw/48fe89ea2134d5ae31440526809682055211ed0d/server_install.sh;chmod +x server_install.sh; ./server_install.sh

Dans le script, validez la détection du système et choisissez l'option 1.
Il vous sera demandé de valider quelques actions.
Vous pouvez changer le port du ssh via ce script, il suffit de le préciser quand ce sera demandé.

Une fois fini vous pouvez redémarrer votre serveur.
Si vous avez changé le port du ssh, pensez à la préciser dans votre client quand vous vous connectez.

Reconnectez vous et repassez en root.

Mysql

Depuis Debian 9, le paquet mysql-server des dépots ressort MariaDB, un fork de Mysql Server Community de Oracle.
Bien que la rétro-compatibilité avec pas mal de fonctions de la version de oracle soit plus ou moins fonctionnelle, j'ai vu quelques problèmes de gens avec OpenSMTPD en particulier, donc on va installer la version de Oracle.

C'est pas spécialement compliqué, quand on se rend sur le site de Mysql, il suffit de chercher le lien du .deb qui installe le bon dépôt.

Pour les fainéants voici un joli oneliner que vous pouvez copier coller :

apt install lsb-release -y; wget https://dev.mysql.com/get/mysql-apt-config_0.8.12-1_all.deb ; dpkg -i mysql-apt-config_0.8.12-1_all.deb ; apt update ; apt install mysql-server

Il vous sera demandé quelle version de Mysql vous voulez utilisez, choisissez la version 5.7 et définissez une passphrase root.

Ensuite on met en place un schéma pour la suite.
Premièrement on se connecte au serveur et on tape sa passphrase :

mysql -u root -p

Ensuite on fait un nouveau schéma et on défini un utilisateur qui à les permissions dessus.

CREATE DATABASE smtpd; 
GRANT ALL ON smtpd.* to 'opensmtpd'@'localhost' IDENTIFIED BY 'MA-SUPER-PASSPHRASE';

Faites exit et ensuite on définit la structure :

cat <<EOF > smtpd.sql
DROP TABLE IF EXISTS valias;
DROP TABLE IF EXISTS vdomains;
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS userinfo;

CREATE TABLE IF NOT EXISTS valias (
alias_id INT(8) NOT NULL AUTO_INCREMENT,
addr varchar(42) NOT NULL,
alias varchar(42) NOT NULL,
PRIMARY KEY (alias_id)
) ENGINE=InnoDB ;

CREATE TABLE IF NOT EXISTS vdomains (
domain_id INT(11) NOT NULL AUTO_INCREMENT,
domain VARCHAR(42) NOT NULL,
PRIMARY KEY (domain_id)
) ENGINE=InnoDB ;

CREATE TABLE IF NOT EXISTS userinfo (
user_id INT(11) NOT NULL AUTO_INCREMENT,
user VARCHAR(42) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
uid INT(42) DEFAULT 106,
gid INT(42) DEFAULT 107,
maildir VARCHAR(255) DEFAULT '/var/empty',
PRIMARY KEY (user_id)
) ENGINE=InnoDB ;

CREATE TABLE IF NOT EXISTS users (
user_id INT(8) NOT NULL AUTO_INCREMENT,
username TEXT NOT NULL,
domain TEXT NOT NULL,
mailbox TEXT NOT NULL,
password TEXT NULL,
home TEXT NOT NULL,
uid INTEGER NOT NULL,
gid INTEGER NOT NULL,
PRIMARY KEY (user_id)
) ENGINE=InnoDB ;
EOF
mysql -uroot -p smtpd < smtpd.sql 

OpenSMTPD

Yes ! On commence enfin le sérieux !

OpenSMTPD est directement sur les dépôts de Debian et sa version est largement suffisante.
Du coup on installe les paquets opensmtpd et opensmtpd-extras.

apt install opensmtpd opensmtpd-extras

On vous demandera le FQDN du serveur, laissez la valeur par défaut.
Pour les destinataires de certaines adresses, mettez rien.

Maintenant on va toucher au fichier de configuration. /etc/smtpd.conf
Dégagez tout et mettez cette configuration :

# This is the smtpd server system-wide configuration file.
# See smtpd.conf(5) for more information.

pki server.domain.tld certificate "/root/.acme.sh/domain.tld/fullchain.cer"
pki server.domain.tld key "/root/.acme.sh/domain.tld/domain.tld.key"

table vdomains mysql:/etc/smtpd-mysql.conf
table vusers mysql:/etc/smtpd-mysql.conf
table userinfo mysql:/etc/smtpd-mysql.conf
table credentials mysql:/etc/smtpd-mysql.conf

listen on ens32 port 25 tls pki server.domain.tld
listen on ens32 port 465 smtps pki server.domain.tld auth <credentials>
listen on ens32 port submission tls-require pki server.domain.tld auth <credentials>

listen on lo port 10025 tag Filtered
listen on lo port 10027 tag Signed

accept tagged Filtered for any alias <vusers> deliver to lmtp "/var/run/dovecot/lmtp"
accept from any for domain <vdomains> relay via "smtp://127.0.0.1:10024"

accept tagged Signed for any relay
accept for any relay via "smtp://127.0.0.1:10026"

Remplacez server.domain.tld (ligne 4, 5 12, 13 et 14) par le FQDN de votre serveur et mettez votre certificat TLS public ligne 4 la clé privée sur la ligne 5.
Aussi, si votre interface réseau n'est pas ens32, pensez à la changer. (ligne 12, 13 et 14)

Bien sûr il faut dire à OpenSMTPD quelle base de données utiliser et aussi avec quels identifiants... Et bien ça se passe dans /etc/smtpd-mysql.conf !

host localhost
username opensmtpd
password MA-SUPER-PASSPHRASE
database smtpd

query_credentials SELECT user,password FROM userinfo WHERE user=?;

query_domain SELECT domain FROM vdomains WHERE domain=? LIMIT 1;

query_userinfo SELECT uid,gid,maildir FROM userinfo where user=?;

query_alias SELECT alias FROM valias WHERE addr=?;

Hop là, pour OpenSMTPD c'est bon !

Amavis

Maintenant on attaque Amavis, pareil la version sur les dépôts

apt install amavisd-new

Et on édite notre propre fichier de configuration ici : /etc/amavis/conf.d/99-local

use strict;

$enable_dkim_verification = 1;
$enable_dkim_signing = 1;
dkim_key("domain.tld", "main", "/etc/certs/dkim.key" );

@dkim_signature_options_bysender_maps = (
    { '.' =>
        { ttl => 21*24*3600, c => 'relaxed/simple' }
    }
);

$inet_socket_port = [10024, 10026];
$policy_bank{'MYNETS'} = {
        originating => 1,
        os_fingerprint_method => undef,
};

$interface_policy{'10026'} = 'ORIGINATING';

$policy_bank{'ORIGINATING'} = {
        originating => 1,
        allow_disclaimers => 1,
        virus_admin_maps => ["root\@$mydomain"],
        spam_admin_maps => ["root\@$mydomain"],
        warnbadhsender => 1,
        forward_method => 'smtp:127.0.0.1:10027',
        smtpd_discard_ehlo_keywords => ['8BITMIME'],
        bypass_banned_checks_maps => [1],
        terminate_dsn_on_notify_success => 0,
};

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

Editez domain.tld ligne 5 par votre domaine (et non FQDN).
Comme vous le remarquez, on spécifie une clé DKIM, sauf que faut bien la générer non ? Eh bien c'est ce qu'on va faire !

DKIM

La pour le coup c'est super simple :

mkdir /etc/certs
openssl genrsa -out /etc/certs/dkim.key 2048
openssl rsa -in /etc/certs/dkim.key -pubout -out /etc/certs/dkim-public.key

Et hop là toutes mes fécilitations vous êtes en possession d'une super clé DKIM !
La troisième commande génère la clé publique que vous pouvez utiliser pour faire votre record DKIM sur votre zone DNS.

Dovecot

Car lire ses mails c'est quand même pratique :')

Il y a un peu beaucoup plus de paquets à installer par contre...

apt install dovecot-core dovecot-imapd dovecot-lmtpd dovecot-managesieved dovecot-sieve dovecot-mysql

Et ensuite on édite la configuration ici : /etc/dovecot/dovecot.conf

## Dovecot configuration file

# basic config
info_log_path = /var/log/dovecot-info.log
log_path = /var/log/dovecot.log
log_timestamp = "%Y-%m-%d %H:%M:%S "

!include conf.d/auth-sql.conf.ext 

# authentication
passdb {
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb { 
    driver = static 
    args = uid=virtmail gid=virtmail home=/var/virtmail/%u 
}

mail_location = maildir:/var/virtmail/%u 
mail_uid = virtmail 
mail_gid = virtmail

# the protocols we use
protocols = imap lmtp sieve

# ssl config
ssl_cert = </etc/certs/exem.pl.cert
ssl_key = </etc/certs/exem.pl.key
ssl_cipher_list = HIGH+kEECDH:HIGH:!PSK:!SRP:!3DES:!aNULL
ssl = yes

## configuring services 
# disables imap login without SSL (yes dovecot is dumb that way)
service imap-login {
    inet_listener imap {
        port=0 
    }
}

service lmtp {
    unix_listener lmtp {
        mode = 0666
    }
}

## configuring protocols
# the dovecot lda, we set it to use sieve
protocol lda {
    mail_plugins = $mail_plugins sieve
}

protocol lmtp {
    postmaster_address =  root@localhost
    mail_plugins = $mail_plugins sieve
}

plugin {
    sieve = ~/.dovecot.sieve
    sieve_dir = ~/sieve
}

Pensez ligne 28 et 29 à mettre le chemin de vos certificats/clés et ligne 54 définir une adresse mail qui servira de postmaster.

Vous remarquerez un user virtmail dans la config... Il existe pas ? On va remédier à ça.

useradd -m -c "Virtual Mail" -d /var/virtmail -s /sbin/nologin virtmail

Fichier de configuration suivant : /etc/dovecot/conf.d/auth-sql.conf.ext

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

Et enfin le dernier : /etc/dovecot/dovecot-sql.conf.ext

driver = mysql 

connect = host=localhost dbname=smtpd user=opensmtpd password=MA-SUPER-PASSPHRASE

default_pass_scheme = SHA512-CRYPT 

password_query = \ 
  SELECT user, password \ 
  FROM userinfo WHERE user = '%u'

Presque fini !

Il faut mettre des données en base de données afin que les différents services puissent les exploiter.

Connectez vous à Mysql : mysql -u root -p
Et tapez ceci (remplacez domain.tld par votre domaine) :

INSERT INTO `smtpd`.`vdomains` (`domain`) VALUES ('domain.tld');

On fait exit et on se prépare un petit script pour pouvoir générer des utilisateurs.
Créez un fichier mail-add-user.sh, rendez le executable chmod +x mail-add-user.sh et éditez le.

echo -e "Domain ?";read -r domain
echo -e "User ?";read -r user
echo -e "Password ?";read -r userpass
blowedpass=$(smtpctl encrypt $userpass)

cat <<EOF > user.sql
INSERT INTO valias VALUES('','$user@$domain', '$user');
INSERT INTO userinfo VALUES('','$user','$blowedpass',default,default,default);
EOF

mysql -uroot -p smtpd < user.sql
rm user.sql
useradd $user
echo -e "Done."
(Pour une raison obscure, il faut un user unix en plus à chaque fois, j'investigue)

On l'enregistre et on l'execute ./mail-add-user.sh.
Votre domaine sera demandé, l'username que vous voulez utiliser, ainsi que le mot de passe pour l'utilisateur.

Hop là un utilisateur a été créé.

Maintenant on redémarre tous les services :

systemctl restart opensmtpd dovecot amavis

Hop là et en théorie votre serveur mail est normalement fonctionnel !

DNS

Quelques petits records DNS à ajouter sur la zone de votre domaine.

Premièrement un A et un AAAA pointant sur votre serveur, ça parrait con mais je préfère le mentionner.
Ensuite un MX pointant sur le FQDN de votre serveur.

Maintenant commence la partie fun, DKIM, SPF et DMARC

# DKIM
main._domainkey.domain.tld. TXT "v=DKIM1; k=rsa; t=s; s=email; h=sha256; p=<public-dkim-key>"

# SPF
domain.tld. TXT "v=spf1 mx -all"

# DMARC
_dmarc.domain.tld. TXT "v=DMARC1; p=none"

Hop là normalement ça devrait être bon.

Firewall

C'est bien beau de setup un serveur mail, si il est pas accessible de l'exterieur c'est un peu useless.

Voici les 8 commandes iptables pour ouvrir les ports 993, 25, 465 et 587.

iptables -A INPUT -p tcp -m tcp --dport 993 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 465 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 587 -j ACCEPT

ip6tables -A INPUT -p tcp -m tcp --dport 993 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --dport 465 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --dport 587 -j ACCEPT

Hop là, les ports sont ouverts !

Fini !

Voilà, vous voici avec votre propre serveur mail !

Vous pouvez tester son fonctionement via un service comme mail-tester et ensuite profiter :)