Cet 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
- Configuration du pare-feu
- Configuration de SELinux
- Installation
- Création d’un utilisateur
- Configuration du serveur
- Mise en service et premier test
- Sécuriser la connexion
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.
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.