courier-mta : Installation

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 commande makehosteddomains)

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 et hosteddomains
  • 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 installer courier-maildrop et non pas maildrop 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 sous MAILUSER= et MAILGROUP=.
  • 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 activer
  • pythonfilter-modules.conf : pour configurer chaque module.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *