Table des matières

Ressources:

1. Présentation

NFS est un protocole de partage de fichiers principalement dédié à Unix, et qui existe depuis les années 80. Bien qu'il existe d'autres solutions (AFS, CIFS), sa simplicité et son efficacité l'ont rendu très populaire. Il a été inventé et largement porté par Sun depuis le début.

Version Date Standards Fonctionnalités
v2 1989 RFC1094 UDP (stateless)
v3 1995 RFC1813 UDP, 64bits, cache (stateless)
v4 2000 RFC3010, RFC3530 UDP+TCP, ACL, auth+autz+sec, RPC-less (stateful)

Stateless vs. Stateful

Le principe d'un protocole sans état est de pouvoir contenir une information complète dans chaque “paquet” (ici un ordre, comme lire ou écrire), sans reposer sur des informations envoyées dans des paquets précédents. Ceci permet une implémentation simple et robuste, mais limite les possibilités et peut affecter les performances (l'état est redondant dans chaque ordre).

Cependant, l'idée des concepteurs originaux de NFS est de pouvoir rajouter des fonctionnalités “stateful”, mais en dehors du service d'échange de fichiers principal. C'est par exemple le cas du démon lockd, responsable du verouillage des fichiers (accès exclusif), qui maintient nécessairement une information qui couvre plusieurs requêtes concernant le même fichier.

Aujourd'hui l'expérience concernant les protocoles stateful est bien plus avancé, et les avantages peuvent outrepasser ceux d'un protocol stateless: notamment lorsque les services annexes stateful en v2/v3 se multiplient, et que leurs interactions sont complexes. En particulier, l'implémentation basée sur RPC requiert de nombreux ports ouverts (imprévisibles) et sont particulièrement difficiles à firewaller.

UDP vs. TCP

UDP est précisemment un protocole stateless, qui s'adapte bien aux protocoles NFS v2/v3. Par contre il ne possède pas de mécanisme d'équilibrage de la bande passante et de gestion de la congestion comme TCP, et bien entendu pas de facilité de détection d'erreur et de retransmission. UDP est donc utilisable sur un réseau local, en général dédié, où l'on sait que les conditions de congestion et de panne sont quasi nulles.

Pour une utilisation plus large (WAN, VPN), TCP devient alors incontournable. En pratique, des implémentation des protocoles v2 et v3 en TCP ont été réalisées par la plupart des vendeurs Unix (même si elles ne font pas partie des standards). Aujourd'hui, TCP étant parfaitement géré et sans surcharge sur des équipements de commutation et de routage, c'est la solution préférée.

64 bits

NFS v2 utilise des tailles de fichier représentées sur 32 bits signés, donc jusqu'à 2^31^-1 octets (2Go). A partir de NFS v3, et si le reste de l'infrastructure de l'OS le supporte, cette information est sur 64 bits, donc virtuellement illimitée (pour 10 ans…).

NFS v4

NFS v4 a introduit de nombreux changements (inspiré par AFS et CIFS) et utilise une infrastructure nettement différente.

Il utilise notamment l'infrastructure d'authentification, d'autorisation et de cryptage GSSSAPI (ex: Kerberos), en lieu et place du test machine/IP originel. Il est donc nativement équipé pour être utilisé directement sur Internet, sans précautions supplémentaires (VPN, firewalls, etc).

Enfin il ne repose plus sur portmapper (le démon RPC) et utilise une seule session TCP sur un port prédéterminé (2049), simplifiant grandement son filtrage et sa gestion.

2. NFS v3 côté serveur

NFS v3 est implémenté complètement dans Linux 2.4 et Linux 2.6. Attention, certaines modifications importantes concernant NFS ont été réalisés pendant le développement de ces deux séries, consulter la FAQ.

Kernel vs. User

Il existe deux implémentations de référence: l'une en grande partie implementée dans le noyau, l'autre entièrement réalisée en tant qu'application utilisateur (Debian: paquets nfs-kernel-server et nfs-user-server).

Il est évident que pour des raisons de performance, on préférera si possible l'implémentation kernel: elle implique moins de changements de contexte, et pas ou peu de copies de données kernel/user. Les inconvénients:

Heureusement NFS v3 est un composant logiciel relativement simple, et aujourd'hui mature dans les séries 2.4 et 2.6. On peut préférer son implémentation user-space quand :

Note : le support client nécessite toujours un support spécifique côté noyau.

Démons

NFS v2/v3 requiert un écosystème de services pour fonctionner correctement côté serveur:

Nom Port(s) Description
portmap 111 tcp+udp RPC server (annuaire de services)
[nfsd]] 2049 tcp+udp NFS server (opération standard sur les fichiers)
[rpciod] - NFS I/O kernel thread
[lockd] ou rpc.lockd dynamique Locking (accès exclusif aux fichiers) - optionnel
rpc.mountd dynamique Mount/umount (filehandle initial)
rpc.statd dynamique Aide pour lockd en cas de reboot - optionnel
rpc.quotad dynamique Gestion des quotas - optionnel

Configuration

Portmap utilise tcpwrappers pour gérer un système d'autorisation/rejet simple par IP ou sous-réseau, à l'aide des fichiers /etc/hosts.allow et /etc/hosts.deny. Cela peut être rapidement fastidieux, par exemple:

Exemple de /etc/hosts.allow (autorise RPC sur un sous-réseau privé)

portmap : 127. 192.168.1. : ALLOW
lockd : 127. 192.168.1. : ALLOW
rquotad : 127. 192.168.1. : ALLOW
mountd : 127. 192.168.1. : ALLOW
statd : 127. 192.168.1. : ALLOW

Note : l'utilisation de tcpwrappers est optionnelle, un fichier de configuration vide équivaut à un plein accès.

Le démon NFS est entièrement contrôlé par le fichier /etc/exports, qui a une syntaxe très simple: un partage de fichiers par ligne :

Exemple de /etc/exports :

/home 192.168.1.0/24(rw,sync)
/var/log *.insia.org(ro) trusted.com(rw,all_squash)
/pub (ro)

Attention: ce fichier est très sensible aux espaces (ne jamais en mettre entre une IP et la première parenthèse!).

Il est tout à fait possible de contrôler le démon indépendemment de ce fichier de configuration, mais la pratique standard consiste à effectuer les modifications dans le fichier, puis demander au démon de relire cette configuration ainsi :

# exportfs -r

Une mise à jour a pour effet :

Détails de la configuration

Un partage NFS peut accepter différentes options, chacune mérite une attention particulière. Il n'existe pas de réglage absolu et optimal, mais uniquement des compromis adaptés à des situations particulières. Le détail est dans man exports.

Sécurité

Le serveur fait confiance au client et interprète les attributs UID et GID des opérations et des fichiers comme tel: pour NFS, ce sont des informations comme les autres. Le serveur utilise la sémantique du système de fichier local pour savoir ce qu'il est autorisé à faire, donc on se retrouve dans un schéma de droits et d'accès Unix traditionnel.

Hormis les options simples (et simplistes) no_root_squash, all_squash et anonuid/anongid, la correspondance entre les identifiants (UID/GID) des différentes machines (clients et serveur) est l'identité. On utilise souvent un annuaire type LDAP ou NIS pour unifier cette information sur un parc de machines.

Diagnostics

Côté serveur, on observe peu de choses. Le protocole étant sans état, si l'on utilise pas RPC on ne peut même pas détecter les sessions TCP (par ex: netstat -tnp|grep :2049). Il existe un outil pour obtenir des statistiques globales, nfsstat et la possibilité de lister le détail des services RPC disponibles sur la machine avec rpcinfo -p.

3. NFS v3 côté client

L'utilisation est un peu plus simple, mais il faut toujours à peu près le même écosystème: si le serveur principal (nfsd et rpc.moutnd) n'est bien sûr pas requis, les services secondaires (rpc.statd., rpc.lockd et donc portmap) sont requis.

Utiliser un partage NFS se fait comme un montage Unix standard. Il est recommandé d'utiliser le fichier standard /etc/fstab à cet effet :

Exemple (extraite) de /etc/fstab

device mountpoint fs-type options dump fsckorder
192.168.1.1:/home /mnt/home nfs rw,sync,hard,intr 0 0

Puis :

# mnt /mnt/home

Note: l'erreur précise en cas d'échec de montage se trouve côté serveur dans ses logs.

Détails de la configuration

Ces informations sont documentées dans man nfs.

Gestion de panne

Quand le serveur n'est plus joignable, le comportement par défaut consiste à attendre indéfiniment son retour (hard,nointr). Dès que le serveur est à nouveau visible, le traffic reprend normalement dans la seconde, les clients étant “gelés” au moment de la panne.

Un client NFS v3 utilisant une stratégie de cache évoluée et concertée avec le serveur, se sert également d'informations fournies par le serveur s'il a rebooté pour savoir ce qu'il doit faire de ses caches (les invalider ou les envoyer). Ceci est vrai seulement en mode synchrone.

Si le serveur est injoignable , et ce de manière indéfinie, il ne peut être remplacé par un autre serveur que sous certaines conditions (cf. fsid). Sinon en général on chercher à débloquer les processus: