Artisan Numérique

/système/courrier/imap/ Stockage centralisé du courrier avec Cyrus-IMAP

Cyrus est un serveur IMAP à peu près aussi puissant que difficile à manipuler. Voici donc ma petit cuisine pour le mettre en oeuvre, le paramétrer, le sécuriser ainsi que quelques astuces pour sortir de quelques galères...

Pourquoi Cyrus ?

Alors donc, pourquoi utiliser Cyrus et pas le simplissime UW IMAP ? En fait les deux outils ne boxent simplement pas dans la même catégorie. UW-IMAP est petit démon d'une mise en œuvre ultra rapide (il suffit de l'installer pour que ça marche), utilisant la structure de stockage des mails natif d'UNIX. Le revers de cette simplicité est déjà son manque de fonctionnalité (gestion des ACL, langage Sieve, dossiers partagés ou multi-niveaux). Ensuite ce démon est très très lent lorsque le volume de courriels stocké devient trop important.

Cyrus quant à lui est un système complet disposant du langage Sieve (traitement automatique des courriels entrant au niveau serveur), l'utilisation d'une base de donnée pour le stockage (db4 en l'instance), le support des ACL, les dossiers multi-niveaux, les dossiers partagés entre utilisateur, etc.

Mais comme je le disais en introduction, Cyrus est aussi puissant que difficile à manipuler, voir même capricieux. Sa base de donnée n'est pas d'une fiabilité inattaquable, loin de là...

Installation du serveur

Tout d'abord il faut installer les paquets suivants :

apt-get install cyrus-common-2.2 cyrus-imapd-2.2 cyrus-admin-2.2 mailutils libsasl2-2 sasl2-bin libsasl2-modules postfix

L'installation du paquet sasl est une des joyeusetés de Cyrus. Ce démon qu'il faut obligatoirement prend en effet en charge tous les aspects authentification.

Vérification des services

Le serveur cyrus, comme son nom ne l'indique pas, permet de fonctionner selon les protocoles IMAP et IMAPS, mais aussi POP3 et POP3S. Un petite vérification d'usage pour vérifier que les ports associés à ces protocoles existent dans le fichier /etc/services qui doit contenir :

pop3            110/tcp
imap            143/tcp
imaps           993/tcp
pop3s           995/tcp
sieve           2000/tcp

Paramétrage

Deux fichiers sont responsables du paramétrage de cyrus : /etc/imapd.conf et /etc/cyrus.conf. Le premier regroupe les paramètres de fonctionnement :

# L'endroit où sont stockés les indexes (entre autre). A backuper !!!
configdirectory: /var/lib/imap

# L'endroit où sont stockés les courriels. A backuper !!!
partition-default: /var/spool/imap

# login de l'utilisateur administrateur
admins: cyrus

# interdit l'accès anonyme
allowanonymouslogin: no

# nous ne voulons pas de script sieve dans les homes utilisateur
sieveusehomedir: no

# dossier de stockage des scripts sieve
sievedir: /var/lib/imap/sieve

# méthode d'autentification : SASL2
sasl_pwcheck_method: saslauthd

# mécanisme d'autentification : PLAIN
sasl_mech_list: PLAIN

Le second fichier de configuration, /etc/cyrus.conf définit les services qui doivent être montés au démarrage (IMAP, POP3, etc...) ainsi que le nombre d'instances à exécuter en parallèle. Vous pouvez ainsi mettre en commentaire les services que vous ne comptez pas utiliser :

    SERVICES {
      imap          cmd="imapd"     listen="imap"   prefork=1
#      imaps         cmd="imapd -s"  listen="imaps"  prefork=2
      pop3          cmd="pop3d"     listen="pop3"   prefork=1
      pop3s         cmd="pop3d -s"  listen="pop3s"  prefork=1
      sieve         cmd="timsieved" listen="sieve"  prefork=1

      lmtp          cmd="lmtpd -a" listen="lmtp" prefork=0
    }

Si vous désirez n'écouter que l'adresse local pour un service, il suffit de remplacer, par exemple pour le service IMAP, le listen="imap" par listen="127.0.0.1:imap". Cette astuce est valable pour n'importe quelle adresse disponible. L'omission de l'adresse implique l'écoute de toutes les adresses. Attention à la sécurité !!

Paramétrage de SASL2

On peut maintenant lancer la gestion des mots de passes sasl par

$sudo /etc/init.d/saslauthd start

Il faut maintenant donner un mot de passe à cyrus :

passwd cyrus
#  rentrer un mot de passe

Et comme nous avons la joie de devoir utiliser sasl, il faut aussi changer le mot de passe qui lui est spécifique

Saslpasswd2 cyrus
#  rentrer un mot de passe

Création des boîtes aux lettres

Pour créer nos premières boites il faut déjà que le serveur soit lancé :

sudo /etc/init.d/cyrus-imapd start

Il faut maintenant créer les boites aux lettres. Pour cela, nous allons nous connecter à Cyrus en tant qu'utilisateur Cyrus, créer la boite et changer son mot de passe, l'utilisateur de test sera bien évidement gaston :

rootcyradm -u cyrus localhost
Mot de passe : ****

A rentrer dans l'interface de cyradmin
Cyrus> cm user.gaston
sortie de l'interface cyradmin
Cyrus> quit

rootuseradd gaston
rootpasswd gaston
rentrer ici le mot de passe de gaston
rootSaslpasswd2 gaston
et on recommence, cette fois pour sasl

Voilà c'est fait, gaston a maintenant un compte.

Création d'un dossier partagé

Pour illustrer la gestion des droits par cyrus, nous allons créer un dossier accessible à deux utilisateurs. Le client IMAP affichera alors ce dossier en dessous du dossier propre à l'utilisateur. Nous allons donner à un des deux utilisateurs (titi) un droit de lecture seule, et à l'autre (gaston) les droits complets.

Pour commencer, voici déjà, la liste des droits pour cyrus :

| flag | description | ------- | ----------------------------------------------------- | l | Les dossiers de la boîtes peuvent être vus. | r | Les messages de la boîtes peuvent être vus. | s | Les drapeaux Seen et Recent peuvent être modifiés. | w | Les autres drapeaux peuvent être modifiés. | pi | Des messages peuvent être ajoutés. | c | Des sous-dossiers peuvent être créés. | d | Les messages peuvent être supprimés. | a | L'utilisateur peut administrer cette boîte (droits).

D'après cette liste, gaston aura un masque de droit lrswpicda et titi aura quant à lui un simple lr

Voyons maintenant comment utiliser l'outil d'administration de cyrus pour créer notre boite partagée et assigner les droits :

rootcyradm -u cyrus localhost
Taper le mot de passe cyrus
Mot de passe : *****

Obtenir la liste des boites existantes
rootlm
Création d'une nouvelle boite
Cyrus>cm "notre partage"
liste les droits sur la boite créée
Cyrus>lam "notre partage"
cyrus lrswipcda
anyone lrs
Droits totaux à gaston
Cyrus>sam "notre partage" gaston lrswipcda
Droits restreints à tutu
Cyrus>sam "notre partage" titi lrs
On supprime les droits sur anyone
Cyrus>dam "notre partage" anyone
Vérification
lam "notre partage"
cyrus lrswipcda
gaston lrswipcda
titi lrs
Sortir maintenant...
Cyrus>quit

Maintenant imaginons que nous voulions renommer (ou déplacer) puis finalement détruire cette boite, il faut nous connecter en tant que gaston qui a seul les droits d'administration dessus :

rootcyradm -u gaston localhost
Mot de passe : ****

renommer la boite (il est aussi possible d'utiliser cette commande pour
Déplacer une boite avec toutes ses sous boites dans une autre boite, très pratique...)
Cyrus>renm "notre partage" "nos partages"
Obtenir la liste des boites existantes
Cyrus>dm "nos partages"
Sortir maintenant...
Cyrus>quit

Si vous voulez avoir des dossiers placés au même niveau qu'INBOX, vous devez rajouter la ligne suivante dans /etc/imapd.conf :

altnamespace:1

Activation de l'IMAP Sécurisé (IMAPS)

IMAP est un protocole « en clair », il est donc important lorsque l'on connecte un serveur Cyrus sur le monde extérieur de ne pas ouvrir le port IMAP mais plutôt sa version cryptée : IMAPS.

La première chose à faire est de générer ses certificats. Vous pouvez pour cela suivre ce tutorial. Ensuite il fait déplacer les 3 fichiers dans un dossier de votre choix, par exemple /var/lib/imapd/ssl.

Tout d'abord, placez le fichier ca.crt dans le dossier /etc/ssl/ca. Ensuite, il faut éditer le fichier /etc/imapd.conf pour modifier les 3 dernières lignes comme suit :

# les certificats à utiliser pour les accès SSL (voi plus loin)
tls_cert_file: /etc/ssl/cyrus-imapd/mamachine.mondomaine.com.crt
tls_key_file: /etc/ssl/cyrus-imapd/mamachine.mondomaine.com.key
tls_ca_cert: /etc/ssl/ca/ca.crt

Ensuite, il faut décommenter la ligne correspondant à imaps dans /etc/cyrus.conf, sauver, et redémarrer cyrus.

Connexion de Postfix à Cyrius

Il y a deux manière (à ma connaissance) de faire communiquer. Soit les deux démons sont sur la même machine (méthode simple), soit les deux machines sont distantes l'une de l'autre, postfix cloîtré dans la DMZ et Cyrus sur la LAN, et il faut alors utiliser le protocole lmtp (Local Mail Transfert Protocol).

Tout sur la même machine : Utilisation d'un socket UNIX

Il suffit de modifier le fichier /etc/postfix/main.conf pour avoir la ligne :

mailbox_transport=lmtp:unix:/var/lib/imap/socket/lmtp

Ensuite dans /etc/postfix/master.conf il faut retrouver la ligne suivante :

lmtp    unix    -       -       n       -       -       lmtp

Enfin dans /etc/cyrus.conf :

#  lmtp         cmd="lmtpd" listen="lmtp" prefork=0
  lmtpunix      cmd="lmtpd" listen="/var/lib/imap/socket/lmtp" prefork=1

Une fois ces petits travaux effectués, relancez postfix, puis cyrus. Les deux serveurs vont alors utiliser le protocole LMTP pour communiquer via un socket unix.

Entre deux machines : Utilisation d'un canal LMTP

Nous allons ici renseigner postfix pour envoyer son courrier sur le serveur imapd de cyrus. Pour cela, il faut éditer le fichier /etc/postfix/main.cf et chercher mailbox_transport pour renseigner comme suit :

mailbox_transport = lmtp:unix:/var/lib/imap/socket/lmtp

Puis dans le fichier /etc/postfix/master.cf changer la ligne :

lmtp    unix    -       -       y       -       -       lmtp

en

lmtp    unix    -       -       n       -       -       lmtp

Enfin il suffit de relancez postfix, puis cyrus.

Maintenant de faire un test d'envoi pour vérifier que tout se passe bien (le fichier /var/log/postfix.log indique les éventuelles erreurs.

Sauvetage d'une base de courriels corrompue

Il m'est arrivé d'obtenir une grosse corruption de la base des boîtes aux lettres. C'est l'horreur à plus d'un titre car la reconstruction /usr/lib/cyrus-imapd/reconstruct -m nous envoi joyeusement balader. Les logs quant à eux contiennent un erreur typique, en boucle du genre : DBERROR: skiplist recovery /var/lib/imap/mailboxes.db: 0090 should be ADD or DELETE

Bon, la solution car si quelqu'un me lit, il y a des chances qu'il soit sous une bonne dose de stress. Déjà, détente. Les données critiques ne sont pas dans /var/lib/imap mais dans /var/spool/imap. D'un côté les indexes de l'autre les messages. La première chose à faire, c'est d'arrêter tous les serveurs qui alimente cyrus (postfix/lmtp par exemple) pour ne pas perdre de mails entrant (vous avez tous des MX de secours configuré...).

Maintenant, si ce n'est déjà fait : backup !! Copier ces dossiers avec rsync quelque part en lieu sur.

Ensuite, vous vous connectez en tant que cyrus su - cyrus et vous créer quelque part (disons en /var/lib/imap/restore_mb.sh) le script suivant :

#!/bin/sh
# Script de reconstruction de mailboxes.db
#  Argument n°1 : dossier des mails (ex. /var/spool/imap)
#  Argument n°2 : l'utilisateur par défaut pour les dossiers partagés

# On se positionne sur les boites
cd $1

# intération sur les boîtes visible
for mb in * ; do
  cd $mb

  # si c'est un dossier utilisateur, on utilise cela pour l'associer (ACL) à sa boite
  if [ -d user ] ; then
    cd user

    # la magie de sed... transformation de la liste des
    # dossiers en déclaration de mailboxes compatible cyrus.
    # (nb. J'ai trouvé cela sur le net dans un bout de post qui
    # m'a permis d'écrire ce script...)
    find . -type d | grep ./ |
      sed -e "s/\.\///" |
      sed -e "s/\//\./g" |
      sed -e "s/\([a-z]*\)\(.*\)/user\.\1\2${TAB}default${TAB}\1${TAB}lrswipcda${TAB}cyrus${TAB}lrswipcda${TAB}/"
    cd ..
  fi

  # traitement des éventuels dossiers partagés
  find . -type d |
    grep -v "./user" |
    grep ./ |
    sed -e "s/\.\///" |
    sed -e "s/\//\./g" | sed -e "s/\([a-z]*\)\(.*\)/\1\2${TAB}default${TAB}$1${TAB}lrswipcda${TAB}cyrus${TAB}lrswipcda${TAB}/"
  cd ..
done | sort -u

Ce script se lance comme suit :

/var/lib/imap/restore_mb.sh /val/lib/spool utilisateur_partage > /var/lib/imap/mailboxes.txt

Le premier argument est la base de stockage des mails, le second un utilisateur qui deviendra propriétaire des boites partagées (si vous en avez). Le scripte basiquement fabrique un fichier texte de dump de type mailboxes.db équivalent à ce que la commande ctl_mboxlist -d aurait créé... Nous allons d'ailleurs utiliser cette même commande, avec -u en paramétrer pour reconstruire la base :

service cyrus-imapd stop # si ce n'est déjà fait..
cd /var/lib/imap
mv mailboxes.mb mailboxes.mb.corrupted
/usr/lib/cyrus-imapd/ctl_mboxlist -u -f /var/lib/imap/mailboxes.db <  /var/lib/imap/mailboxes.txt
sudo /etc/init.d/cyrus-imapd start

Voilà, il ne reste plus qu'à relancer cyrus et redonner les bons droits aux boites partagés.. ouf :)))