6. Configuration du serveur NFS

Le rôle du serveur NFS est de mettre à disposition sur le réseau une partie de son arborescence locale de système de fichiers. On parle d'«exportation».

[Note] Note

Il existe plusieurs implémentations libres de serveur NFS. On se limite ici à l'utilisation du logiciel lié au noyau Linux.

Q21.

Quel est le paquet qui contient les outils nécessaires au fonctionnement du serveur NFS ? Installez ce paquet.

Interroger les méta données du gestionnaire de paquets pour identifier le nom du paquet à installer.

La recherche des mots clés nfs et server donne les résultats suivants.

$ aptitude search '?and(nfs, server)'
p   nfs-kernel-server      - support for NFS kernel server
v   nfs-server

Les informations données par la commande $ aptitude show nfs-kernel-server permettent de confirmer qu'il s'agit bien du paquet à installer.

$ sudo apt install nfs-kernel-server

Q22.

Quel est le fichier de configuration principal de gestion des exportations NFS ?

Rechercher dans le support Linux NFS-HOWTO.

Quelles que soient les versions du protocole, c'est toujours le fichier /etc/exports qui est utilisé. Ce fichier est présenté dans le support Linux NFS-HOWTO. Le fichier livré avec le paquet contient, en commentaires, deux exemples complets de configuration NFSv3 et NFSv4. C'est ce dernier exemple que l'on adapte pour traiter les questions suivantes.

Q23.

Créer le répertoire /home/exports/home. Quelles sont les instructions d'exportation à ajouter au fichier de configuration pour ce répertoire ?

Rechercher dans les supports Linux NFS-HOWTO et Nfsv4 configuration. On peut aussi utiliser les pages de manuels fournies avec le paquet du serveur NFS.

En exploitant la documentation Nfsv4 configuration et l'exemple donné dans le fichier de configuration, on applique les instructions de configuration suivantes dans le fichier /etc/exports.

$ sudo mkdir -p /home/exports/home
$ cat << EOF | sudo tee -a /etc/exports
/home/exports           192.168.51.192/27(rw,sync,fsid=0,crossmnt,no_subtree_check)
/home/exports/home      192.168.51.192/27(rw,sync,no_subtree_check)
EOF

$ cat << EOF | sudo tee -a /etc/exports
/home/exports           2001:678:3fc:1f5::/64(rw,sync,fsid=0,crossmnt,no_subtree_check)
/home/exports/home      2001:678:3fc:1f5::/64(rw,sync,no_subtree_check)
EOF

Bien sûr, les adresses des réseaux IPv4 et/ou IPv6 doivent être adaptées au contexte.

Les options entre parenthèses sont documentées dans les pages de manuels exports : $ man 5 exports. Les éléments de la liste suivante sont extraits de cette documentation.

  • rw : autoriser les requêtes en lecture et en écriture sur le volume NFS. Le comportement par défaut est d'interdire toute requête qui modifierait le système de fichiers.

  • sync : ne répondre aux requêtes qu'après l'exécution de tous les changements sur le support réel.

  • fsid=0 : avec NFSv4, un système de fichiers particulier est la racine de tous les systèmes de fichiers partagés. Il est défini par fsid=root ou fsid=0, qui veulent tous deux dire exactement la même chose.

  • crossmnt : cette option permet aux clients de se déplacer du système de fichiers marqué crossmnt aux systèmes de fichiers partagés montés dessus. Voir l'option nohide.

  • no_subtree_check : cette option neutralise la vérification de sous-répertoires, ce qui a des subtiles implications au niveau de la sécurité, mais peut améliorer la fiabilité dans certains cas. Si un sous-répertoire dans un système de fichiers est partagé, mais que le système de fichiers ne l'est pas, alors chaque fois qu'une requête NFS arrive, le serveur doit non seulement vérifier que le fichier accédé est dans le système de fichiers approprié (ce qui est facile), mais aussi qu'il est dans l'arborescence partagée (ce qui est plus compliqué). Cette vérification s'appelle subtree_check.

Q24.

Comment rendre la configuration d'exportation NFS effective ? Comment vérifier que les paramètres actifs sont corrects ?

Rechercher dans la liste des outils fournis avec le paquet nfs-kernel-server la commande qui permet de connaître l'état courant des exportations NFS.

On identifie la commande exportfs dans la liste des binaires fournis avec le paquet serveur NFS.

$ dpkg -L nfs-kernel-server | grep bin
/sbin
/sbin/nfsdcltrack
/usr/sbin
/usr/sbin/exportfs
/usr/sbin/rpc.mountd
/usr/sbin/rpc.nfsd

Après chaque modification d'un fichier de configuration, il ne faut surtout pas oublier de relancer le service correspondant.

$ sudo systemctl restart nfs-kernel-server
$systemctl status nfs-kernel-server
● nfs-server.service - NFS server and services
     Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled; vendor preset: enabled)
     Active: active (exited) since Sun 2021-08-29 15:47:25 CEST; 10s ago
    Process: 7699 ExecStartPre=/usr/sbin/exportfs -r (code=exited, status=0/SUCCESS)
    Process: 7700 ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS (code=exited, status=0/SUCCESS)
   Main PID: 7700 (code=exited, status=0/SUCCESS)
        CPU: 8ms

août 29 15:47:24 server-nfs systemd[1]: Starting NFS server and services...
août 29 15:47:25 server-nfs systemd[1]: Finished NFS server and services.

Enfin, on consulte la liste des entrées exportées via NFS.

$ sudo exportfs
/home/exports   192.168.51.192/27
/home/exports   2001:678:3fc:1f5::/64
/home/exports/home
                192.168.51.192/27
/home/exports/home
                2001:678:3fc:1f5::/64

Cette dernière liste est identique à celle produite par la commande showmount côté client NFS.

Q25.

Qu'est-ce qui distingue l'exportation d'une arborescence entre les versions 3 et 4 du protocole NFS ?

Rechercher dans les différences relatives à la notion de nommage dans les manipulations proposées dans les supports Linux NFS-HOWTO et Nfsv4 configuration.

Donner la signification du paramètre fsid=0 dans la documentation relative à la version 4. Proposer une analogie avec le fonctionnement d'un serveur Web.

Au delà des évolutions du protocole, c'est la cohérence du système de nommage qui distingue la version 4 du système de fichiers réseau. Il s'agit de garantir qu'un objet (fichier ou répertoire) soit représenté de la même manière sur un serveur et sur ses clients.

Dans le contexte de ces travaux pratiques les répertoires utilisateurs doivent être référencés à partir d'une racine nommée /ahome/.

Du point de vue infrastructure, l'utilisation de cette référence de nommage unique présente un avantage non négligeable. En effet, les répertoires d'exportation tels qu'ils ont été définis dans le fichier /etc/exports donné ci-dessus désignent un espace de stockage physique.

La racine /ahome/ désigne un espace de stockage logique. Ce schéma de nommage logique doit rester constant alors que les volumes de stockages physique peuvent migrer et se déplacer, être étendus, etc.

Les différences entre les manipulations proposées dans les supports Linux NFS-HOWTO et Nfsv4 configuration traduisent les différences de conception entre les deux générations du protocole NFS. On peut relever deux paramètres importants sur le serveur.

  • L'option fsid=0, présente dans le fichier /etc/exports/, permet de définir une racine de montage tout comme on le verrait sur un serveur Web. Le paramètre de configuration DocumentRoot /var/www du serveur apache2 désigne la racine à partir de laquelle les pages Web publiées sont référencées. Cette racine est indépendante de l'arborescence du système de fichier local du serveur.

  • L'utilisation d'un montage local avec l'option bind de la commande mount permet de mettre en cohérence l'arborescence du serveur et de ses clients. Ainsi, le répertoire /ahome/ présente les mêmes objets que l'on soit connecté sur le serveur ou sur un client. Le schéma de nommage est donc cohérent.

    Le montage local peut se faire manuellement sur le serveur avec la syntaxe suivante.

    $ sudo mkdir /ahome
    $ sudo mount --bind /home/exports/home /ahome

    Une fois la configuration validée, on peut intégrer ce montage local dans la configuration système pour que l'opération soit effectuée à chaque initialisation. Il faut alors éditer le fichier de configuration dédié aux montages des volumes locaux du système : /etc/fstab.

    Voici comment ajouter l'instruction de montage au fichier /etc/fstab du serveur NFS.

    $ echo "/home/exports/home     /ahome  none    defaults,bind    0    0" | \
    sudo tee -a /etc/fstab
    
    $ grep -v ^# /etc/fstab
    UUID=8362b3e6-d426-4f1b-93eb-e1efc22f60f4 /       ext4    errors=remount-ro 0    1
    UUID=f3e18b95-7430-4fea-ace5-7dd4cea6398a none    swap    sw    0       0
    /home/exports/home     /ahome  none    defaults,bind     0       0

Q26.

Comment créer un compte utilisateur local baptisé etu-nfs avec un répertoire utilisateur situé sous la racine /ahome ?

Après consultation des pages de manuels de la commande adduser, on dispose des options de création de compte respectant le critère énoncé. L'option --home permet de désigner le répertoire utilisateur dans l'arborescence système.

$ sudo adduser --home /ahome/etu-nfs etu-nfs
$ id etu-nfs
uid=1001(etu-nfs) gid=1001(etu-nfs) groupes=1001(etu-nfs)

Les identifiants numériques uid/gid jouent un rôle important dans la suite des manipulations. Voir Section 7, « Gestion des droits sur le système de fichiers NFS ».

Q27.

Créer un fichier texte ayant pour propriétaire l'utilisateur etu-nfs côté serveur et visualiser son contenu côté client.

Réaliser une capture et relever les numéros de ports caractéristiques de des transactions de montage. Est-il possible de retrouver le contenu du fichier texte dans les données de capture ?

Pour réaliser cette capture, il faut synchroniser les opérations entre les systèmes client et serveur. On commence par le lancement du l'analyseur réseau puis on visualise le contenu du fichier.

Côté serveur NFS, on créé le fichier texte puis on lance la capture réseau.

etu@server-nfs:~$ su - etu-nfs
Mot de passe :
etu-nfs@server-nfs:~$ echo "This file is mine" > textfile
etu-nfs@server-nfs:~$ exit
déconnexion
etu@server-nfs:~$ tshark -i enp0s6 -f "! port 22"
Capturing on 'enp0s6'
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 NFS 254 V4 Call GETATTR FH: 0x455db001
2001:678:3fc:1f5:baad:caff:fefe:3 → 2001:678:3fc:1f5:baad:caff:fefe:2 NFS 330 V4 Reply (Call In 3) GETATTR
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 TCP 86 883 → 2049 [ACK] Seq=169 Ack=245
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 NFS 262 V4 Call ACCESS FH: 0x455db001, [Check: RD LU MD XT DL XAR XAW XAL]
2001:678:3fc:1f5:baad:caff:fefe:3 → 2001:678:3fc:1f5:baad:caff:fefe:2 NFS 258 V4 Reply (Call In 6) ACCESS, [Allowed: RD LU MD XT DL XAR XAW XAL]
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 TCP 86 883 → 2049 [ACK] Seq=345 Ack=417
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 NFS 254 V4 Call GETATTR FH: 0x455db001
2001:678:3fc:1f5:baad:caff:fefe:3 → 2001:678:3fc:1f5:baad:caff:fefe:2 NFS 330 V4 Reply (Call In 9) GETATTR
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 TCP 86 883 → 2049 [ACK] Seq=513 Ack=661
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 NFS 278 V4 Call READDIR FH: 0x455db001
2001:678:3fc:1f5:baad:caff:fefe:3 → 2001:678:3fc:1f5:baad:caff:fefe:2 NFS 1174 V4 Reply (Call In 12) READDIR
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 TCP 86 883 → 2049 [ACK] Seq=705 Ack=1749
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 NFS 254 V4 Call GETATTR FH: 0x455db001
2001:678:3fc:1f5:baad:caff:fefe:3 → 2001:678:3fc:1f5:baad:caff:fefe:2 NFS 330 V4 Reply (Call In 15) GETATTR
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 TCP 86 883 → 2049 [ACK] Seq=873 Ack=1993
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 NFS 322 V4 Call OPEN DH: 0x6cceef4e/
2001:678:3fc:1f5:baad:caff:fefe:3 → 2001:678:3fc:1f5:baad:caff:fefe:2 NFS 442 V4 Reply (Call In 18) OPEN StateID: 0x5daa
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 TCP 86 883 → 2049 [ACK] Seq=1109 Ack=2349
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 NFS 270 V4 Call READ StateID: 0x7dca Offset: 0 Len: 18
2001:678:3fc:1f5:baad:caff:fefe:3 → 2001:678:3fc:1f5:baad:caff:fefe:2 NFS 214 V4 Reply (Call In 21) READ
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 TCP 86 883 → 2049 [ACK] Seq=1293 Ack=2477
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 NFS 262 V4 Call CLOSE StateID: 0x5daa
2001:678:3fc:1f5:baad:caff:fefe:3 → 2001:678:3fc:1f5:baad:caff:fefe:2 NFS 202 V4 Reply (Call In 24) CLOSE
2001:678:3fc:1f5:baad:caff:fefe:2 → 2001:678:3fc:1f5:baad:caff:fefe:3 TCP 86 883 → 2049 [ACK] Seq=1469 Ack=2593

Comme dans les opérations de capture réseau précédentes, il est préférable de stocker les résultats dans un fichier pour les exploiter ultérieurement avec une interface interactive qui permet d'isoler chaque champ de protocole.

Ici, on relève l'utilisation du protocole TCP en couche transport avec le port enregistré 2049/nfs. Une analyse détaillée de l'appel de procédure READ montre que le contenu du fichier texte est bien visible.