FTPCet article décrit la mise en place d’un serveur FTP avec VsFTPd (Very Secure FTP Daemon) sur un serveur dédié tournant sous CentOS 7. FTP a été pendant longtemps la manière la plus simple pour échanger des fichiers sur Internet. Même si le protocole reste encore extrêmement populaire – notamment dans le cadre des hébergements web mutualisés – on peut considérer qu’il est obsolète, au vu des considérations de sécurité comme les mots de passe qui transitent en clair. Nous allons pallier à ce manque en ajoutant le chiffrement avec Let’s Encrypt.

FTP actif et FTP passif

Avant de mettre les mains à la pâte, une petite explication sur les deux modes de transfert de fichiers FTP.

Le mode FTP actif, c’est le mode par défaut des clients FTP. Dans un premier temps, une session TCP est initiée sur le port 21 du serveur. Une fois la session établie et l’authentification FTP acceptée, le serveur établit une session TCP depuis le port 20 vers un port dynamique du client.

Le mode FTP passif est conseillé à partir du moment où les clients peuvent se trouver derrière un pare-feu. Dans ce mode, toutes les initialisations de sessions TCP se font à partir du client. Là aussi, le client établit une première session TCP sur le port 21. La session est établie, l’authentification est acceptée, et à partir de là, on demande au serveur de se mettre en attente de session TCP grâce à la commande PASV. Le client peut alors établir une seconde session TCP sur un port dynamique vers le serveur.

Le numéro de port dynamique est transmis du serveur vers le client suite à la commande PASV. On peut réduire la plage de ports en configurant le serveur FTP de manière appropriée, et c’est ce que nous allons faire ici.

Configuration du pare-feu

Le pare-feu nécessite une configuration un peu particulière avec le protocole FTP. Pour permettre l’accès au serveur, nous devons faire trois choses.

  • charger le module nf_conntrack_ftp
  • ouvrir le port 21 en TCP
  • ouvrir les ports 50001 à 50010 en TCP pour le mode passif

Voici à quoi cela ressemble concrètement avec le pare-feu FirewallD.

$ sudo firewall-cmd --permanent --add-service=ftp
$ sudo firewall-cmd --permanent --add-port=50001-50010/tcp
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: dns ftp http https ssh
  ports: 50001-50010/tcp
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
  • Le chargement du module nf_conntrack_ftp est déjà prédéfini dans le fichier /usr/lib/firewalld/services/ftp.xml.

Configuration de SELinux

Si l’on utilise SELinux en mode renforcé sur le serveur, il suffit de modifier la valeur par défaut du booléen ftpd_full_access comme ceci.

$ sudo setsebool -P ftpd_full_access 1

À partir de là, SELinux ne nous posera aucun problème.

Installation

Le serveur VsFTPd est fourni par les dépôts officiels de Red Hat et de CentOS.

$ sudo yum install vsftpd

Création d’un utilisateur

Je vais créer un utilisateur bahiajon sur le serveur. Il n’est pas censé se connecter directement au système. Ses données seront stockées en-dessous de /srv/ftp/bahiajon, le répertoire utilisateur correspondant que je dois créer au préalable.

$ sudo mkdir -pv -m 0770 /srv/ftp/bahiajon
mkdir: created directory ‘/srv/ftp’
mkdir: created directory ‘/srv/ftp/bahiajon’
$ sudo useradd -c "Bahia Jon" -d /srv/ftp/bahiajon/ -s /sbin/nologin bahiajon
useradd: warning: the home directory already exists.
Not copying any file from skel directory into it.
$ sudo chown bahiajon:bahiajon /srv/ftp/bahiajon/
$ sudo passwd bahiajon
Changing password for user bahiajon.
New password: **********
Retype new password: **********
passwd: all authentication tokens updated successfully.

Configuration du serveur

La configuration de VsFTPd s’effectue dans le fichier /etc/vsftpd/vsftpd.conf. Avant d’aller plus loin, nous allons sauvegarder la configuration par défaut.

$ cd /etc/vsftpd/
$ sudo cp vsftpd.conf vsftpd.conf.orig

À partir de là, nous allons modifier ou ajouter quelques directives. Pour commencer, on va désactiver les connexions anonymes.

anonymous_enable=NO

Ensuite, on va descendre vers la fin du fichier et définir la configuration de notre utilisateur.

chroot_local_user=YES
userlist_enable=YES
userlist_deny=NO
check_shell=NO
userlist_file=/etc/vsftpd/vsftpd.user_list
allow_writeable_chroot=YES

Cette dernière stance mérite quelques explications.

  • La directive chroot_local_user=YES interdit aux utilisateurs de quitter l’arborescence de leur répertoire utilisateur pour se balader un peu partout dans le système.
  • La directive userlist_enable=YES active une liste d’utilisateurs.
  • Dans la configuration par défaut, la liste spécifie les utilisateurs auxquels on interdit l’accès au serveur. Nous allons faire le contraire avec userlist_deny=NO et créer une liste qui contiendra un seul utilisateur autorisé.
  • La directive check_shell=NO est nécessaire lorsqu’un utilisateur doit pouvoir se connecter alors même qu’il ne dispose d’aucun shell de connexion.
  • Le fichier spécifié par la directive userlist_file contiendra la liste avec les utilisateurs autorisés à se connecter.

Les listings récursifs sont autorisés.

ls_recurse_enable=YES

Notre serveur utilise uniquement l’IPv4, ce que nous allons préciser ici.

listen=YES
listen_ipv6=NO

Ici, on peut activer le mode FTP passif et définir la plage de ports dynamiques.

pasv_enable=YES
pasv_min_port=50001
pasv_max_port=50010

Étant donné qu’un utilise le mode FTP passif, on peut commenter ou supprimer la ligne suivante.

# connect_from_port_20=YES

Un peu plus bas, on pourra supprimer le doublon userlist_enable=YES et désactiver l’utilisation des encapsuleurs TCP.

tcp_wrappers=NO

Au total, notre fichier /etc/vsftpd/vsftpd.conf ressemble à ceci.

# /etc/vsftpd/vsftpd.conf
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
xferlog_std_format=YES
chroot_local_user=YES
userlist_enable=YES
userlist_deny=NO
check_shell=NO
userlist_file=/etc/vsftpd/vsftpd.user_list
allow_writeable_chroot=YES
ls_recurse_enable=YES
listen=YES
listen_ipv6=NO
pasv_enable=YES
pasv_min_port=50001
pasv_max_port=50010
pam_service_name=vsftpd
tcp_wrappers=NO

Puisque notre utilisateur bahiajon ne dispose pas de shell de connexion, il faut impérativement commenter la ligne correspondante dans /etc/pam.d/vsftpd.

# auth required pam_shells.so

Il ne reste plus qu’à créer le fichier /etc/vsftpd/vsftpd.user_list censé contenir la liste des utilisateurs autorisés à se connecter à VsFTPd.

$ echo bahiajon | sudo tee /etc/vsftpd/vsftpd.user_list

Mise en service et premier test

Activer et démarrer le serveur VsFTPd.

$ sudo systemctl enable vsftpd --now

Pour tester le serveur localement, on pourra utiliser un client FTP comme lftp. Avant de le lancer, on va lui fournir un fichier test à se mettre sous la dent.

$ echo "Ceci est un test FTP" | sudo tee /srv/ftp/bahiajon/test
$ sudo chown bahiajon:bahiajon /srv/ftp/bahiajon/test

À présent, on peut initier une première connextion sur le serveur en tant qu’utilisateur bahiajon.

$ lftp -u bahiajon localhost
Password: **********
lftp bahiajon@localhost:~> ls     
-rw-r--r--    1 1001     1001           21 Mar 22 07:16 test
lftp bahiajon@localhost:/> cat test
Ceci est un test FTP
21 bytes transferred
lftp bahiajon@localhost:/> bye

Une fois que ce premier test depuis le serveur fonctionne, on pourra essayer de se connecter depuis une machine distante.

$ lftp -u bahiajon ftp.slackbox.fr

Sécuriser la connexion

Dans la configuration actuelle, les identifiants et autres mots de passe transitent « en clair » dans le réseau et peuvent donc facilement être interceptés. Nous allons donc prendre soin de chiffrer tout cela.

Dans un premier temps, je vais générer un certificat Let’s Encrypt si ce n’est pas déjà fait.

Puis j’ajoute une série de directives à mon fichier vsftpd.conf.

rsa_cert_file=/etc/letsencrypt/live/sd-100246.dedibox.fr/fullchain.pem
rsa_private_key_file=/etc/letsencrypt/live/sd-100246.dedibox.fr/privkey.pem
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
require_ssl_reuse=NO
ssl_ciphers=HIGH

Les options utilisées sont déjà suffisamment explicites en elles-mêmes. Pour en savoir un peu plus, consultez la page de manuel vsftpd.conf(5).

Prendre en compte les modifications en redémarrant le service.

$ sudo systemctl restart vsftpd

À partir de là, je peux accéder au serveur avec n’importe quel client FTP capable de gérer les connexions chiffrées, comme par exemple Filezilla ou lftp.

Curieusement, Filezilla ne reconnaît pas d’emblée le certificat, mais ce n’est pas bien grave.

Filezilla SSL

En revanche, le client lftp gère parfaitement les connexions chiffrées.

$ lftp -u bahiajon ftp.slackbox.fr
Mot de passe :
lftp bahiajon@ftp.slackbox.fr:~> ls
-rw-r--r-- 1 1001 1001 21 Mar 22 07:16 test
lftp bahiajon@ftp.slackbox.fr:/> cat test
Ceci est un test FTP
21 octets transférés
lftp bahiajon@ftp.slackbox.fr:/> bye

La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce blog ? Offrez un café au rédacteur en cliquant sur la tasse.