Installation de base

Jouons un peu avec ce serveur FTP. Ce sera l'occasion de voir plus en détails les commandes du protocole. Pour les besoins de cette manipulation, une machine virtuelle fera l'affaire. Lorsque nous aurons fait le tour du problème, nous pourrons placer notre serveur où ce sera le plus judicieux.

L'hôte virtuel a pour adresse IP 192.168.10.76 et fonctionne avec une Debian squeeze. Pour tout dire, il s'agit d'un DomU Xen, hébergé sur Une Debian squeeze « xénifiée ».

Ce réseau est accessible par le réseau 192.168.0.0/24 où se trouve le poste de travail (Ubuntu 10.10, en attendant de passer à Arch Linux).

Il n'y a pas ici de NAT, ni d'un côté ni de l'autre, il y a juste un tunnel OpenVpn entre les deux réseaux IP, si vous voulez tout savoir.

Voici la vraie installation : Topologie réelle Mais qui fonctionnellement peut se résumer ainsi : Topologie simplifiée Nous avons donc fonctionnellement deux réseaux IP 192.168.10.0/24 et 192.168.0.0/24 simplement routés entre eux. Le tunnel peut être omis, mais si nous voulons le détail d'un tcptraceroute :

Tracing the path to 192.168.10.76 on TCP port 21 (ftp), 30 hops max
 1  192.168.0.254  0.168 ms  0.143 ms  0.185 ms
 2  192.168.25.3  47.686 ms  46.795 ms  46.018 ms
 3  192.168.10.76 [open]  45.906 ms  47.400 ms  50.886 ms

Installation

C'est simple :

aptitude install pure-ftpd

Qui installe aussi pure-ftpd-common. Il y a d'autres versions de ce serveur :

# aptitude search pure-ftpd
p   mysqmail-pure-ftpd-logger      - real-time logging system in MySQL - Pure-FTPd traffic-logger                    
i   pure-ftpd                      - Secure and efficient FTP server                                                 
i A pure-ftpd-common               - Pure-FTPd FTP server (Common Files)                                             
p   pure-ftpd-ldap                 - Secure and efficient FTP server with LDAP user authentication                   
p   pure-ftpd-mysql                - Secure and efficient FTP server with MySQL user authentication                  
p   pure-ftpd-postgresql           - Secure and efficient FTP server with PostgreSQL user authentication       

Nous n'allons pas monter une usine à gaz et les identifications des utilisateurs fournies par le paquet pure-ftpd nous suffisent largement. Les logs dans un simple fichier texte suffiront également.

L'installation se termine par le démarrage du serveur en mode « standalone » avec la ligne de commande :

Starting ftp server: Running: /usr/sbin/pure-ftpd -l pam -8 UTF-8 -E -O clf:/var/log/pure-ftpd/transfer.log -u 1000 -B 

Quelques mots à propos de pure-ftpd

Ce serveur, dans sa version « vanilla » n'est pas prévu pour s'appuyer sur un fichier de configuration. Cette dernière se fait par une liste d'arguments, ce qui explique cette ligne de commande un peu incantatoire. Le mainteneur du paquet Debian a toutefois jugé nécessaire, pour rester dans l'harmonie Debian, de créer un « wrapper » qui lit un tas de fichiers situés dans /etc/pure-ftpd/ ainsi qu'un fichier /etc/default/pure-ftpd-common. Ce « wrapper » ne fait que construire la ligne de commande nécessaire au démarrage de pure-ftpd.

Comme nous n'utiliserons pas ce serveur de façon intensive, nous le ferons fonctionner plutôt à travers le super-serveur inetd. Pour cette raison, nous ne nous intéresserons pas plus que ça à la particularité Debian.

Analysons tout de même la ligne de commande construite par défaut lors de l'installation :

  • -l pam indique que l'authentification des utilisateurs se fait à travers PAM. Peut-être choisirons-nous quelque chose de plus simple ;
  • -8 UTF-8 n'est pas documentée mais elle semble vouloir indiquer que l'on souhaite utiliser UTF-8 ;
  • -E interdit les connexions anonymes ;
  • -O clf:/var/log/pure-ftpd/transfer.log permet d'indiquer où et avec quel format le serveur va consigner les transferts de fichiers effectués. Ici, dans un format similaire à celui d'Apache ;
  • -u 1000 interdit aux utilisateurs dont l'uid est inférieure à 1000 de se connecter au serveur, autrement dit, les comptes « système » ;
  • -B démarre le serveur en tâche de fond (sera inutile pour nous).

Pure-ftpd propose plusieurs méthodes d'identification des utilisateurs. PAM en est une, mais si nous souhaitons isoler les comptes FTP des comptes locaux, mieux vaut utiliser une logique d'utilisateurs virtuels. Sans aller jusqu'à une base SQL ou un annuaire LDAP, notre serveur propose une méthode « maison », gérée avec un outil pure-pw que nous utiliserons.

Apriori, nous ne souhaitons pas créer de zone publique (connexions anonymes).

Il pourra être nécessaire d'étudier quelques techniques pour préserver cette pauvre bande passante : Nombre limité de connexions simultanées, nombre limité d'utilisateurs simultanés, limitation du débit des transferts…

Nous savons que par défaut FTP laisse passer en clair les identifiants des utilisateurs. Peut-être faudra-t-il envisager de mettre en œuvre TLS.

Nous mettrons en place un filtrage de paquets (Netfilter) sur le serveur virtuel, il faudra l'adapter pour que FTP fonctionne correctement.

Mode opératoire

Dans un premier temps, nous allons désactiver le démarrage en mode « daemonized ». Pour les essais, nous ferons démarrer le serveur dans un shell et lorsque nous aurons arrêté une configuration convenable, nous configurerons inetd pour qu'il prenne en charge notre serveur FTP.

Recherche d'une configuration

L'authentification

Le support des utilisateurs virtuels se fait par un fichier de structure assez similaire au /etc/passwd. Il est maintenu par la commande pure-pw.

Comme ces utilisateurs sont virtuels, ils n'ont aucune existence sur le système. il est nécessaire de créer un compte système que le serveur pourra emprunter pour effectuer les opérations de lecture et d'écriture pour le compte de ces utilisateurs virtuels. Un seul compte utilisateur suffit, si l'on veut rester simple, chaque utilisateur virtuel disposant de son propre espace, dans lequel il est emprisonné (chroot).

Préparation du système

Commençons par arrêter le serveur « standalone » :

# /etc/init.d/pure-ftpd stop

Puis modifions /etc/default/pure-ftpd-common comme suit :

STANDALONE_OR_INETD=inetd

De cette manière, le script init ne cherchera plus à démarrer pure-ftpd comme un service.

Nous allons maintenant créer un groupe ftpgroup :

# groupadd ftpgroup

Nous créons un utilisateur ftpuser qui appartient à ce groupe, qui n'a pas de répertoire par défaut, qui n'a pas de shell et qui n'a pas non plus de mot de passe :

# useradd -g ftpgroup -d /dev/null -s /bin/false ftpuser

Nous créons un répertoire qui contiendra les répertoires des utilisateurs virtuels :

# mkdir /home/ftpusers

Création d'un compte virtuel

Avec la commande pure-pw créons un compte test :

# pure-pw useradd test -u ftpuser -d /home/ftpusers/test

Cette commande nécessitera d'entrer un mot de passe pour notre utilisateur test. Nous pouvons vérifier :

# pure-pw show test

Login              : test
Password           : $1$GrGl3h50$VHP8e646FLXfk7qUUnA7G1
UID                : 1001 (ftpuser)
GID                : 1001 (ftpgroup)
Directory          : /home/ftpusers/test/./
Full name          : 
Download bandwidth : 0 Kb (unlimited)
Upload   bandwidth : 0 Kb (unlimited)
Max files          : 0 (unlimited)
Max size           : 0 Mb (unlimited)
Ratio              : 0:0 (unlimited:unlimited)
Allowed local  IPs : 
Denied  local  IPs : 
Allowed client IPs : 
Denied  client IPs : 
Time restrictions  : 0000-0000 (unlimited)
Max sim sessions   : 0 (unlimited)
Tout ceci laisse entendre qu'il est possible de configurer finement chaque compte virtuel. Il sera intéressant de lire le manuel de pure-pw… Le mot de passe est chiffré, mieux vaut donc ne pas l'oublier, ou alors il faudra en générer un nouveau (pure-pw permet de le faire); cet utilisateur empruntera bien le compte système ftpuser pour ses opérations de lecture/écriture, son répertoire de base sera bien /home/ftpusers/, le ./ qui suit signifie qu'il sera prisonnier de son répertoire, ce que nous ne manquerons pas de vérifier.

Ce n'est pas tout. Pure-pw a créé (par défaut) un fichier /etc/pure-ftpd/pureftpd.passwd, mais pure-ftpd n'utilisara pas directement ce fichier pour l'authentification. Pour des raisons de rapidité, il faut créer un fichier formaté spécialement, toujours avec la commande pure-pw :

# pure-pw mkdb

qui crée, toujours par défaut, un fichier /etc/pure-ftpd/pureftpd.pdb.

Premier test

Nous démarrons le serveur avec les options suivantes :

# pure-ftpd -j -l puredb:/etc/pure-ftpd/pureftpd.pdb
  • -j fera que le répertoire de l'utilisateur sera automatiquement créé s'il n'existe pas déjà ;
  • -l indique le mode d'authentification (puredb) et le fichier à consulter.

Nous pouvons dans une autre console, observer deux choses :

# ps aux | grep pure
root     23658  0.0  0.3  24888  1668 pts/0    S+   18:44   0:00 pure-ftpd (SERVER) 

et :

# netstat -laputen | grep pure
tcp     0    0 0.0.0.0:21    0.0.0.0:*       LISTEN      0          71232       23658/pure-ftpd (SE
tcp6    0    0 :::21         :::*            LISTEN      0          71234       23658/pure-ftpd (SE

Nous avons un serveur qui tourne (c'est tant mieux), sous l'identité root (oups ?) et qu'il écoute sur toutes les interfaces, aussi bien en IPv4 qu'en IPv6.

Avec notre FileZilla nous nous connections au serveur 192.168.10.76 avec comme identifiant test et son mot de passe et nous voyons dans le liste du haut :

Statut :	Connexion à 192.168.10.76:21...
Statut :	Connexion établie, attente du message d'accueil...
Réponse :	220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
Réponse :	220-You are user number 1 of 50 allowed.
Réponse :	220-Local time is now 18:30. Server port: 21.
Réponse :	220-IPv6 connections are also welcome on this server.
Réponse :	220 You will be disconnected after 15 minutes of inactivity.
Commande :	USER test
Réponse :	331 User test OK. Password required
Commande :	PASS ********
Réponse :	230-User test has group access to:  ftpgroup  
Réponse :	230 OK. Current directory is /
Commande :	OPTS UTF8 ON
Réponse :	200 OK, UTF-8 enabled
Statut :	Connecté
Statut :	Récupération du contenu du dossier...
Commande :	PWD
Réponse :	257 "/" is your current location
Statut :	Succès de la lecture du contenu du dossier
Tout s'est bien passé. Sur le serveur, le dossier a été créé (par ftpuser) :

# ls -l /home/ftpusers/
total 4
drwxr-xr-x 2 ftpuser ftpgroup 4096  1 janv. 18:30 test

Si nous essayons de remonter dans l'arborescence (..), nous avons :

Statut :	Récupération du contenu du dossier...
Commande :	CDUP
Réponse :	250 OK. Current directory is /
Commande :	PWD
Réponse :	257 "/" is your current location
Statut :	Succès de la lecture du contenu du dossier
CDUP (Change Directory UP) pour aller vers le répertoire parent a bien été exécutée, mais test est resté prisonnier de son répertoire.

Tant que notre client est connecté, revoyons un peu :

# ps aux | grep pure
root     23658  0.0  0.3  24888  1672 pts/0    S+   18:44   0:00 pure-ftpd (SERVER)                                
ftpuser  23666  0.0  0.2  37540  1480 pts/0    S+   18:49   0:00 pure-ftpd (IDLE)                                  
root     23667  0.0  0.1  37512  1000 pts/0    S+   18:49   0:00 pure-ftpd (PRIV)

et :

# netstat -laputen | grep pure
tcp     0   0 0.0.0.0:21           0.0.0.0:*               LISTEN      0    71232     23658/pure-ftpd (SE
tcp     0   0 192.168.10.76:21     192.168.0.16:34924      ESTABLISHED 0    71309     23666/pure-ftpd (ID
tcp6    0   0 :::21                :::*                    LISTEN      0    71234     23658/pure-ftpd (SE

Nous avons un nouveau service qui tourne sous l'identité ftpuser, en mode IDLE parce que nous ne faisons rien de particulier en ce moment et un troisième service (PRIV).

Le service IDLE a bien établi une connexion en IPv4 entre le client (192.168.0.16:34924) et le serveur (192.168.10.76:21). Autrement dit, les échanges entre client et serveur vont se faire sous l'identité ftpuser (ouf !).

Tout ceci est plutôt encourageant.