P9 Système d'hébergement domestique

De Wiki d'activités IMA
Révision datée du 28 octobre 2015 à 16:11 par Rlibaert (discussion | contributions) (Firewall)

Cahier des charges

Présentation générale du projet

Contexte

Les gens font confiance à des organismes comme google pour gérer leurs courriels, voire pour les protéger. Il n'est pas évident que leur confiance soit bien placée. Ce projet doit permettre à tout utilisateur de créer quelques comptes de messagerie sur une système embarqué de type raspberry et permettre de conserver les données à la maison.

Le système doit être constitué à base de standards (base LDAP, serveur de messagerie connu et maintenu, client de messagerie idem). L'interface d'administration doit être elle aussi très simple d'utilisation.

Un effort particulier doit être porté sur l'alimentation du système embarqué. L'idéal serait un mode de veille lorsqu'aucun paquet TCP/IP n'est adressé à la machine. Il est aussi demandé de mettre au point une alimentation à base d'énergie renouvelable (e.g. panneau solaire) permettant d'alimenter totalement ou partiellement le système. Enfin pour permettre de se passer de la box grande consommatrice d'énergie, le système embarqué doit pouvoir en reprendre les fonctionnalités principale (connexion avec le DSLAM, redirection des ports UDP/TCP, ...).

Objectif du projet

L'objectif est de réaliser un système embarqué avec une alimentation autonome pour héberger une messagerie électronique domestique. Par domestique, il faut comprendre pour une dizaine de boites aux lettres. En outre, le système devra pouvoir être alimenté par un panneau solaire ou, le cas échéant, prendre relai sur le secteur lorsque l'alimentation fournie par le soleil n'est plus suffisante.

Description du projet

Choix techniques : matériel et logiciel

Matériel obtenu à ce jour :

  • 1 Raspberry Pi 2 [obtenue le 07/10/2015]
  • 1 Carte µSD 8 GB [obtenue le 07/10/2015]
  • 1 Cable USB/µUSB [obtenu le 07/10/2015]
  • 1 Câble RJ45 [obtenu le 07/10/2015]

Système d'hébergement domestique : développement détaillé

Explications et compte rendu.

Suivi de l'avancement du Projet

Semaine 1 (21/09/2015)

Notre but étant la réalisation d'une messagerie électronique domestique capable de gérer une dizaine de boites aux lettres, nous nous orientons dans un premier temps sur les points suivants que nous allons éclaircir afin d'en tirer un cahier des charges.

Nous allons étudier et approfondir les points suivants :

  • Installer une base LDAP, ou avoir plutôt avoir plusieurs comptes UNIX
  • Installer un serveur de messagerie SMTP, et IMAP/POP
  • Investiguer du côté de POSTFIX
  • Étudier la taille d'un mail vide, et en moyenne, et voir combien ça fait par rapport au système
  • Enquêter sur la forme des fichiers utilisateurs (généraliser les données)

Ce qui doit pouvoir être fait :

  • Distinction administrateur / utilisateur
  • Un administrateur doit pouvoir gérer les comptes de messagerie (addition/suppression/etc)
  • Gestion des quotas/espace disque réservé par ex
  • Choix du quota (par qui ? options ?)
  • SECURISER : apache, mod_security, étudier l'utilisation d'un pare-feu logiciel ?

Prévision du Matériel :

  • Raspberry Pi 2
  • Alimentation RPi
  • Carte SD (8Go)

Le module énergétique sera équipé des éléments suivants :

  • 1 MPPT
  • Convertisseur Numérique Analogique : MAX5250
  • Potentiomètre : MCP4261
  • Relai : R561D.56 NTE
  • Résistances : Deux de 100Ω et deux de 10kΩ
  • une LED
  • 40 pins broches mâle/mâle (Digikey Parts : A26509-40-ND), découpé par la suite en 8-8-6-4
  • Circuit d'alimentation autonome : cellule photovoltaique
  • Circuit d'alimentation autonome : batterie (avec port micro-USB et port USB)

Semaine 2 (28/09/2015)

Dans un premier temps l'idée est de développer le système principal avec les fonctionnalités. Autrement dit les différents packages et fonctionnalités installées sur la raspberry ainsi que l'interface utilisateur sur le site web. Dans cette partie nous listerons les différentes fonctionnalités que nous aimerions implémenter.


☐ Serveur SMTP (communications entre serveurs mails SMPT) et serveur IMAP/POP3 (postier)

  • Postfix pour SMTP
  • Dovecot, Courier ou Cyrus pour IMAP/POP3
  • Implémentation de protocoles plus complexes et offrant notamment des fonctionnalités de chiffrement (SMTPS / ESMTP / SSL / HTTPS / Certificat)
  • LMTP

☐ Gestion particulière des gros mails et notamment de leurs pièces jointes

  • Bigfile pour un stockage en ligne
  • Décodage base 64 des pièces jointes ? (difficulté++)

☐ Gestion des utilisateurs

  • Plusieurs comptes, en utilisant LDAP
  • La possibilité de s'identifier en tant qu'administrateur

☐ Listes de diffusion

☐ Comptes mail temporaires (10 minutes mail like)

☐ Antivirus & Spam

  • ClamAV ou SpamAssassin ou autres : lourd.
  • iptables dans un premier temps.
  • Antispam maison, gestion du contenu, marquage de spam par l'utilisateur, "boites intelligentes" de spams.

☐ Les noms de domaines sont peut être nécessaires dès le départ pour tester le fonctionnement des fonctionnalités (telnet qui dit nope ?)

  • Record A
  • Record MX

☐ Sauvegarde automatique périodique de la Raspberry Pi (pendant le développement, pour éviter de perdre les données)

Il faudra aussi prêter attention aux fonctionnalités disponibles sur l'interface et ne pas laisser des fonctionnalités fantômes issues d'un template générique que l'on a pu trouver sur l'Internet.

Semaine 3 (05/10/2015)

Nous avons précisé les éléments constituants l'interface web :

  • Gestion des comptes (création, modification, suppression d'utilisateurs...)
  • Gestion des listes de diffusions
  • Gestion des quotas
  • Affichage du courrier
  • Gestion de l'antivirus

Semaine 4 (12/10/2015)

Nous avons mis en place un github pour suivre le développement : GitHub.

Nous commençons à visualiser la structure de notre serveur mail. Dans un premier temps nous constituons notre base de données. Finalement nous utiliserons bien LDAP, qui semble relativement simple à utiliser contrairement à notre première impression.

Nous avons utilisé un tutoriel de Gandi pour mettre en place la base de notre annuaire. Nous utiliserons les schemas disponibles dans le paquet courier-ldap. Nous avons écrit un script en perl permettant d'installer ce schema facilement, nous évitant d'avoir à réinstaller le paquet complet pour récupérer un unique fichier.


Il est important maintenant de changer les règles d'accès à la base de données. En effet la base de données est disponible pour n'importe qui, on peut y entrer avec la commande :

ldapsearch -c -h localhost -b dc=domain,dc=tld -x

Nous avons ici aussi écrit un script permettant de le faire automatiquement. A ce stade il est nécessaire de s'identifier en tant qu'administrateur pour voir l'arbre :

ldapsearch -c -h localhost -b dc=domain,dc=tld -D "cn=admin, dc=domain,dc=tld" -W


On peut dorénavant développer la structure de notre directory. Nous avons choisi de reprendre la base du tutoriel de Gandi et d'ajouter une entité mail qui regroupera tout les utilisateurs du serveur mail. Nous avons donc écrit un fichier .ldif décrivant cette structure et l'avons ajoutée avec la commande :

ldapadd -D "cn=admin,dc=domain,dc=tld" -W -h localhost -f ldif/mail_tree.ldif

On peut vérifier que la structure a bien été ajoutée à notre arbre avec la commande :

ldapsearch -D "cn=admin,dc=domain,dc=tld" -W -h localhost -b "dc=domain,dc=tld"


Maintenant, on peut ajouter nos utilisateurs à la base de données. Ici il est d'autant plus intéressant d'automatiser cette manipulation. Le principe est d'écrire un fichier .ldif et de l'ajouter de la même manière que précedemment avec ldapadd. Nous nous sommes inspirés ici encore du tutoriel de Gandi tout en l'adaptant. Le script perl add_user.pl simplifie grandement l'ajout d'un utilisateur. On pourra par la suite le modifier pour l'utiliser directement avec du code php. On peut vérifier que l'utilisateur a bien été ajouté avec la commande habituelle ldapsearch et même tester l'identification avec :

ldapwhoami -vvv -h localhost -D "cn=username,dc=mail,dc=domain,dc=tld" -x -W

Si la commande renvoie Result: Success (0) alors l'identification a fonctionné.


La commande ldapsearch permet aussi de filtrer les recherches dans la base. Par exemple, avec notre configuration on peut afficher les utilisateurs avec la commande :

ldapsearch -D "cn=admin,dc=domain,dc=tld" -W -b "dc=mail,dc=domain,dc=tld" "(&(objectClass=CourierMailAccount))"

On peut aussi indiquer quels champs à afficher en les indiquant à la fin de cette commande.

Semaine 5 (19/10/2015)

DNS et SSL

Nous avons obtenu un nom de domaine auprès de Gandi pour notre projet. Le site est accessible à l'adresse : intimail.pw

nous avons configuré un serveur DNS et la certification SSL sur notre raspberry pi. Pour la démarche je vous renvoie à notre wiki de TP de Protocoles Réseaux Avancés. La méthode est identique.

De la même manière que dans le TP de PRA, nous voulions implémenter DNSSEC. Cependant arrivé à la dernière étape, nous nous sommes rendu compte que Gandi ne propose pas cette fonctionnalité pour les .pw. Dans l'éventualité où les DNSSEC seraient implémentés au cours de notre projet, nous pourrons activer cette fonctionnalité rapidement.

La différence réside dans le fait que pour un serveur mail il faut un enregistrement de type MX. Dans le fichier de configuration des enregistrements de bind, nous avons ajouté les lignes :

@       IN      MX      10 mail.intimail.pw.
mail    IN      A       193.48.57.171

De plus, un serveur mail doit pouvoir faire les résolutions inverses. En effet certains serveurs mail sont configurés pour rejeter ou retarder la livraison de mails provenant de serveurs dont la résolution inverse n'est pas effectuée. L'enregistrement PTR devient alors :

171     IN      PTR     mail.intimail.pw.

A ce stade, le serveur DNS devrait être correctement configuré et le SSL fonctionnel.

LDAP

Pour notre annuaire LDAP, nous avons utilisé les schémas proposés dans le package courier-ldap. Ces fichiers particuliers permettent à ldap de structurer sa base de données. Après différents essais et discussion, nous avons retenu la structure suivante :

LDAP directory structure

Nous avons regroupé la totalité de nos entrées sous une entité commune mail, celle ci se divisant ensuite en deux groupes people et groups. Le dc people regroupe les informations des utilisateurs, que l'on détaillera plus tard. Le dc groups permettra quant à lui regroupera les différentes listes de diffusion. Il contient aussi le groupe particulier des administrateurs qui permettra de donner des droits privilégiés à certains utilisateurs.

Pour ce qui est des informations des utilisateurs, voici un exemple de fichier de configuration pour l'utilisateur Jean Valjean :

dn: cn=jvaljean,dc=people,dc=mail,dc=intimail,dc=pw
uid: jvaljean
mail: jvaljean@intimail.pw
sn: Valjean
givenName: Jean
displayName: Jean Valjean
mailbox: intimail.pw/jvaljean/
homeDirectory: /home/vmail/
objectClass: top
objectClass: inetOrgPerson
objectClass: CourierMailAccount
userPassword: {SSHA}gCbVPaSGUaqjrq0mTQY77sOH4Xcq59Fg

Ces différentes informations ne sont pas définitives : certains champs peuvent peut être être retirés (comme le champ homeDirectory qui pour l'instant est commun et identique à tout les utilisateurs).

Web

Nous avons cherché un template léger, simple, mais néanmoins fonctionnel et agréable pour notre interface web. L'idée est, plutôt que de prendre un webmail classique dont nous n'utiliserions que 25 à 50% des capacités, de réaliser un webmail qui répond à toutes les exigences du cahier des charges et implémentant uniquement le nécessaire. Il s'est avéré après recherches que l'une des meilleures solutions était de partir sur une interface codée en PHP (ce dernier implémente une API dédiée à LDAP), agrémentée de Bootstrap pour le JS/CSS. Notre choix s'est finalement porté sur le template Lumino, que l'on peut essayer par ici.

Après divers test, il s'avère qu'une page de cette interface met en moyenne pour charger totalement :

  • 2,10s sur une connexion mobile 3G moyenne (4MB/s)
  • 1,90s sur une connexion 4G moyenne (15MB/s)
  • 2,80s sur une connexion DSL moyenne (2MB/s)
  • 1,90s sur une connexion Wifi (30MB/s)
  • 1,70s sur une connexion THD (100MB/s)

Résultats qui semble apporter bon compris poids/qualité de l'interface.

Nous avons alors déployé cette interface, dans un dossier /var/www/webmail/, puis ajouté le VirtualHost correspondant à notre site dans la configuration apache

Config à venir, quelqu'un a éteint tutur06, notre raspberry est donc off :(

Semaine 6 (26/10/2015)

Firewall

Etant donné que nous avons subi plusieurs tentatives de connexion frauduleuses sur notre serveur, nous avons décidé de mettre en place un semblant de sécurité sur ce dernier. Nous avons donc écrit un petit script iptables simples pour filtrer les entrées. Celui ci se contente de bloquer tout les paquets entrant et de laisser passer les paquets par les ports ou nous avions vraiment besoin (ici SSH, HTTP, HTTPS, DNS, NTP, SMTP, POP3 et IMAP). Après discussion, nous avons resserré davantage nos règles. Désormais le SSH n'est autorisé que pour des adresses ip spécifiées dans un fichier de liste blanche.

Nous avons aussi repéré dans le fichier /var/loh/auth.log plusieurs tentatives de connexions. Dans un premier temps nous avions cru à un problème de configuration de notre structure. Après avoir vérifié dans le log /var/log/syslog nous nous sommes aperçu qu'il s'agissait de connexions depuis des ip extérieures qui nous sont inconnues. Etant donné le nombre d'essais nous pensons que c'était une tentative d'intrusion sur le serveur SMTP par bruteforce. Comme première approche de contre-mesure nous avons pris le parti de constituer une liste noire. En effet ici nous n'avons pas le choix de laisser le port 25 (SMTP) ouvert. Pour cela nous avons utilisé les commandes :

cat /vat/log/syslog | grep SASL\ LOGIN\ authentication\ failed                           # Pour lister les messages de connexion échouées
sed -ne 's/.*\[\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\)\].*/\1/p'      # Pour n'afficher que les ip
*file* | sort | uniq                                                                     # Pour classer et éliminer les doublons

On peut ensuite vérifier que les ip listées sont bien inconnues. Nous avons ainsi constitué une liste noire de 23 adresses ip.

Postfix

Nous avons installé l'agent de transfert de mail Postfix (apt-get install postfix postfix-ldap) sur la raspberry et configuré celui ci en accord avec notre base de données LDAP. Après un test d'envoi via telnet :

telnet ex 25
Trying xxx.xxx.xxx.xxx...
Connected to intimail.pw.
Escape character is '^]'.
220 mail.intimail.pw
ehlo intimail.pw
250-mail.intimail.pw
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
MAIL FROM:toto(arobase)titi.com
250 2.1.0 Ok
RCPT TO:jvaljean(arobase)intimail.pw
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
Subject: Premier Test
Here is my test
.
250 2.0.0 Ok: queued as 0EDFC21428
quit
221 2.0.0 Bye
Connection closed by foreign host.

Il est maintenant intéressant de tester notre DNS avec un outil en ligne. Nous avons ici utilisé l'excellent dnsstuff pour cela. C'est grâce à ce dernier que nous avons pu corriger les erreurs de notre serveur mail, à savoir :

  • SMTP Greeting : Il permet de faire en sorte que le serveur mail est reconnu par les autres serveurs. Cela évite que certains serveurs ne refusent les mails provenant d'intimail.pw.
  • Acceptance of abuse/postmaster : Les serveurs mails doivent avoir deux adresses abuse@... et postmaster@... . Nous avons donc créé ces deux boîtes mail pour répondre à ces conditions

Cyrus SASL

Nous avons implémenté l'authentification sur le serveur SMTP en SASL avec Cyrus. Après configuration, on peut maintenant envoyer des mail depuis notre serveur sur un serveur extérieur tel que gmail.

LDAP

Nous avons créé quelques utilisateurs LDAP pour peupler notre répertoire, contenant diverses informations utiles, afin de pouvoir commencer à implémenter une API d'authentification et réaliser divers essais sur l'interface web. Nous avons aussi ajouté un champ quota dans les informations des utilisateurs. A première vue ce champ pourra être utilisé avec le serveur IMAP et POP3. Cependant, afin d'éviter d'installer des services supplémentaires, nous choisissons de nous orienter dans une autre direction. Postfix nous permet à l'heure actuelle d'envoyer et recevoir des mails avec nos utilisateurs virtuels, et stocke chaque mail dans un fichier sur le système. L'interface web peut donc, sans Dovecot ou serveurs IMAP/POP3, parser par elle-même les mails reçus et préparer un envoi. Il nous faut, en prenant cette voie, réfléchir à l'implémentation des quotas, non gérés par PostFix. L'idée serait de lancer un script quand Postfix reçoit un mail, avant de le stocker sur le système, et de vérifier que la taille de ce mail + de ceux déjà reçu/envoyés par avant ne dépasse pas le quota attribué à un utilisateur, et rejeter le mail à l'expéditeur si on va dépasser alors le quota.

Web

Nous avons modifié le template de site web en accord avec nos objectifs. L'utilisateur doit d'abord se connecter avec ses identifiants LDAP (uid et mot de passe correspondant à son unique Distinguished Name (DN: cn=jvaljean,dc=people,dc=mail,dc=intimail,dc=pw). Une fois connecté, il tombe sur une interface que l'on pourrait appeler une "vue globale", réunissant les informations principales : le nombre de nouveaux mails, l'utilisation actuelle de son quota sur le disque, les quelques derniers mails reçus, et un calendrier afin de se repérer simplement niveau date. Sur le côté, il est possible d'aller voir plus en détail l'inbox où se trouvent tous les mails reçus, ou encore aller voir les messages envoyés, et supprimer les courriels dans la poubelle. Si l'utilisateur est administrateur, il a aussi accès à un onglet "Manage" d'où il pourra prendre fonction de ses pleins pouvoirs. Cette dernière fonctionnalité n'étant pas encore implémentée, tout utilisateur voit pour l'instant cet onglet.

Toute la journée du mardi le code web a été réaménagé et modulé. Nous réfléchissons désormais au stockage et à la récupération de l'état instantané du quota mail (stocker cette valeur dans un fichier, ou en fait un attribut supplémentaire d'un utilisateur LDAP, où est d'ailleurs déjà stocké son quota max). L'idée est de ne pas trop solliciter le système et d'incrémenter ou décrémenter une variable à chaque réception/envoi de mail plutôt que recalculer entièrement la taille du dossier où sont les mails. On pourra en outre envisager de mettre en place une tâche périodique (via CRON) qui vérifiera en heures creuses que la taille du dossier mail est bien égale au quota en variable dans le système.

Par la suite il a été convenu de supprimer Apache et de le remplacer par le serveur web Lighttpd, plus léger et plus performant. Pour la configuration, on rajoute simplement un hôte au fichier /etc/lighttpd/lighttpd.conf auquel on fournit notamment le chemin d'accès aux fichiers du site, ou encore les clés pour SSL. Nous avons alors réinstallé PHP et nous l'avons reconfiguré et activé pour Lighttpd. Enfin, l'activation du mod_rewrite et la mise en place de règles différentes de celles d'Apache (qui font la même chose mais à la sauce Lighttpd) nous permettent de conclure cette migration en environ 25-30min (!). Le mod_rewrite, un peu gadget nous l'avouons, permet chez nous de résoudre une URL de type www.domaine.com/page.php en écrivant simplement www.domaine.com/page. On atteint donc la page de connexion de notre webmail par https://www.intimail.pw/login. Nous avons en outre pu préciser la suite de notre projet. L'idée est d'avoir 2 ports sur lequel Postfix écoute (disons *:25 et localhost:10025). A réception d'un email sur *:25, postfix est configuré pour lancer un script que nous réalisons. Ce script vérifie le quota de l'utilisateur, si le mail reçu ne le dépasse pas il transfère alors le mail à localhost:10025 qui l'accepte et écrit le mail sur le disque de manière normale. Sinon, il renvoie un code d'erreur et le mail n'est pas accepté. De plus, le script mettra à jour un index dans un fichier propre à chaque utilisateur que le webmail lira. En somme, l'utilisation de fichiers quota et index évite à l'interface web de vérifier entièrement les dossiers et sous-dossiers mail à chaque actualisation de la page, ce qui créerait une charge énorme pour la Pi. On s'abstient en plus d'installer Dotecove/Un serveur IMAP/Un serveur POP grâce à notre webmail et nos scripts qui gèrent tout et uniquement ce dont nous avons besoin. Notre architecture s'oriente donc sur les schémas suivants :

A classical mail server infrastructure
Our light mail server infrastructure

Semaine 7 (02/11/2015)

Semaine 8 (09/11/2015)

Semaine 9 (16/11/2015)

Semaine 10 (23/11/2015)

Semaine 11 (30/11/2015)

Semaine 12 (07/12/2015)

Semaine 13 (14/12/2015)

Semaine 14 (04/01/2016)

Semaine 15 (11/01/2016)

Semaine 16 (18/01/2016)

Semaine 17 (25/01/2016)

Semaine 18 (01/02/2016)

Semaine 19 (08/02/2016)

Semaine 20 (15/02/2016)

Semaine 21 (22/02/2016)

Fichiers Rendus

Interface web : [http:// Soon™] Rapport de Mi-Projet : [http:// Soon™] Rapport de Projet : [http:// Soon™]