Permettre une authentification unifiée pour SMTP, POP/IMAP et FTP

De e-glop
Révision datée du 9 janvier 2013 à 10:47 par BeTa (discussion | contributions) (vsftpd)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)

Introduction

Objectif

Avoir une authentification unifiée entre services FTP, IMAP, POP3 et SMTP.

Notes

Ici il s'agira d'un "backend" PostgreSQL. L'équivalent est tout à fait imaginable pour MySQL bien entendu, à quelques détails près.

Cette solution permet, dans un second temps, de mettre en place une interface unifiée de gestion de ses comptes. Ainsi en deux clics, il sera possible de créer un compte courriel et son compte FTP associé et que tout soit mis en place très rapidement.

Pré-requis

Vous aurez sans doute besoin de prendre connaissance de la première partie de cette documentation : Paramétrer un serveur mail Postfix, Courier-IMAP avec authentification PostgreSQL et SASL

Les commandes proposées sont parfois directement liées aux infrastructures basées sur les distributions Debian (Ubuntu par exemple).

Mise en œuvre de l'authentification unifiée

Besoins et débouchés

Nous avons tout notre système de messagerie qui fonctionne déjà sur une authentification via PostgreSQL. Nous souhaitons donc appuyer l'authentification des utilisateurs virtuels de vsftpd sur ce même mécanisme.

Afin de permettre l'authentification sur PostgreSQL de vsftpd, il faut passer par pam-pgsql. Installons donc ce module de PAM si ce n'est déjà fait :

sudo apt-get install libpam-pgsql

PAM

il est nécessaire de configurer PAM pour se connecter à PostgreSQL :

$ sudo vi /etc/pam.d/vsftpd

# Standard behaviour for ftpd(8).
auth	required	pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed

# Note: vsftpd handles anonymous logins on its own.  Do not enable
# pam_ftp.so.

auth required pam_pgsql.so config_file=/etc/pam.d/vsftpd.pgsql.conf
account required pam_pgsql.so config_file=/etc/pam.d/vsftpd.pgsql.conf

Afin que l'authentification se fasse correctement, il faut faire connaître à PAM le schéma vu précédemment :

$ sudo vi /etc/pam.d/vsftpd.pgsql.conf

debug
pw_type = md5
connect = hostaddr=HOST port=5432 dbname=DB user=USER password=PASSWORD connect_timeout=15
auth_query = select substring(password from 9) from mailbox where username = %u
acct_query = select NOT active AS acc_expired, 0 AS acc_new_pwreq, (password ISNULL OR password = ) as user_password from mailbox where username = %u

Vous noterez 3 points importants :

  • n'oubliez pas d'entrer vos paramètres pour permettre à PAM de se connecter à votre base de données
  • le mot de passe est en clair (cf. ci-après)
  • la requête spécifiée pour récupérer le mot de passe en base de données a été sensiblement adaptée par "substring(password from 9)" car vfstpd ne comprend pas le préfixe nécessaire à Postfix {MD5RAW}, que nous retirons donc artificiellement via ce hack.

afin d'éviter toute fuite d'information, nous ne pouvons que vous recommander de changer les droits du dernier fichier créé :

$ sudo chmod 640 /etc/pam.d/vsftpd.pgsql.conf

vsftpd

Enfin, pour ne pas que vsftpd fasse de correspondance entre nos utilisateurs virtuels et nos utilisateurs réels, nous allons le paramétrer en ce sens en rajoutant à votre configuration personnalisée :

$ sudo vi /etc/vsftpd.conf

# ajouter ces lignes dans le fichier de configuration
guest_enable=YES
guest_username=ftpsecure
user_sub_token=$USER
local_root=/ftp/$USER
EOF

Attention à ce que le guest_username corresponde à un utilisateur réel de votre système, créé spécialement pour cet usage. Ça sera l'utilisateur réel commun à tous vos utilisateurs virtuels.

Bug possible sur le chroot des utilisateurs virtuels

Il est possible, depuis les dernières version 2.x de vsftpd que vous obteniez le message suivant lors d'une tentative de connection :

500 OOPS: vsftpd: refusing to run with writable root inside chroot()

Cela est en lien avec l'option chroot_local_user=YES. Pour contourner ce problème, tout en laissant les répertoires de vos utilisateurs accessibles en écriture, il est nécessaire d'ajouter l'option :

allow_writeable_chroot=YES
#allow_writable_chroot=YES # pour vsftpd-ext

Cependant, ce n'est pas tout. Pour certaines version 2.x de vsftpd (au moins la 2.3.5 fournie avec la Debian Wheezy à l'heure où ces lignes sont écrites) cette option est non supportée. Ainsi la seule solution trouvée, afin de conserver un comportement conforme à vos attentes, a été d'installer une version 3.x issue de Debian SID. Pour ce faire, nous sommes aller voir packages de Debian, puis nous avons téléchargé la version 3.x de notre architecture et la plus proche de notre distribution Debian (ici version 3.0.2 issue de la Debian SID) pour l'installer finalement "à la main" :

$ sudo dpkg -i vsftpd_3.0.2-1_amd64.deb

Limites

Dès maintenant, tous vos comptes courriels deviennent également des comptes FTP. Cependant, cela revêt 3 grandes limites :

  • Les mots de passe passent en clair via FTP, alors qu'ils sont peut-être déjà sécurisés via vos solutions courriels... pensez donc à rajouter les fonctionnalités de cryptage à vsftpd ("FTPS", FTP over SSL)
  • Tous les comptes courriels ont leur équivalent FTP... on peut donc imaginer rajouter un boolean dans la table mailbox pour définir si un compte est actif pour l'accès FTP ou non (ajout d'une colonne pour se faire)
  • Lors de la création d'un nouveau compte courriel/FTP, le répertoire de stockage des emails est créé automatiquement mais pas le répertoire FTP... il faut donc soit l'automatiser de manière externe à vsftpd qui n'a pas cette fonctionnalité, soit le faire "à la main".

Automatiser la création des répertoires FTP des nouveaux comptes

La meilleure solution que nous avons vu pour le moment est de passer par une tâche "cron" (le plannificateur des tâches). Nous avons choisi une tâche exécutée en PHP car c'est déjà le langage utilisé par notre "backend" de gestion qui est sous Symfony. Voici donc la solution déployée sur nos serveurs :

pré-requis

Il faut déjà installer php5-cli sur le serveur :

$ sudo apt-get intall php5-cli

/etc/cron.hourly/create-ftp-dirs.php

Voici donc le script utilisé, placé dans un répertoire contenant les scripts à lancer toutes les heures :

$ sudo vi /etc/cron.d/create-ftp-dirs.php

#!/usr/bin/php
<?php
  define('HOST',);
  define('DB',);
  define('USER',);
  define('PASSWD',);
  define('FTPROOT',);
  
  $conn = pg_connect('host='.HOST.' dbname='.DB.' user='.USER.' password='.PASSWD);
  $q = pg_query("SELECT username FROM mailbox");
  while ( $row = pg_fetch_row($q) )
  if ( !file_exists(FTPROOT.'/'.$row[0]) )
  {
    mkdir(FTPROOT.'/'.$row[0]);
    chown(FTPROOT.'/'.$row[0],'ftpsecure');
    chgrp(FTPROOT.'/'.$row[0],'ftpsecure');
  }
  pg_free_result($q);
?>

Sécurisons les informations

Les identifiants pour se connecter à la base de données sont accessibles depuis ce script, veillez donc à ce que seul l'utilisateur root puisse y accéder :

$ sudo chown root:root /etc/cron.hourly
$ sudo chmod 700 /etc/cron.hourly

Conclusion

Créez un nouveau compte email, vérifiez qu'il peut bien recevoir des courriels. Vérifiez également, après avoir attendu une heure que le dossier soit créé, qu'il accède bien au service FTP... CQFD !