Un aide-mémoire que je veux complet pour installer sur Debian 8 (Jessie) une instance de courier-mta avec tout ce qu’il faut : accès TLS (SSL) en IMAP/POP et SMTP et python-filter.
Préparation / réflexion
Je ne choisis pas la solution la plus simpliste mais je ne veux pas avoir à y revenir trop souvent donc je prévois un dimensionnement correct.
- Je vais utiliser le domaine
gosane.fr
pour définir la config. Bien sûr, vous adaptez 😉 - L’authentification se fera sur une simple base de données PostgreSQL (une seule table, rien de méchant). Facile à déployer et à maintenir, facile à ajouter une couche web pour changer les mots de passe notamment.
- L’idée est de forcer les clients à se connecter exclusivement en mode TLS. J’aurai certainement à revenir sur cet idéal (qui est juste le strict minimum en ces temps de surveillance d’état) car certains clients risquent de ne pas être compatibles.
- Les boîtes aux lettres seront virtuelles et gérées par l’utilisateur vmail.
- Bien entendu, il faut un certificat X509, soit auto-généré (ce que fait
courier
par défaut) soit fourni par une autorité de certification (CA). Je vais utiliser un certificat Gandi.
Mises en garde
- Je passe
root
pour faire la config - Le nom officiel de la machine est sd12345.dedibox.fr (non ce n’est pas vraiment 12345).
courier
n’aime pas du tout les fichiers de backup (ceux qui finissent par un~
par exemple) dans les dossiers qui acceptent des fichiers ayant des noms quelconques (par exemple/etc/courier/aliases/
) car ils sont vus comme les autres (et soit ça crée des doublons, soit ça laisse des données dont vous ne voulez pas).- Sous Debian, le compte qui possède
courier
est daemon. Il faut donc que ce compte (voire qu’exclusivement ce compte) puisse lire les fichiers de configuration. - Je fais ce tutoriel POUR MOI donc mes choix sont arbitraires, certainement discutables pour certains et, bien entendu pas exhaustif. C’est exprès. Vos commentaires (constructifs) sont les bienvenus mais inutile de troller en me suggérant, j’en ris d’avance, MySQL au lieu de PostgreSQL par exemple.
Installation des packages
courier lui-même
apt-get install courier-mta courier-imap-ssl courier-mta-ssl courier-pop courier-pop-ssl courier-authlib-postgresql
Si vous comptez utiliser maildrop
(pour faire des répondeurs en cas de vacances par exemple), vous devez installer le paquet courier-maildrop
et non pas juste maildrop
car ce dernier ne gère pas les utilisateurs virtuels.
postgresql
Le package postgresql-contrib-9.4 contient l’extension pgcrypto qui permet de générer les hashs de mots de passe.
apt-get install postgresql postgresql-contrib-9.4
Configuration
Création de l’utilisateur vmail
adduser --disabled-login vmail
Le système répond :
Ajout de l'utilisateur « vmail » ...
Ajout du nouveau groupe « vmail » (1000) ...
Ajout du nouvel utilisateur « vmail » (1000) avec le groupe « vmail » ...
...
Notez bien l’uid (1000) et le gid (1000 aussi) de ce compte.
dhparams.pem
Sans entrer dans les détails, il est indispensable de générer des paramètres Diffie-Hellman d’une bonne taille pour s’assurer d’un bon niveau de sécurité. Sous Jessie la taille est de 768 bits alors que 2048 sont recommandés. J’efface le fichier car si celui-ci a moins de 25 jours, il n’est pas recréé. Ah, et contrairement à ce que dit la doc, la variable d’environnement n’est pas BITS
mais DH_BITS
.
rm -f /etc/courier/dhparams.pem
DH_BITS=2048 mkdhparams
Il est recommandé de re-générer ce fichier tous les mois donc on ajout à la cron de root :
# Regénérer les paramètres Diffie-Hellman de courier tous les mois
0 0 1 * * DH_BITS=2048 /usr/sbin/mkdhparams
Authentification
On va créer un utilisateur toto de test dont le mot de passe sera tata
. On va utiliser la commande authpasswd
pour générer le hash SHA-256 correspondant :
authpasswd sha256
Et entrer (les 2 fois) tata. Le système répond :
{SHA256}0cfJnG4uezEfUd2dGRYaWDJiX7IfNRMfum2mJRPwwJk=
J’écris ça juste pour la référence, j’ai trouvé une façon élégante de faire ça directement depuis PostgreSQL.
PostgreSQL
Il est temps de créer la base de données qui va stocker les données des comptes et tout ce qui va avec :
sudo -u postgres psql
La suite se passe dans l’interpréteur psql.
Création du compte PostgreSQL qui aura accès à la base de données :
CREATE USER mailuser WITH PASSWORD '1TrucTresDur!';
Création de la base elle-même :
CREATE DATABASE mail OWNER mailuser;
Connexion à la base :
\c mail
Installer l’extension pgcrypto
qui permet de générer les hashs des mots de passe.
CREATE EXTENSION pgcrypto;
Prendre l’identité mailuser
pour que la table qu’on va créer lui appartienne :
SET ROLE mailuser;
Créer la table. Attention, on va indiquer en valeurs par défaut l’uid (1000) et le gid (1000) de l’utilisateur vmail créé au début. Si vous les avez oubliés vous pouvez les retrouver avec id vmail
depuis le shell.
CREATE TABLE passwd (
id TEXT DEFAULT '' NOT NULL PRIMARY KEY
,crypt TEXT DEFAULT '' NOT NULL
,clear TEXT DEFAULT '' NOT NULL
,name TEXT NOT NULL
,uid int DEFAULT 1000 NOT NULL
,gid int DEFAULT 1000 NOT NULL
,home TEXT NOT NULL
,maildir TEXT NOT NULL
,defaultdelivery TEXT NOT NULL
,quota TEXT DEFAULT '' NOT NULL
);
Créer un compte de test :
INSERT INTO passwd (id,crypt,clear,name,home,maildir,defaultdelivery) VALUES ('toto','{SHA256}'||encode(digest('tata','sha256'),'base64'),'tata','Toto Laricot','/home/vmail/toto','Maildir','');
Ça m’a pris un bon moment de trouver comment générer le hash directement avec PostgreSQL. Enjoy !
Quitter l’interpréteur :
\q
On vient de créer l’utilisateur virtuel toto, il faut créer son répertoire :
sudo -u vmail mkdir /home/vmail/toto
Ainsi que le Maildir correspondant :
sudo -u vmail maildirmake /home/vmail/toto/Maildir
Choix du module
On va d’abord indiquer à courier quel module d’authentification utiliser. Dans notre cas, authpgsql
. Dans /etc/courier/authdaemonrc
changer :
authmodulelist="authpgsql"
Paramétrer authpgsql
Modifier /etc/courier/authpgsqlrc
ainsi :
PGSQL_HOST localhost
PGSQL_PORT 5432
PGSQL_USERNAME mailuser
PGSQL_PASSWORD 1TrucTresDur!
PGSQL_DATABASE mail
Pour que les authentifications CRAM-* marchent, authlib DOIT voir les mots de passe en clair
Il faut donc dé-commenter la ligne :
PGSQL_CLEAR_PWFIELD clear
Et on redémarre courier et son module d’authentification :
service courier-mta restart
service courier-authdaemon restart
Test
courier
fournit un outil de test :
authtest toto tata
Authentication succeeded.
Authenticated: toto (uid 65534, gid 65534)
Home Directory: /home/toto
Maildir: (none)
Quota: (none)
Encrypted Password: {SHA256}0cfJnG4uezEfUd2dGRYaWDJiX7IfNRMfum2mJRPwwJk=
Cleartext Password: tata
Options: (none)
courier
esmtpacceptmailfor
Pour que courier
accepte des mails pour un domaine local, il faut le lui dire. Pour ça, on liste, dans /etc/courier/esmtpacceptmailfor
, tous les domaines pour lesquels on accepte du courrier entrant. localhost
en fait partie. De plus, pour gérer tous les sous-domaines, il faut ajouter une ligne commençant par un point .
suivi du nom du domaine en question.
Le mien contient :
localhost
sd-12345.dedibox.fr
gosane.fr
.gosane.fr
Domaines locaux
Quand on envoie un mail à quelquun@domaine.com, courier
doit savoir s’il doit rechercher dans sa base le compte “quelquun” ou le compte “quelquun@domaine.com” car si votre serveur héberge à la fois domaine.com
et exemple.com
, les deux utilisateurs quelquun@domaine.com et quelquun@exemple.com ne sont pas forcément la même personne.
Donc vous devez, pour tous les domaines que vous hébergez, déterminer si courier
doit retirer le nom de domaine avant de rechercher l’utilisateur dans la base de données.
- Ceux pour lesquels vous autorisez
courier
à retirer le domaine doivent être placés dans/etc/courier/locals
- Les autres doivent être placés dans
/etc/courier/hosteddomains
(et il faudra lancer la commandemakehosteddomains
)
Il faut redémarrer courier-mta
pour que les changements soient pris en compte.
Configuration ESMTP
Modifier /etc/courier/esmtpd
ainsi :
ESMTPAUTH="LOGIN CRAM-MD5 CRAM-SHA1 CRAM-SHA256"
ESMTPAUTH_TLS="LOGIN CRAM-MD5 CRAM-SHA1 CRAM-SHA256"
Modifier /etc/courier/esmtpd-msa
:
ESMTPDSTART=YES
TLS (SSL)
Le plus compliqué est de fabriquer les fichiers .pem
pour courier. Il faut d’abord récupérer, la clé privée .key
(créée en même temps que le .csr
) le certificat .crt
chez Gandi ainsi que ce qu’ils nomment le certificat intermédiaire GandiStandardCA2SSL.pem
. On prend tous ces fichiers et on les concatène pour fabriquer les fichiers pour courier : d’abord la clé privée (le .key
) puis le certificat du domaine, puis le certificat intermédiaire :
cat gosane.key gosane.crt GandiStandardSSLCA2.pem >/etc/courier/imapd.pem
Donner les droits qui vont bien :
chown daemon:daemon imapd.pem
chmod 400 imapd.pem
Puis recopier ce fichier avec les droits pour esmtpd et pop (on pourrait préciser un seul fichier dans la configuration, ce serait sûrement plus propre :
cp -a imapd.pem esmtpd.pem
cp -a imapd.pem pop3d.pem
Enfin, vérifier dans /etc/courier/esmtpd
qu’il est bien indiqué (attention notamment au répertoire qui pointe par défaut vers /usr/lib/courier
) :
TLS_CERTFILE=/etc/courier/esmtpd.pem
Et dans /etc/courier/imapd-ssl
:
TLS_CERTFILE=/etc/courier/imapd.pem
Même chose dans /etc/courier/pop3d
pour ceux qui l’utilisent.
Redémarrer courier :
service courier-mta restart
service courier-mta-ssl restart
service courier-imap restart
service courier-imap-ssl restart
Apple c’est toujours simple
Apple Mail et l’application iOS/iPhone sont des applications simples. Donc elles n’acceptent (apparemment) qu’une seule méthode d’authentification : CRAM-MD5. Pourquoi pas. CRAM suppose que le module d’authentification dispose du mot de passe en clair (pour refabriquer le hash MD5/SHA1/SHA256 à la volée).
Dans ce cas, il faut :
-
dans
/etc/courier/authpgsqlrc
s’assurer que la ligne suivante est décommentée :PGSQL_CLEAR_PWFIELD clear
-
dans
/etc/courier/imapd
activer la ligne qui contient les authentifications CRAM-* :IMAP_CAPABILITY=”IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA AUTH=CRAM-MD5 AUTH=CRAM-SHA1 AUTH=CRAM-SHA256 IDLE”
Trucs à vérifier
Parce-que je me fais avoir à chaque fois :
- vérifier qu’authdaemon est bien démarré ! (ERR: authdaemon: s_connect() failed: No such file or directory)
- la cohérence entre l’uid et le gid stockés pour l’utilisateur dans la base de données et ceux de vmail
- le chemin (/home/vmail/nom_du_compte)
- les droits, notamment pour les fichiers
.pem
- la configuration de
locals
,esmtpacceptmailfor
ethosteddomains
- en cas de lenteur pour envoyer des messages, mettre
TCPDOPTS="-stderrlogger=/usr/sbin/courierlogger -nodnslookup -noidentlookup"
dans esmtpd - ce qu’il y a dans “Apple c’est toujours simple” (pour tout ce qui est lié aux authentifications CRAM)
- pour que les utilisateurs puissent se logger indifféremment avec “compte” ou “compte@domaine.com” il faut indiquer
domaine.com
dans/etc/courier/defaultdomain
. Bien sûr, il ne peut y en avoir qu’un. - pour Outlook, il faut installer
gamin
. Je ne sais pas pourquoi mais sans ça, il râle à propos de “filesystem notification error with FAM/Gamin”. A priori si ça lui sert à savoir s’il y a de nouveaux mails. - si vous comptez utiliser
maildrop
, vous devez absolument installercourier-maildrop
et non pasmaildrop
car ce dernier ne gère pas les utilisateurs virtuels - avec les version récentes (Debian/Stretch) vérifier que les uid/gid sont bien définis à
courier
dans/etc/courier/esmtpd
sousMAILUSER=
etMAILGROUP=
. -
il est important de bien définir le
hostname -f
(au risque de recevoir des “517 Syntax error”) : il faut définir le FQDN de la machine comme première entrée du fichier/etc/hosts
pour la ligne 127.0.0.1 (et rebooter pour que les changements soient enregistrés) :127.0.0.1 machine.domaine.com machine localhost
courier-pythonfilter
Comme déjà indiqué ici, on commence par récupérer la dernière version ici
cd
wget http://phantom.dragonsdawn.net/~gordon/courier-patches/courier-pythonfilter/courier-pythonfilter-1.10.tar.gz
tar xfz courier-pythonfilter-1.10.tar.gz
cd courier-pythonfilter-1.10
python setup.py install
mkdir /var/lib/pythonfilter
chown daemon:daemon /var/lib/pythonfilter
ln -sf /usr/local/bin/pythonfilter /usr/lib/courier/filters
filterctl stop pythonfilter
filterctl start pythonfilter
Puis installer spamassassin
et clamav
:
apt-get install spamc spamassassin clamav python-gdbm python-pyclamd python-pyclamav
Pour clamav, configurer le socket dans /etc/pythonfilter-modules.conf
:
localSocket = '/var/run/clamav/clamd.ctl'
(ici j’ai mis la valeur trouvée dans /etc/clamav/clamd.conf
)
Pour spamassassin, il faut l’activer dans /etc/default/spamassassin
:
ENABLED=1
Créer un utilisateur avec peu de droits :
adduser --disabled-password spamuser
Et configurer ainsi /etc/pythonfilter-modules.conf
(attention, par défaut, spamcPath
pointe sur /usr/local/bin/spamc
qui n’existe pas) :
[spamassassin.py]
spamcPath = '/usr/bin/spamc'
maxMsgSize = 512000
username = 'spamuser'
rejectScore = 10
Il faut ensuite configurer les fichiers suivants :
pythonfilter.conf
: pour indiquer quels modules activerpythonfilter-modules.conf
: pour configurer chaque module.