IMA4 2017/2018 P20

De Wiki de Projets IMA



Solution de messagerie à base de conteneurs

Présentation générale

Description

Un système de messagerie électronique se compose de quatre éléments fondamentaux :

  • le Mail Transfert Agent ou MTA : permet d’acheminer le courriel d’un serveur à un autre. Le protocole généralement utilisé est le SMTP.
  • le serveur du protocole entrant : permet la réception et la distribution du courriel. Les plus généralement utilisés sont POP3 et IMAP.
  • le Mail Delivery Agent ou MDA : agent en charge de la gestion des boîtes aux lettres. Il est chargé de livrer le courriel dans la boîte du destinataire.
  • le Mail User Agent ou MUA : logiciel client de messagerie qui fournit un environnement pour la gestion du courriel.


Architecture-systeme-messagerie-electronique.JPG


Le but de ce projet est d'utiliser la technologie des conteneurs pour le déploiement de la solution de messagerie.

Les conteneurs sont en train de révolutionner le marché et les pratiques de la virtualisation. A des VMs, certes efficaces, mais lourdes qui s’appuient sur des hyperviseurs et qui demandent des OS invités, ils opposent un mode de virtualisation « light », directement enraciné dans le kernel de l’OS hôte. La virtualisation à base de conteneurs est une méthode de virtualisation dans laquelle la couche de virtualisation s'exécute au sein même du système d’exploitation. Cette approche permet d'améliorer les performances, puisqu'un seul et unique système d'exploitation (l'hôte) se charge des appels matériels. Elle permet également d'héberger sur un serveur beaucoup plus d'instances virtualisées que la virtualisation traditionnelle.

Objectifs

Permettre de déployer facilement un système de messagerie pour quelques utilisateurs grâce à la technologie des conteneurs. A partir de scripts Shell, on devra être capables de créer, lister ou supprimer des comptes de messagerie sur le serveur de messagerie.

Analyse du projet

Positionnement par rapport à l'existant

L'architecture de notre système de messagerie serait la suivante :

Architecture de la messagerie envisagée


Ainsi, nous aurions :

  • Un conteneur avec le système principal contenant :
    • Un serveur SMTP pour la réception des différents courriels et la redistribution
    • Le Webmail
  • Un conteneur pour chaque compte de messagerie contenant :
    • Un serveur SMTP pour recevoir et envoyer les courriels
    • Un Mail Delivery Agent pour stocker les messages dans le système de fichiers du conteneur
    • Un serveur IMAP pour qu'un client de messagerie puisse récupérer les messages stockés


Il n'existe pas, à notre connaissance, de solution de messagerie à base de conteneur autre que sous forme de projet en cours de développement ou proposée par des particuliers.

Analyse du premier concurrent : PEPS

PEPS est une solution open source moderne de messagerie, partage de fichiers et serveur de collaboration encore en cours de développement qui tient à rivaliser à Gmail ou Dropbox en innovant. La particularité de cette solution est son chiffrement bout à bout qui permet d'éviter le stockage des clés de chiffrement sur le serveur. Il n'y a donc que l'expéditeur et les destinataires qui peuvent lire les messages échangés.

La partie serveur de cette solution se déploie sous forme de conteneur grâce à Docker.

Cette solution propose son propre Webmail et la gestion des comptes de messagerie est faite directement à partir de ce logiciel.

Nous n'avons pas trouvé d'informations concernant le déploiement de la partie utilisateur.

Analyse du second concurrent : docker-mailserver

docker-mailserver est un serveur mail fonctionnel à déployer sous forme de conteneur développé par un particulier. Le serveur est déployé en une ligne de commande et la création d'une adresse de messagerie se fait par l'utilisation d'un script Shell.

Cette solution ne propose que la partie serveur d'une solution de messagerie.

Scénario d'usage du produit ou du concept envisagé

Michel lance sa start-up avec son ami Robert. Il décide tout de suite de mettre en place un système de messagerie. Il déploie dans un premier temps le conteneur dans lequel se trouve le système principal de messagerie sur son serveur et effectue quelques réglages nécessaires. Ensuite, sa Start-up comptant 4 employés, il déploie 4 conteneurs utilisateurs, un pour chaque compte de messagerie. Le script add_user.sh fourni avec la solution lui permet d'attribuer très rapidement, pour chaque conteneur, une adresse de messagerie.

Les utilisateurs peuvent alors consulter et échanger des mails à partir du Webmail à l'adresse lastartupdemichel.org. Leurs adresses de messagerie ont été créé par le script sous la forme box@nom_utilisateur.lastartupdemichel.org. Ils peuvent aussi accéder au conteneur associé à leur compte de messagerie par SSH.

Michel peut vérifier que les comptes de messagerie ont bien été créé en utilisant le script list_user.sh qui liste tous les comptes de messagerie du système. Si un employé venait à quitter la Start-up, il pourrait supprimer le compte de messagerie associé à l'employé en utilisant le script delete_user.sh qui lui permet de supprimer un compte de messagerie, dont il précisera le nom d'utilisateur, en une ligne de commande.

Question difficile

Quel est l'interêt de l'utilisation des conteneurs par rapport aux solutions traditionnelles de messagerie ?

Réponse à la question difficile

L'utilisation de la technologie des conteneurs permettrait un déploiement rapide et facile du système de messagerie. Les utilisateurs pourraient se créer un compte de messagerie en deux ou trois lignes de code plutôt que de devoir entrer toutes leurs informations sur le web comme nous le faisons traditionnellement.

Préparation du projet

Cahier des charges

Structure :

  • Solution de messagerie fonctionnelle
  • Utilisation de la technologie des conteneurs pour le déploiement de la solution :
    • Un conteneur principal contenant un serveur SMTP pour la réception des différents courriels et la redistribution et une application Webmail
    • Un conteneur utilisateur par compte de messagerie contenant un serveur SMTP pour recevoir et envoyer les courriels, un facteur pour stocker les messages dans le système de fichiers du conteneur et un serveur IMAP pour qu'un client de messagerie puisse récupérer les messages stockés


Utilisation :

  • Scripts shell permettant la création, la suppression et le listing des comptes de messagerie sur le serveur de messagerie


Point de vue Réseau :

  • Tous les éléments disposent d'une adresse IPv6 routée
  • Le système principal dispose d'une adresse IPv4 routée
  • Les conteneurs disposent d'une adresse IPv4 privée
  • Un domaine Internet est dédié au système
  • Chaque conteneur reçoit les courriels pour un sous-domaine
  • Le MX des sous-domaines donne l'adresse IPv4 du système principal sur internet

Choix techniques : matériel et logiciel

  • Gestion des conteneurs : Docker CE
  • Mail Transfert Agent : Postfix
  • Serveur IMAP : Dovecot
  • Mail Delivery Agent : Dovecot
  • Mail User Agent : Rainloop
  • Serveur Web : NGINX

Liste des tâches à effectuer

  • Mettre en place l'environnement de travail
  • Réaliser le conteneur principal contenant le Webmail et le MTA de relai
  • Réaliser le conteneur client contenant un MTA, un MDA et un serveur IMAP
  • Tester la solution
  • Ecrire les scripts shell

Réalisation du Projet

Feuille d'heures

Tâche Prélude Heures S1 Heures S2 Heures S3 Heures S4 Heures S5 Heures S6 Heures S7 Heures S8 Heures S9 Heures S10 Heures S11 Heures S12/S13 Total
Analyse du projet 5h 5h
Documentation 2h 4h 5h 11h
Mise en place de l'environnement de travail 5h 8h 6h 30min 30min 20h
Prise en main des différents logiciels 5h 5h
Constitution du conteneur principal 6h 14h 3h 6h 29h
Constitution du conteneur utilisateur 5h 5h
Écriture des scripts 4h 4h
Test et débogage de la solution 30h 30h

Prologue

  • Analyse du projet :
    • Recherches sur les systèmes de messagerie
    • Recherches sur la technologie des conteneurs
    • Recherche de concurrents
    • Écriture d'un premier scénario d'utilisation
  • Wiki :
    • Remplissage de la partie Présentation générale et Analyse de projet
    • Réponse à la question difficile suite à la présentation orale

Semaine 1

Documentation sur :

  • Mise en place d'un système de messagerie en général
  • Postfix
  • Courier-imap
  • Procmail

Semaine 2

  • Documentation sur :
    • Docker CE et Docker Compose : Installation et guides d'utilisation
  • Wiki :
    • Modification du scénario d'utilisation
    • Remplissage de la partie Préparation du projet

Semaine 3

Prise en main des logiciels :

  • Docker CE
  • Docker Compose
  • Docker Machine

Semaine 4

Documentation : Mise en place d'un serveur DNS

Semaine 5

Mise en place de l'environnement de travail :

  • Activation de la communication série sur la Raspberry Pi :

La communication série n'étant pas activée par défaut sur la version installée de Raspbian, il faut monter la carte SD sur un ordinateur puis modifier les fichiers cmdline.txt et config.txt. On vérifie que l'option console=serial0,115200 est bien présente dans la ligne du fichier cmdline.txt et on ajoute enable_uart=1 à la fin du fichier config.txt. On peut maintenant accéder à la Raspberry Pi grâce à Minicom par la commande minicom -o -8 -b 115200 -D /dev/ttyUSB0

  • Connexion de la Raspberry Pi à internet par Wifi :

Pour connecter la Raspberry Pi en Wifi, on modifie le fichier /etc/wpa_supplicant/wpa_supplicant.conf en y ajoutant à la fin :

   network={
   ssid="nomDeLaBox"
   psk="cléDeSécurité"
   key_mgmt=WPA-PSK }

en remplaçant "nomDeLaBox" et "cléDeSécurité" par les informations de la box à laquelle on souhaite se connecter.

  • Activation du serveur SSH :

Maintenant que la Raspberry Pi est connectée à internet, on active le serveur SSH afin de pouvoir y accéder par ssh plutôt que de devoir utiliser minicom. Pour ce faire, on lance les commandes : update-rc.d ssh enable et invoke-rc.d ssh start. La Raspberry Pi est désormais accessible par ssh.

Semaine 6

Mise en place de l'environnement de travail :

  • Installation de machines virtuelles :

Installation de deux machines virtuelles sous Ubuntu grâce à Virtualbox qui serviront de clients pour la solution de messagerie. Ces machines virtuelles ont été installé sur un ordinateur personnel et sont accessibles à distance. Celles-ci ont leur interface réseau configurée en accès par pont de sorte à posséder une adresse IP privée. Installation d'openssh-server pour l'accès à distance.

  • Attribution d'adresses IP privées fixes aux différentes machines utilisées :

A travers l'interface graphique du routeur personnel, on réserve une adresse IPv4 privée fixe pour le système principal (Raspberry Pi) et pour les deux clients (machines virtuelles créées précédemment) . Il faut ensuite attribuer ces adresses aux machines utilisées. Sur la Raspberry, l’OS étant Raspbian Jessie, le fichier réseau à modifier n’est pas /etc/network/interfaces mais /etc/dhcpcd.conf. On ajoute dans ce dernier :

  interface wlan0
  static ip_address=192.168.0.11/24
  static routers=192.168.0.254
  static domain_name_servers=192.168.0.254

192,168,0,11 étant l’adresse réservée sur le routeur. Puis le fichier /etc/resolv.conf dans lequel on remplace l’adresse présente par celle du routeur.

  • Redirection d’un port du routeur pour le ssh :

A travers l’interface graphique du routeur, on redirige un port vers l’adresse privée fixe de la Raspberry pour pouvoir y accéder en ssh depuis l’extérieur. On précise ce port dans le fichier /etc/ssh/sshd_config sur la Raspberry. On peut désormais accéder à la Raspberry à partir n'importe quel endroit par ce port.

  • Réservation et configuration d'un nom de domaine :

Réservation du nom de domaine mcreteur.fr pour le système de messagerie. Ajout d'un enregistrement de type A faisant pointer le nom de domaine mcreteur.fr sur l'adresse IPv4 publique fixe du routeur personnel utilisé. Création du sous domaine smtp.mcreteur.fr qui sera dédié au serveur smtp installé sur la Rapsberry. Ajout d’un enregistrement de type A faisant pointer le sous domaine smtp.mcreteur.fr sur l’adresse IPv4 publique fixe du routeur personnel utilisé. Ajout d’un enregistrement de type MX pour le sous-domaine smtp.mcreteur.fr pour préciser que le serveur mail du domaine mcreteur.fr correspond au serveur smtp.mcreteur.fr

  • Changement du nom d’hôte de la Raspberry :

On attribue le sous domaine smtp.mcreteur.fr en modifiant le fichier /etc/hostname en remplaçant raspberrypi par smtp pour faire de smtp le nom de la machine. Puis le fichier /etc/hosts en remplaçant l’occurence raspberrypi par smtp.mcreteur.fr smtp pour préciser le FQDN et le hostname.

On peut vérifier que le serveur mail du domaine mcreteur.fr est bien géré par le sous domaine smtp.mcreteur.fr :

MX du domaine mcreteur.fr

Semaine 7

Mise en place de l'environnement de travail :

  • Installation de l’environnement Docker sur les différents machines utilisées :
    • Installation de Docker CE :

- Installation des packages nécessaires à l’utilitaire apt pour utiliser un dépôt à travers HTTPS :

    sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg2 \
    software-properties-common

- Ajout de la clé GPG officielle Docker : Pour la Raspberry :

    curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | sudo apt-key add - 

Pour les VM sous Ubuntu :

    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 


- Utilisation du dépôt stable : Pour la Raspberry :

    echo "deb [arch=armhf] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
    $(lsb_release -cs) stable" | \
    sudo tee /etc/apt/sources.list.d/docker.list

Pour les VM sous Ubuntu :

   sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

- Mise à jour des packets :

   sudo apt-get update

- Installation de la dernière version de Docker CE :

   sudo apt-get install docker-ce
  • Installation de Docker Compose :
   sudo apt-get install docker-compose


  • Mise en place d’un cluster Docker swarm :

Afin de pouvoir déployer les conteneurs sur toutes les machines utilisées d’un seul coup à partir du serveur, on met en place un cluster avec Docker Swarm. Sur le système principal, on lance la commande :

  docker swarm init --advertise-addr 192.168.0.11

qui permet de mettre en place le cluster à l’adresse IP 192.168.0.11 qui est celle du système principal. Le système principal est alors un manager du cluster. La commande entrée nous renvoi la commande à utiliser sur les autres machines pour rejoindre le cluster.

Sur les deux machines virtuelles, on entre alors la commande la commande indiquée pour rejoindre le cluster en tant que worker, les machines virtuelles étant les clients du système.

Une fois la commande entrée sur les deux clients, on peut vérifier que toutes les machines sont bien connectées au cluster :

Affichage du cluster

Semaine 8

  • Constitution du conteneur principal :

Maintenant que l'environnement de travail est en place, nous pouvons nous lancer dans le développement de la solution. Nous avons décidé de commencer par le serveur SMTP, donc par l'installation et la configuration de Postfix sur le système principal.

La configuration de Postfix se fait dans les fichiers main.cf qui contient la configuration de Postfix ainsi que master.cf qui contient les services Postfix à démarrer. Nous avons donc téléchargé ces deux fichiers sources pour les modifier nous mêmes et nous demanderons à Docker, grâce à un Dockerfile, de remplacer les fichiers main.cf et master.cf, qui seront présent dans le conteneur à l'installation de Postfix, par ceux que nous avons modifié pour que Postfix soit configuré.

Dans un premier temps, nous avons modifié le fichier master.cf : nous décommentons la ligne "submission inet n - n - - smtpd" afin de séparer le service de transfert de message entre serveurs de messagerie (port 25) du service de soumission de message par les clients de mesagerie (port 587) pour respecter les normes. Nous décommentons aussi certains paramètres de ce service de soumission pour restreindre son utilisation aux machines ou aux clients authentifiés par sasl par exemple pour plus de sécurité.

Dans un second temps, nous modifions le fichier main.cf : nous ajoutons le réseau privé 192.168.0.0 au paramètre mynetworks, on modifie le paramètre inet_protocols en all pour permettre l'utilisation de l'IPv6, on décommente les paramètres alias_database et alias_maps pour pouvoir par la suite, préciser les machines locales et faciliter la distribution du courier. On décommente aussi les paramètres mydestination et myorigin mais nous ne changeons pas les valeurs. Nous ferons en sorte de configurer ces paramètres par un script afin de ne pas perdre en portabilité.

Ensuite, on écrit le script permettant de mettre à jour les paramètres myorigin et mydestination en fonction de la machine sur laquelle est lancé le conteneur. Ce script se résume à postconf -e "myhostname = $HOSTNAME" pour mettre à jour le hostname et postconf -e "mydomain = $DOMAINNAME" pour mettre à jour le nom de domaine.

Enfin, on écrit le Dockerfile : On y précise que l'on veut installer Postfix, que l'on veut remplacer les fichiers main.cf et master.cf installés par défaut, par les notres. On copie le script de configuration de Postfix à l'intérieur du conteneur, on autorise son execution et on l'execute. Finalement, on expose les ports 25 et 587 du conteneur pour pouvoir utiliser les services.

Ces fichiers seront probablement amenés à subir des modifications par la suite.

Semaine 9

Pendant la configuration de Postfix, nous nous sommes posés la question de la sécurisation des échanges de données. Nous avons décidé de certifier notre serveur afin que les échanges soient chiffrés. Nous avons utilisé le Certbot de Let's Encrypt qui fournit des certificats SSL/TLS gratuitement. Avant de pouvoir utiliser ce dernier, il fallait mettre en place un serveur web. Nous avons choisi Nginx. Nous avons tenté d'installer Nginx via un simple Dockerfile sur la Raspberry mais nous avons rencontré un problème d'architecture. Il nous était impossible de lancer un conteneur avec le dockerfile sur la Raspberry bien que Docker y était installé. Après s'être documenté un peu, nous avons décider de changer de système principal et d'opter pour un Ubuntu Server.


  • Mise en place de l'environnement de travail : Nous avons refait tout ce que nous avions fait sur la Raspberry pour que le serveur soit opérationnel à savoir : installation d'openssh server pour le contrôle à distance, redirection d'un port du routeur vers le serveur pour le ssh, réservation d'une adresse privée fixe, création du sous domaine mail.mcreteur.fr et paramètrages DNS associés, changement du nom d'hôte et du FQDN et finalement, installation de Docker et Docker Compose.


  • Constitution du conteneur principal : Sur le serveur Ubuntu, nous avons rencontré aucun problème pour le lancement du conteneur. Cependant, le serveur web n'a pas été au point tout de suite et il a fallu de nombreuses modifications et de nombreux tests avant que ce dernier soit fonctionnel. La version finale du Dockerfile permettant de mettre en service le serveur web nginx est la suivante :

Dockerfile du serveur web


On télécharge la dernière version de Nginx, on remplace le fichier de configuration par défaut de Nginx par celui que nous avons créé, on intègre notre page html d'accueil du serveur web au bon endroit et enfin on expose les ports 80 (HTTP) et 443 (HTTPS). Comme pour Postfix, nous avons créé un fichier de configuration pour nginx. Dans ce dernier, on précise que l'on souhaite écouter sur le port 80, que le domaine est mcreteur.fr et on donne le dossier lequel le test pour la certification doit se faire.

Avant de pouvoir lancer le conteneur, il faut rediriger les ports du routeur vers le serveur afin de pouvoir accéder au serveur web. On libère donc les ports 80 et 443 et on les redirige vers le serveur. On lance le conteneur par la commande docker :

   sudo docker run --tty -i -p 80:80 -p 443:443 -v certs:/etc/letsencrypt -v certs-data:/data/letsencrypt mcreteur/certification-letsencrypt:v5

Cette commande permet de lancer le conteneur en mode interactif, en mappant les ports 80 et 443 de l'hôte sur ceux du conteneur et en mappant des volumes dans lesquels seront stockés les certificats. Grâce à cette commande, le serveur web est en ligne et accessible à l'adresse mcreteur.fr. On peut donc désormais lancer la certification par le Certbot par la commande :

   docker run -it --rm  -v certs:/etc/letsencrypt  -v certs-data:/data/letsencrypt  deliverous/certbot  certonly  --webroot --webroot-path=/data/letsencrypt --register-unsafely-without-email --agree-tos  -d mcreteur.fr

Cette commande permet de lancer le conteneur Certbot qui se supprimera lui même après avoir fait ce qu'il a à faire, pour certifier le domaine mcreteur.fr en mappant les mêmes volumes que pour le serveur web. Les premières fois que nous avons lancé ce conteneur, la certification a échoué, l'accès au domaine mcreteur.fr par le port 443 (HTTPS) était refusé par le serveur. En effet, sur le serveur, le port 443 était bloqué. Nous l'avons ouvert par la commande :

   sudo ufw allow out 443/tcp

Une fois le port 443 ouvert, la certification a été réalisé avec succès :

Certification du domaine


Il a alors fallu modifier le fichier de configuration nginx.conf pour permettre l'accès au serveur web en HTTPS par le port 443. Nous avons alors indiqué au serveur web à travers ce fichier, qu'il fallait en plus d'écouter sur le port 80, écouter aussi sur le port 443 en activant le protocole SSL et en indiquant de nombreux paramètres pour ce protocole. Une fois cela fait, nous pouvons accéder au domaine en HTTPS, la connexion à ce dernier est chiffrée :


Accès HTTPS au site web

Semaine 10

  • Mise en place de l'environnement de travail : Nous avons rencontré un léger problème par rapport à l'accès à distance au serveur Ubuntu installé. La connexion à ce dernier par SSH n'était pas possible alors que la redirection du port dédié au SSH sur le routeur n'avait pas changé. Le problème venait au final du fait que les ports du serveur sont protégés par un firewall. Nous avons alors débloqué un port pour le SSH de la même manière que la semaine dernière pour les ports dédiés au HTTP/HTTPS. Il faudra donc penser à ouvrir les ports nécessaires pour la communication SMTP et IMAP par la suite.
  • Constitution du conteneur principal : Maintenant que nous sommes en possession de certificats TLS/SSL, nous avons indiqué leur chemin (/etc/letsencrypt/live/mcreteur.fr/) dans notre configuration Postfix. Il faudra alors lier le volume Docker les contenant lors de l'exécution du conteneur principal afin qu'ils soient utilisables et ainsi pouvoir réaliser des connexions SMTP chiffrées. Nous avons aussi essayé d'approfondir la multitude de paramètres Postfix existants. Notre configuration de Postfix actuelle reste assez flou, nous pourrons sans doute beaucoup mieux comprendre les différents paramètres lors des tests qui ne sont pour l'instant pas réalisables.

Semaine 11

  • Constitution du conteneur principal : Après avoir passé beaucoup de temps sur la configuration de Postfix sans pouvoir réellement tester, nous avons décidé de passer à autre chose. Nous nous sommes alors lancés dans la mise en place du webmail Rainloop. Nous reprenons alors le Dockerfile utilisé pour Nginx puisque nous devrons indiqué au serveur web qu'il doit charger les fichiers de Rainloop. On récupère alors les fichiers d'installation par la commande :
  RUN wget http://repository.rainloop.net/v2/webmail/rainloop-latest.zip

Ensuite, on créé un dossier pour accueillir le webmail, on y décompresse les fichiers d'installations et on supprime l'archive :

  RUN mkdir /var/www/rainloop
  RUN unzip rainloop-latest.zip -d /var/www/rainloop
  RUN rm -rf rainloop-latest.zip

Le dossier /var/www/rainloop sera à partager avec Nginx pour pouvoir avoir le webmail sur notre serveur. Il faut donc modifier les droits sur ces dossiers :

 WORKDIR /var/www/rainloop
 RUN find . -type d -exec chmod 755 {} \; 
 RUN find . -type f -exec chmod 644 {} \; 
 RUN chown -R www-data:www-data .

Ces lignes dans le Dockerfile permettront d'installer correctement Rainloop dans le conteneur. Il faut maintenant modifier la configuration de Nginx pour pouvoir mettre en ligne le Webmail sur notre domaine. On modifie alors le fichier nginx.conf que nous avions créé pour obtenir les certificats. Nous avons dû procéder à de nombreux essais avant d'être capables d'accéder au webmail via l'adresse mcreteur.fr en HTTPS. Au final, nous ne touchons pas à la configuration du serveur HTTP étant donné que nous voulons que le Webmail ne soit accessible qu'en HTTPS mais on modifie le bloc concernant le serveur HTTPS. On indique alors le dossier Rainloop à charger sur lequel nous avons précédemment modifier les permissions. On indique des emplacements pour les fichiers de log et quelques règles PHP. Les paramètres SSL avaient déjà été indiqué. On laisse pour server_name "mcreteur.fr" pour pouvoir accéder au webmail via cette adresse. Après avoir configuré Nginx, on se rend compte qu'il faut installer des bibliothèques PHP dans le conteneur. On indique ces dernières dans le Dockerfile, on créé une image Docker puis on lance le conteneur associé par la commande :

   sudo docker run --tty -i -p 80:80 -p 443:443 -v certs:/etc/letsencrypt -v certs-data:/data/letsencrypt mcreteur/messagerie:v2

Encore une fois, on lie les ports 80 (HTTP) et 443 (HTTPS) du conteneur sur ceux de l'hôte de façon à ce que l'on puisse accéder au serveur Nginx et on monte de nouveau les dossiers de l'hôte Docker dans lesquels sont contenus les certificats. Nous avons alors passé beaucoup de temps sur une erreur PHP que nous indiquait le serveur. Un service PHP n'était pas lancé au démarrage du conteneur ce qui ne permettait pas d'afficher le webmail. Il faut alors lancer la commande :

  service php7.0-fpm start

Sans lancer ce service au démarrage du conteneur, le webmail n'est pas accessible.


Accès au webmail en HTTPS

Semaine 12 et 13

  • Mise en place de l'environnement de travail : Nous avons redirigé les ports 25 (SMTP), 587 (SMTPD), 143 (IMAP) et 993 (IMAPS) du routeur sur notre serveur puis les avons ouverts sur ce dernier. Nous avons créé les sous domaines smtp.mcreteur.fr, client1.mcreteur.fr, client2.mcreteur.fr' qui seront nos MX sur le site du registrar. Nous avons fait pointé ces différents sous-domaines sur l'adresse publique du serveur et nous les avons enregistré en tant que MX pour le domaine mcreteur.fr.


  • Constitution du conteneur principal : Nous avons tout d'abord réalisé un Dockerfile global en rassemblant les différentes sous parties pour le conteneur principal à savoir : le serveur web Nginx, Postfix, Rainloop et PHP. Pour cela, il nous a suffit de mettre bout à bout les différents Dockerfile réalisés jusqu'à maintenant. En créant une image à partir de ce dernier, nous nous sommes rendus compte qu'il fallait lancer tous les services (PHP, Postfix, Nginx) manuellement une fois le conteneur lancé. Nous avons tenté d'intégrer des lignes de commande dans le dockerfile telle que :
  RUN service postfix start

Cependant, nous nous sommes aperçus que ça ne fonctionnait pas tout le temps. Nous avons alors décidé d'utiliser la commande ENTRYPOINT des dockerfile qui permet d'exécuter un script au lancement du conteneur :

  ENTRYPOINT ["script.sh"]

Cela nous a aussi posé problème puisque dès lors que l'intégralité du script a été exécuté, le conteneur se ferme tout seul. Notre conteneur s'arrêtait donc tout seul une fois que les services avait été lancé. Pour contrer ce problème, nous avons utilisé une petite astuce qui consiste à lancer un bash en fin de script de sorte à ce que le conteneur ne s'arrête pas :

  postconf -e "myhostname = $(hostname -f)"
  postconf -e "mydomain = $(hostname -d)"
  service postfix start 
  service php7.0-fpm start 
  service nginx start &
  exec "/bin/bash";

De cette façon, le conteneur ne se ferme pas tout seul et les services sont bien lancés automatiquement au démarrage. C'est une fois le conteneur démarré que nous nous sommes rendus compte de l'absence des fichiers de log de chaque service, assez problématique pour déboguer. Après quelques recherches, nous avons découvert qu'il fallait installer le service rsyslog pour voir apparaître des fichiers de log. Nous avons donc ajouter son installation dans le dockerfile et le lancement du service associé dans le script. Après cela, nous avons pu tester le fonctionnement de notre serveur SMTP. Nous avons alors lancé le conteneur avec l'option -h smtp.mcreteur.fr qui permet de configurer le hostname du conteneur et donc le domaine en correspondance avec les enregistrements du domaine. Nous avons utilisé un site web pour tester notre serveur SMTP (au moment du test le MX en question est mail.mcreteur.fr, non pas smtp.mcreteur.fr) :

Test serveur SMTP
Test serveur SMTP



















Visiblement, le serveur SMTP fonctionne et supporte bien l'encryptage TLS. La ligne "Reverse DNS is not a valid Hostname" nous indique probablement un défaut de configuration DNS. On peut aussi voir que le serveur n'accepte pas les mails extérieurs.


  • Constitution du conteneur utilisateur : Une fois le conteneur principal en place, nous avons commencé à constituer le conteneur utilisateur qui est censé héberger Postfix (SMTP) et Dovecot (IMAP). Pour ce qui est de Postfix, nous avons dans un premier temps simplement fait un copié coller de la configuration du conteneur principal. Nous ferons les modifications nécessaires lors des tests. Pour Dovecot, la configuration se fait à travers les fichiers :
    • 10-auth.conf : Choix des processus d'authentificaton
    • auth-system.conf : Configuration de l'authentification
    • 10.mail.conf : Configuration de la boîte aux lettres
    • 10.master.conf : Configuration des services
    • 10-ssl.conf : Configuration SSL
    • dovecot.conf : Fichier de configuration principal

On indique alors dans ces fichiers que l'on utilise les protocoles IMAP et LMTP (Pour le transfert local des mails), on configure les paramètres SSL, on indique l'emplacement du dossier qui contiendra les mails ainsi que son utilisateur etc. On créé un dockerfile du même type que celui du conteneur principal : on installe rsyslog, postfix et dovecot, on intègre tous les fichiers de configuration, on expose les ports adéquats et on réutilise la commande ENTRYPOINT avec un script lançant cette fois les services rsyslog, postfix et dovecot.


  • Tests et débogage de la solution : Pour tester la solution, nous avons besoin de trois conteneurs : le conteneur principal ainsi que deux conteneurs clients. Les conteneurs clients doivent utiliser le conteneur principal comme relai, leurs ports n'ont donc pas besoin d'être liés à l'hôte (heureusement d'ailleurs puisqu'un port ne peut être occupé que par un seul client). Les ports des conteneurs clients sont tout de même exposés de sorte à pouvoir communiquer avec le relai. On lance ces derniers par les commandes :
  sudo docker run -h client1.mcreteur.fr -it -v certs:/etc/letsencrypt -v certs-data:/data/letsencrypt mcreteur/client:latest
  sudo docker run -h client2.mcreteur.fr -it -v certs:/etc/letsencrypt -v certs-data:/data/letsencrypt mcreteur/client:latest
  sudo docker run -h smtp.mcreteur.fr -it -p 80:80 -p 443:443 -p 25:25 -p 587:587 -v certs:/etc/letsencrypt -v certs-data:/data/letsencrypt mcreteur/messagerie:latest

Nous avons alors rencontré de nombreux problèmes avant d'avoir quelque chose de fonctionnel. Lorsque l'on voulait envoyé un mail du client1 au client2 par l'utilitaire telnet, le mail parvenait bien au relai mais y restait bloqué :

Logs expéditeur


Logs relai


Il semblait y avoir un problème de routage des messages. Pour contrer ce problème, nous avons créé un réseau docker bridge dédié à la solution de messagerie par la commande :

  docker network create --driver bridge messagerie

Au lancement des conteneurs, il fallait alors préciser l'utilisation de ce réseau ainsi qu'un nom de conteneur afin de faciliter la résolution de nom :

  sudo docker run --network messagerie --name smtp -h smtp.mcreteur.fr -it -p 80:80 -p 443:443 -p 25:25 -p 587:587 -v certs:/etc/letsencrypt -v certs-data:/data/letsencrypt mcreteur/messagerie:latest

En plus de cela, nous avons apporté des modifications aux fichiers de configuration Postfix. Nous avons ajouté dans la configuration du relai, le paramètre : transport_maps que nous avons lié à un fichier transport. Celui-ci permet d'indiquer le routage des messages à effectuer :

  client1.mcreteur.fr   smtp:[client1.messagerie]
  client2.mcreteur.fr   smtp:[client2.messagerie]

Par ce fichier, on indique que les messages à destination de client1 doivent être transmis au serveur smtp associé et de même pour le client2. Nous avons ici utiliser la résolution DNS intégrée à Docker. client1.messagerie signifie le conteneur nommé client1 du réseau messagerie. Les conteneurs sont capables de résoudre des noms d'hôtes au sein d'un réseau Docker. Du côté de la configuration des clients, nous avons utilisé le paramètre :

  relayhost = [smtp.mcreteur.fr]

Cela permet de systématiquement passer par le serveur smtp relai pour la transmission de mail. Nous avons aussi dû attribuer au paramètre mydestination la valeur myhostname pour indiquer que les courriers a destination de leur hostname leur sont destinés. Après avoir corrigé ce problème, nous en avons eu un par rapport à l'authentification SASL de dovecot mise en place. Le mail était bien transféré au destinataire mais le serveur IMAP destinataire n'acceptait pas le mail parce que l'expéditeur n'était pas authentifié correctement :

Logs expéditeur


Logs relai


Logs destinataire


Par manque de temps, plutôt que de mettre en place une base de données contenant les différents utilisateurs et leur mot de passe, nous avons configuré la réception des mails pour qu'elle fonctionne uniquement à destination de l'utilisateur mail. Après cela, il nous était possible d'envoyer des mails entre les différents clients. Nous sommes alors passé à la configuration du webmail Rainloop via l'interface web pour configurer les différents domaines :


Ajout du domaine client1.mcreteur.fr sur Rainloop


Nous avons cette fois encore utiliser la résolution DNS Docker. Après avoir ajouté les domaines client1.mcreteur.fr et client2.mcreteur.fr, nous avons pu nous connecter sur le webmail et échanger des mails :


Réception d'un mail de client1 sur le compte de client2


Il nous est aussi possible d'envoyer des mails vers l'extérieur :

Réception d'un mail de client2 sur le compte Gmail personnel


  • Écriture des scripts : Comme était demandé dans le sujet, nous avons écrit des scripts bash permettant de créer un utilisateur, lister les utilisateurs et supprimer un utilisateur.

Pour automatiser la solution, certaines choses sont nécessaires. Il faut que le fichier transport de routage de mail du serveur de relai soit mis à jour au cours de l'ajout/suppression d'utilisateur de même que le fichier de configuration des domaines du webmail Rainloop. De même, pour que la solution soit utilisable, il faut que les mails des utilisateurs persistent en cas de crash et soient supprimés si l'utilisateur le demande.

Nous avons décidé d'écrire un script supplémentaire permettant de lancer le serveur principal. Dans ce dernier, on initialise le fichier transport, on créé le réseau docker qui accueillera les différents conteneurs et on lance le conteneur principal.

Le script d'ajout d'utilisateur prend le nom de l'utilisateur à ajouter en paramètre. On créé un fichier de configuration de domaine pour cet utilisateur que l'on copie à l'intérieur du conteneur principal grâce à la commande docker cp. On met à jour le fichier transport, on recréé la base de donnée Postfix à partir de ce fichier et on recharge Postfix. Finalement, on lance un conteneur client.

Le script permettant de lister les utilisateurs était relativement simple à faire puisqu'il se résume en une ligne :

  sudo docker ps --filter network=messagerie --format ".Names"

Cette commande Docker affiche les noms des conteneurs se trouvant sur le réseau messagerie.

Finalement, le script de suppression d'utilisateur prend en paramètre l'utilisateur à supprimer. Si cet utilisateur est le conteneur principal, on fait le ménage. C'est à dire que l'on supprime tous les utilisateurs, leur volume de mail associé et le réseau Docker. Sinon on stoppe le conteneur en question et on supprime son volume mail.

Malheureusement, ces scripts ne gèrent pas la configuration DNS étant donné que nous n'avons pas installé de serveur DNS nous-même. Il faut donc veiller à ce que les utilisateurs du système aient un sous-domaine associé et un enregistrement MX de ce sous-domaine pour le domaine principal.

Documents Rendus

Bibliographie

Voici les principaux sites utilisés pour la réalisation du projet :

Ainsi que de nombreux forums pour le débogage.