NFS Howto
De Wiki de la communauté Mandriva.
Présentation
Ce document décrit les bonnes pratiques concernant la configuration de Linux NFS en environnement de production. Il traite des configurations du serveur et des clients, ainsi que de la sécurité et des optimisations de la performance.
Introduction
Qu'est ce que NFS ?
Le système de fichiers réseau (NFS pour Network File System) fut développé pour permettre aux machines de monter la partition d'une machine distante comme si c'était un disque local. Il permet le partage rapide et transparent de fichiers via le réseau. Potentiellement, s'il est mal configuré, il permet aussi à des personnes indésirables d'accéder à votre disque via le réseau (et de là, la possibilité de lire vos e-mails et d'effacer tous vos fichiers ou bien de pénétrer votre système). Aussi veuillez lire soigneusement le chapitre 6 de ce document, "NFS et la sécurité" si vous souhaitez installer une configuration de NFS.
Il existe d'autres systèmes qui fournissent des fonctions similaires à NFS. Samba fournit un service de partage de fichiers avec des clients Windows. Le système de fichiers Andrew, à l'origine développé par IBM et maintenant open source, fournit un mécanisme de partage de fichiers avec des caractéristiques améliorées concernant la sécurité et les performances. Le système de fichiers Coda associe le partage de fichiers avec une attention particulière sur les clients déconnectés. Beaucoup des caractéristiques des systèmes de fichiers Andrew ou Coda sont décortiquées pour être incluses dans la prochaine version de NFS (Version 4). L'avantage de NFS aujourd'hui est qu'il est mature, universel, bien compris et solidement supporté sur de nombreuses plateformes.
La destination de ce document
Ce HOWTO a pour ambition d'être un guide complet, pas à pas, pour configurer NFS correctement et avec efficacité. Configurer NFS se fait en deux temps, à savoir configurer le serveur puis le client. Chacune de ces étapes est traitée par ordre. Enfin le document apporte quelques astuces pour ceux qui ont des besoins particuliers et le paramétrage du matériel, ainsi que des conseils concernant la sécurité et la résolution des problèmes. Ce HOWTO n'est pas une description ni des tripes ni des implémentations ou de l'architecture sous-jacentes de NFS. De la documentation recommandée traitant de ces propos peut être trouvée dans la FAQ NFS. Ce document n'est pas non plus conçu pour être un manuel de référence complet, et ne contient pas de liste exhaustive des caractéristiques de Linux NFS. Pour cela vous pouvez vous reporter aux pages man pour nfs(5), exports(5), mount(8), fstab(5), nfsd(8), lockd(8), statd(8),rquotad(8), and mountd(8). Il ne traite pas non plus de PC-NFS, qui est jugé obsolète (Les utilisateurs sont encouragés à utiliser Samba pour partager des fichiers avec des machines sous Windows) ou NFS Version 4 qui est toujours en développement.
Connaissances requises
Vous devez connaître les bases des réseaux TCP/IP avant de lire ce HOWTO, si vous avez un doute, lisez le Networking-Overview-HOWTO (en anglais)
Matériel requis, version du noyau et nfs-utils
Les différences entre NFS Version 2, NFS Version 3, et NFS Version 4 seront expliquées plus tard ; pour l'instant, vous devez simplement suivre la recommandation d'utiliser NFS Version 3 si vous installez un serveur de fichiers dédié, de grande capacité ou de production. NFS Version 2 ou 4 seront adaptés à une utilisation occasionnelle.
NFS version 2 existe depuis quelque temps maintenant (au moins depuis les noyaux 1.2), cependant vous devez disposer d'un noyau de version au moins égale à 2.2.18 si vous souhaitez :
- Faire cohabiter NFS de Linux avec NFS d'autres systèmes d'exploitation
- Utiliser de façon sûre le verrouillage des fichiers avec NFS
- Utiliser NFS Version 3
Les fonctionnalités de la version 3 exigent le paquetage nfs-utils de version au moins égale à 0.1.6 et le paquetage mount de version au moins égale à 2.10m. Cependant, puisque nfs-utils et mount ont une totale compatibilité ascendante, et puisque les nouvelles versions possèdent beaucoup d'améliorations, il n'existe aucune bonne raison de ne pas installer les derniers paquetages si vous commencez une configuration de NFS.
Tous les noyaux de version 2.4 et suivantes possèdent toutes les fonctionnalités de NFS version 3. Tous les noyaux de version 2.6 et suivantes possèdent toutes les fonctionnalités de NFS version 4. Cela sera présenté avec plus de détails plus tard. Dans tous les cas, si vous compilez votre propre noyau, vous devez sélectionner NFS dans les versions supportées. Aujourd'hui, presque toutes les distributions standard de Linux fournissent un noyau qui supporte NFS version 3. La manipulation de fichiers plus gros que 2 Go nécessite un noyau version 2.4x ou plus récent et glibc version 2.2x ou plus récent. Tous les noyaux après 2.2.18 supportent NFS sur TCP du côté client. Du côté serveur, NFS sur TCP n'existe que sous une forme boguée, en option expérimentale, après les versions 2.2.18. Des patches pour les noyaux 2.4 et 2.5 ont été introduits à partir de 2.4.17 et 2.5.6. L'utilisation de TCP pour NFS est maintenant banale et largement utilisée.
Parce que beaucoup des fonctionnalités ci-dessus furent introduites dans le noyau version 2.2.18, ce document fut écrit principalement pour les noyaux postérieurs à cette version (y compris les 2.6.x). Si vous possédez un noyau plus ancien, ce document peut ne pas décrire correctement votre système NFS. Alors que nous écrivons ce document, le support de NFS version 4 est en développement pour le noyau 2.6.x. Son implémentation n'est pas encore arrêtée et changeante, il n'est pas recommandé pour une utilisation en production. La configuration de NFS version 4 et des technologies intégrées associées sont abordées plus loin dans ce document.
Où obtenir de l'aide et des informations supplémentaires
Depuis novembre 2000, la page d'accueil de Linux NFS est http://nfs.sourceforge.net. Veuillez y rechercher les listes de diffusion relatives à NFS ainsi que la dernière version de nfs-utils, les patches de noyau pour NFS, et d'autres paquetages relatifs à NFS. Si vous rencontrez un problème ou avez une question non traitée dans ce manuel, la FAQ ou les pages man, vous pouvez envoyer un message à la liste de diffusion de NFS (nfs arobase lists point sourceforge point net). Pour aider les développeurs et les autres utilisateurs auxquels vous soumettez votre problème, vous devez inclure :
- La version utilisée de nfs-utils
- La version utilisée du noyau et tout noyau exotique utilisé
- La distribution de Linux utilisée
- la(es) version(s) des autres systèmes d'exploitation utilisés
Il est aussi utile de connaître la configuration du réseau reliant les hôtes. Si votre problème porte sur l'impossibilité des partages mount ou export, veuillez aussi inclure :
- une copie de votre fichier /etc/exports
- la sortie de rpcinfo -p localhost lancé sur le serveur
- la sortie de rpcinfo -p servername lancé sur le client
Envoyer toute cette information avec une question spécifique, après lecture de toute la documentation, est le meilleur moyen d'obtenir une aide efficace. Vous pouvez aussi regarder les pages man de nfs(5),exports(5), mount(8), fstab(5), nfsd(8), lockd(8), statd(8), rquotad(8), et mountd(8).
Configurer un serveur NFS
Introduction à la configuration du serveur
On suppose que vous allez configurer un serveur et un client. Si vous ne souhaitez configurer que le client pour fonctionner avec le serveur de quelqu'un d'autre (disons dans votre service), vous pouvez passer au chapitre 4 “Configurer un client NFS”. Cependant, tout client configuré nécessite des modifications sur le serveur afin que ce client soit accepté (a moins que le serveur ne soit configuré de manière très peu sécurisée), aussi, même si vous ne configurez pas le serveur, vous pouvez souhaiter lire ce chapitre pour avoir une idée des problèmes d'autorisation qu'il faut traiter. La configuration du serveur sera réalisée en deux étapes : Paramétrer les fichiers de configuration de NFS, puis démarrer les services NFS.
Paramétrer les fichiers de configuration
Il y a trois fichiers de configuration principaux que vous aurez besoin d'éditer pour configurer le serveur NFS : /etc/exports, /etc/hosts.allow, et /etc/hosts.deny. Strictement parlant, vous n'avez besoin que de les éditer pour que NFS fonctionne, mais vous auriez une configuration très peu sûre. Vous pouvez aussi avoir besoin d'éditer vos scripts de démarrage.
/etc/exports
Ce fichier contient une liste d'entrées ; chaque entrée indique un volume qui est partagé et comment il est partagé. Reportez vous aux pages man (man exports) pour une description complète de toutes les options de configuration de ce fichier, bien que la description ci-dessous conviendra à la plupart des besoins. Une entrée dans /etc/exports ressemble à cela :
répertoire machine1(option11,option12) machine2(option21,option22)
où
répertoire : le répertoire que vous désirez partager. Cela peut être un volume entier mais pas nécessairement. Si vous partagez un répertoire, alors tous ses sous répertoires, à l'intérieur du même système de fichiers, seront partagés.
machine1 et machine2 : machines clientes qui doivent avoir accès au répertoire. Elles peuvent être listées par leur adresse DNS ou leur adresse IP (ex : machine.company.com ou 192.168.0.8 ). Il est plus fiable et plus sûr d'utiliser l'adresse IP. Si vous devez utiliser l'adresse DNS et qu'elle ne semble pas résolue par le bon nom de machine, voir le chapitre 7 “Dépannage”
optionxx : la liste des options pour chaque machine décrit quel type d'accès possède cette machine. Les options importantes sont :
- ro : Le répertoire est partagé en lecture seule ; la machine cliente ne pourra pas y écrire. C'est la valeur par défaut.
- rw : la machine cliente pourra lire et écrire sur le répertoire
- no_root_squash : Par défaut, tout requête faite sur un fichier du serveur par l'utilisateur root depuis une machine cliente est traitée comme si elle était effectuée par l'utilisateur nobody. (L'UID à laquelle la requête est attribuée est l'UID de l'utilisateur “nobody” sur le serveur, pas sur le client). Si no_root_squash est choisi, alors root sur la machine cliente aura les mêmes droits d'accès aux fichiers que root sur le serveur. Cela peut avoir d'importantes conséquences de sécurité, bien que cela puisse être nécessaire s'il y a besoin de réaliser des tâches administratives sur le client qui impliquent les répertoires exportés. Vous devez avoir une bonne raison pour spécifier cette option.
- no_subtree_check : Seulement si une partie du volume est exportée, une routine appelée “subtree checking” vérifie qu'un fichier qui est appelé par le client est dans la partie appropriée du volume. Si le volume entier est exporté, désactiver cette vérification accélérera les transferts.
- sync : Par défaut, toutes les versions sauf la plus récente (version 1.11) de la commande exportfs utilisera le mode asynchrone (async) indiquant à la machine cliente que l'écriture sur un fichier est terminée – c'est à dire, a été réalisée sur un support de stockage convenable – quand NFS a terminé de gérer l'écriture sur le système de fichiers. Ce comportement peut corrompre les données si le serveur venait à rebooter, et l'option sync empêche cela. Voir le paragraphe 5 “Optimiser les performances de NFS” pour une présentation complète des comportements de sync et async.
Supposons que nous ayons deux machines clientes, slave1 et slave2, qui ont respectivement les adresses 192.168.0.1 et 192.168.0.2. Nous désirons partager nos binaires logiciels et répertoires home avec ces machines. Une configuration typique pour le fichier /etc/exports pourrait ressembler à cela :
/usr/local 192.168.0.1(ro) 192.168.0.2(ro) /home 192.168.0.1(rw) 192.168.0.2(rw)
Ici nous partageons /usr/local en lecture seule avec slave1 et slave2, car il contient probablement nos logiciels et il n'y a pas d'intérêts à autoriser slave1 et slave2 à écrire dessus pour raisons de sécurité. D'un autre coté, les répertoires /home doivent être exportés en lecture/écriture si les utilisateurs souhaitent y enregistrer leur travail. Si vous avez une installation importante, vous pouvez vous retrouver avec beaucoup d'ordinateurs, tous sur le même réseau local, qui nécessitent l'accès au serveur. Il existe plusieurs façons de simplifier la désignation d'un grand nombre d'ordinateurs. Premièrement, vous pouvez donner l'accès en une seule saisie à un groupe de machines en spécifiant un réseau et un masque de réseau. Par exemple, si vous désirez autoriser l'accès à toutes les machines ayant une adresse IP entre 192.168.0.0 et 192.168.0.255 , alors vous pouvez entrer :
/usr/local 192.168.0.0/255.255.255.0(ro) /home 192.168.0.0/255.255.255.0(rw)
Deuxièmement, vous pouvez utiliser les groupes réseau NIS dans les entrées. Pour spécifier un groupe réseau dans le fichier exports, simplement précéder le nom du groupe réseau avec un @. Troisièmement, vous pouvez utiliser les jokers tels que *.foo.com ou 192.168. à la place des noms d'hôtes. Il y avait des problèmes avec les jokers dans les noyaux 2.2 qui ont été résolus avec le noyau 2.2.19. Cependant, vous devez garder à l'esprit que chacune de ces simplifications peut causer un risque au niveau de la sécurité s'il y a au sein du groupe réseau ou du réseau local des machines non dignes de confiance.
Quelques précautions au sujet de ce qui ne doit pas (ou devrait pas) être exporté. Premièrement, si un répertoire est exporté, ses parent et enfants ne peuvent pas être exportés s'ils sont dans le même système de fichiers. Cependant, exporter les deux ne devrait pas être nécessaire car ajouter le répertoire parent dans le fichier /etc/exports provoque l'exportation de tous les sous répertoires du même système de fichiers. Deuxièmement, c'est une mauvaise idée que d'exporter un système de fichiers FAT ou VFAT (par ex : MS-DOS ou Windows 95/98) avec NFS. FAT n'est pas conçu pour une utilisation sur une machine multi-utilisateurs, et en conséquence, les opérations qui dépendent des permissions ne fonctionneront pas. Troisièmement, les périphériques et autres fichiers spéciaux peuvent ne pas être exportés correctement vers des clients non Linux.
/etc/hosts.allow et /etc/hosts.deny
Ces deux fichiers spécifient quels ordinateurs du réseau peuvent utiliser les services du serveur. Chaque ligne du fichier contient une entrée listant un service et un groupe de machines. Quand le serveur reçoit la requête d'une machine, il fait ce qui suit :
- Il vérifie d'abord hosts.allow pour voir si la machine correspond à une règle listée ici. Si c'est le cas, alors l'accès est autorisé.
- Si la machine ne correspond pas à une règle listée dans hosts.allow, alors le serveur consulte hosts.deny pour voir si le client correspond à une règle listée ici. Si c'est le cas, alors l'accès est refusé.
- Si le client ne correspond à aucune règle de chaque fichier, alors l'accès est autorisé
En plus de contrôler l'accès aux services gérés par inetd (tels que telnet et FTP), ce fichier peut aussi contrôler l'accès à NFS en restreignant les connexions aux démons qui fournissent les services NFS. Les restrictions sont faites service par service. Le premier démon auquel l'accès est restreint est portmapper. Essentiellement, ce démon indique aux clients comment trouver tous les services NFS sur le système. Restreindre l'accès à portmapper est la meilleure défense contre les intrusions via NFS car les clients non autorisés ne sauront pas où trouver les démons NFS. Cependant, il y a deux choses à surveiller. La première, c'est que restreindre portmapper n'est pas suffisant si, pour une raison quelqconque, l'intrus sait où trouver les démons. La deuxième, si vous exécutez NIS, c'est que restreindre portmapper limitera aussi les requêtes vers NIS. Cela est généralement sans gravité puisque vous désirez en principe restreindre NFS et NIS de la même façon, mais soyez prévenu.
En général, c'est une bonne idée avec NFS (comme avec la plupart des services internet) de refuser explicitement l'accès aux adresses IP dont vous n'avez pas besoin d'autoriser l'accès. La première étape pour cela est d'ajouter l'entrée suivante à /etc/hosts.deny :
portmap:ALL
A partir de nfs-utils 0.2.0, vous pouvez être un peu plus rigoureux en contrôlant individuellement l'accès aux démons. C'est une bonne précaution puisque qu'un intrus sera souvent capable de soutirer l'accès à portmapper. Si vous avez une version plus récente de nfs-utils, ajoutez des entrées pour chacun des démons NFS (voir le prochain chapitre pour savoir qui sont ces démons, pour l'instant, écrire une entrée pour chacun d'eux dans hosts.deny.
lockd:ALL mountd:ALL rquotad:ALL statd:ALL
Même si vous avez une version plus ancienne de nfs-utils, l'ajout de ces entrées est au pire sans effet (puisqu'elles seront ignorées) et au mieux vous épargneront du souci lors de l'upgrade. Certains administrateurs choisissent de mettre l'entrée ALL:ALL dans le fichier /etc/hosts.deny, ce qui a pour effet que tout service qui lit ces fichiers refusera l'accès de tout hôte, a moins qu'il ne soit explicitement autorisé. Bien que faire ainsi soit plus sûr, cela peut aussi vous causer des soucis quand vous installez de nouveaux services, vous oubliez avoir fait cette configuration et ne comprenez pas pourquoi ils ne fonctionnent pas.
Ensuite, nous avons besoin d'ajouter une entrée dans /etc/hosts.allow pour donner à tous les hôtes les accès nécessaires (si nous laissons seulement les lignes ci-dessus dans /etc/hosts.deny, alors personne n'aura accès à NFS). Les entrées dans /etc/hosts.allow suivent ce format :
service: hôte [ou réseau/masque] , hôte [ou réseau/masque]
Ici, hôte est l'adresse IP d'un client potentiel, il est possible dans certaines versions d'utiliser le nom DNS, mais c'est fortement déconseillé. Supposons que nous ayons la configuration ci-dessus et que nous souhaitons seulement autoriser l'accès à slave1.foo.com et à slave2.foo.com, et supposons que l'adresse IP de ces machines est respectivement 192.168.0.1 et 192.168.0.2. on peut ajouter l'entrée suivante dans /etc/hosts.allow :
portmap: 192.168.0.1 , 192.168.0.2
Dans les versions récentes de nfs-utils on peut aussi ajouter (encore une fois, ces entrées sont sans inconvénient même si elles ne sont pas supportées) :
lockd: 192.168.0.1 , 192.168.0.2 rquotad: 192.168.0.1 , 192.168.0.2 mountd: 192.168.0.1 , 192.168.0.2 statd: 192.168.0.1 , 192.168.0.2
Si vous avez l'intention de lancer NFS sur un grand nombre de machines dans un réseau local, /etc/hosts.allow permet aussi les entrées au format réseau/masque tout comme /etc/exports ci-dessus.
Démarrer les services
Pré-requis
Le serveur NFS devrait être maintenant configuré et nous pouvons le démarrer. Premièrement, vous devez avoir les paquetages nécessaires installés. Ensuite, avant de démarrer NFS, vous devez avoir le réseau TCP/IP en état de marche sur votre machine. Si vous pouvez utiliser telnet, FTP, etc., alors il est très probable que votre TCP soit correct. Ceci dit, avec les distributions Linux récentes, il est possible de démarrer NFS simplement en rebootant la machine, et les scripts de démarrage vont détecter que vous avez configuré le fichier /etc/exports et vont démarrer NFS correctement. Voir le chapitre 4 “Configurer un client NFS”. Si cela ne fonctionne pas, ou si vous ne pouvez pas rebooter la machine, alors le chapitre suivant vous dira quels démons doivent être démarrés pour lancer les services NFS. Si pour une raison quelconque, nfsd était déjà en exécution quand vous avez édité les fichiers de configuration ci-dessus, vous devez ré-initialiser votre configuration, voir le chapitre 4 “Configurer un client NFS” pour plus de détails.
Démarrer Portmapper
NFS dépend du démon portmapper, aussi appellé portmap ou rpc.portmap. Il doit être démarré en premier. Il est normalement placé dans /sbin mais quelquefois dans /usr/sbin. Les distributions les plus récentes démarrent ce démon dans les scripts de boot, mais il est préférable de s'assurer qu'il est en fonctionnement avant de commencer avec NFS (juste taper ps aux ).
Les démons
NFS est pris en charge par cinq démons : rpc.nfsd, qui réalise la majorité du travail; rpc.lockd et rpc.statd, qui gèrent le verrouillage des fichiers; rpc.mountd, qui gère les requêtes du montage initial, et rpc.rquotad qui gère les quotas du fichier utilisateur sur les volumes exportés. A partir du 2.2.18, lockd est appelé par nfsd sur demande, aussi, vous n'avez pas besoin de vous soucier de son démarrage. statd aura besoin d'être démarré séparément. Les distributions Linux les plus récentes possèdent des scripts de démarrage pour tous ces démons. Les démons font tous partie du paquetage nfs-utils, et sont soit dans le répertoire /sbin ou /usr/sbin Si votre distribution ne les inclut pas dans les scripts de démarrage, alors vous devez les ajouter, configurés pour démarrer dans l'ordre suivant :
rpc.portmap rpc.mountd, rpc.nfsd rpc.statd, rpc.lockd (si nécessaire), et rpc.rquotad
Le paquetage nfs-utils possède des modèles de scripts de démarrage pour RedHat et Debian. Pour les autres distributions, en général, vous pouvez simplement copier le script Redhat, mais vous aurez probablement à enlever la ligne qui dit :
. ../init.d/functions
pour éviter d'avoir des messages d'erreur.
Vérifier que NFS est en marche
Pour cela, interrogez portmapper avec la commande rpcinfo quota pour découvrir quels services sont fournis. Vous devez obtenir quelque chose comme cela :
program vers proto port 100000 2 tcp 111 portmapper 100000 2 udp 111 portmapper 100011 1 udp 749 rquotad 100011 2 udp 749 rquotad 100005 1 udp 759 mountd 100005 1 tcp 761 mountd 100005 2 udp 764 mountd 100005 2 tcp 766 mountd 100005 3 udp 769 mountd 100005 3 tcp 771 mountd 100003 2 udp 2049 nfs 100003 3 udp 2049 nfs 300019 1 tcp 830 amd 300019 1 udp 831 amd 100024 1 udp 944 status 100024 1 tcp 946 status 100021 1 udp 1042 nlockmgr 100021 3 udp 1042 nlockmgr 100021 4 udp 1042 nlockmgr 100021 1 tcp 1629 nlockmgr 100021 3 tcp 1629 nlockmgr 100021 4 tcp 1629 nlockmgr
Ceci dit que nous avons NFS versions 2 et 3, rpc.statd version 1, le gestionnaire de verrouillage du réseau (network lock manager, le nom du service pour rpc.lockd) versions 1, 3, et 4. Il y a aussi différents services de listés suivant que NFS fonctionne sur TCP ou UDP. Les systèmes Linux utilisent UDP par défaut, à moins que TCP soit explicitement requis; cependant d'autres OS tels que Solaris choisissent TCP par défaut. Si vous ne voyez pas au moins un ligne qui cite portmapper, une ligne qui cite nfs et une ligne pour mountd, alors vous devez reprendre depuis le début et essayer à nouveau de démarrer les démons (voir le chapitre 7 “Dépannage” si cela ne fonctionne pas). Si vous voyez ces services listés, alors vous êtes prêt à paramétrer les clients NFS pour qu'ils accèdent aux fichiers du serveur.
Modifier le fichier /etc/exports a posteriori
Si vous revenez et modifiez le fichier /etc/exports, les changements ne seront pas pris en compte immédiatement. Vous devez exécuter la commande exportfs -ra pour obliger nfsd de relire le fichier /etc/exports. Si vous ne trouvez pas cette commande, alors vous pouvez tuer nfsd avec le drapeau -HUP. Voir les pages man de kill pour plus de détails. Si cela ne marche toujours pas, voir le fichier hosts.allow pour s'assurer que vous n'avez pas oublié de lister une machine cliente. Vérifier aussi la liste des hôtes sur les pare-feu. Voir les chapitres 7 “Dépannage” et 6 “NFS et la sécurité” pour plus de détails.
Configurer un client NFS
Montage des répertoires distants
Avant de commencer il est bon de vérifier que votre programme mount est assez récent (version 2.10m pour utiliser la version 3 de NFS) et que la machine cliente supporte le montage avec NFS, même si la plupart des distributions le permettent. Si vous avez un noyau version 2.2 ou plus récent, avec le système de fichiers /proc, vous pouvez faire cette vérification en lisant le fichier /proc/filesystems et en vous assurant d'y trouver une ligne contenant nfs. Dans le cas contraire, taper insmod nfs peut le faire magiquement apparaître si NFS a été compilé en tant que module ; sinon vous devrez construire (ou télécharger) un noyau qui intègre le support de NFS. En général, les noyaux qui n'incorporent pas la compilation de NFS vous donneront un message d'erreur très spécifique quand la commande mount ci-dessous est lancée.
Pour démarrer l'utilisation d'une machine cliente NFS, vous avez besoin que portmapper fonctionne sur cette machine, et d'utiliser le verrouillage des fichiers NFS (NFS file locking), vous aurez aussi besoin de rpc.statd et rpc.lockd fonctionnant à la fois sur le serveur et le client. Les distributions récentes démarrent ces services par défaut au moment du boot.
Avec portmap, lockd, et statd en fonctionnement, vous devriez maintenant être capable de monter le répertoire du serveur distant, exactement comme vous montez un disque dur local, avec la commande mount. Continuons notre exemple du paragraphe précédent, supposons que notre serveur, ci-dessus, est appelé master.foo.com et que nous désirons monter le répertoire /home sur slave1.foo.com. Alors, tout ce que nous avons à faire, en root, sur slave1.foo.com est de taper :
et le répertoire /home du serveur apparaîtra en tant que répertoire mnt/home sur le client slave1. (Remarquez que cela suppose auparavant la création du répertoire de montage vide mnt/home)
Si cela ne fonctionne pas, voir le chapitre 7 " Dépannage" Vous pouvez démonter le système de fichiers en tapant :
exactement comme vous le feriez pour un système de fichiers local.
Montage automatique du système de fichiers NFS au démarrage
Le système de fichiers NFS exporté peut être ajouté à votre fichier /etc/fstab de la même façon qu'un système de fichiers local, ainsi il est monté lors du démarrage de votre système. La seule différence est que le type de système de fichiers doit être indiqué nfs et les valeurs de dump et fsckorder (les deux dernières entrées) doivent être à 0. Ainsi pour notre exemple ci-dessus, l'entrée dans /etc/fstab devrait ressembler à :
# device mountpoint fs-type options dump fsckorder ... master.foo.com:/home /mnt nfs rw 0 0 ...
voyez les pages man de fstab si vous n'êtes pas familier avec sa syntaxe. Si vous utilisez un automontage avec amd ou autofs, les champs correspondants dans la liste des montages devraient être très ressemblants voire identiques. A ce moment, vous devriez avoir un NFS en fonctionnement, bien que quelques astuces peuvent être encore nécessaires pour le faire fonctionner parfaitement. Vous devriez aussi lire la section 6 "NFS et la sécurité" pour être sûr que votre configuration est raisonnablement sûre.
Options de montage
Montage soft ou montage hard
Il existe quelques options à ajouter systématiquement. Elles définissent la façon dont le client NFS gère un crash du serveur ou du réseau. Une des choses agréables de NFS est qu'il peut gérer cela gracieusement, si le client est bien paramétré. Il y a deux modes distinct de défaillance :
- soft
Si la requête d'un fichier échoue, le client NFS rapportera une erreur au processus sur la machine cliente requérant l'accès au fichier. Certains programmes peuvent gèrer cela avec calme, la plupart ne le feront pas. Nous ne recommandons pas d'utiliser ce paramètre ; c'est une recette pour avoir des fichiers corrompus et des pertes de données. Vous ne devriez surtout pas faire ce choix pour les disques de courrier, si vous tenez à votre courrier, bien sûr.
- hard
Le programme accédant au fichier sur un système de fichiers monté avec NFS figera si le serveur crash. Le processus ne peut pas être interrompu ou tué (excepté par un "sure kill") à moins que vous ne spécifiez aussi intr. Quand le serveur NFS est de retour en ligne le programme continuera imperturbablement de l'endroit où il était. Nous recommandons d'utiliser hard,intr sur tous les systèmes de fichiers montés avec NFS.
Reprenant l'exemple précédent, le /etc/fstab devient maintenant :
# device mountpoint fs-type options dump fsckord ... master.foo.com:/home /mnt/home nfs rw,hard,intr 0 0 ...
Les options de montage rsize et wsize spécifient la taille des blocs de données que s'échangent le client et le serveur. Les valeurs par défaut peuvent être trop grosses ou trop petites ; il n'y a pas de taille qui conviennent à tous les paramétrages. D'un côté, certaines combinaisons des noyaux Linux et des cartes réseau (plus particulièrement sur les vieilles machines) ne peuvent pas gérer des blocs aussi gros. D'un autre côté, si la gestion de blocs plus importants est possible, les échanges seront plus rapides. Trouver la taille optimale des blocs est un facteur important de performance et c'est un grand avantage si vous envisagez d'utiliser des serveurs NFS dans un environnement de production. Voir le chapitre 5 "Optimiser les performances de NFS" pour plus de détails.
Optimiser les performances de NFS
Pour obtenir des performances optimales avec NFS, la première chose à faire est d'analyser soigneusement l'environnement à la fois du côté serveur et du côté client. les premiers chapitres traitent des problèmes qui sont généralement importants pour le client. Ensuite (chapitre 5.3 et suivants), seront traités les problèmes côté serveur. Dans les deux cas, ces problèmes ne seront pas limités exclusivement à un côté ou à un autre, mais il est pratique de séparer les deux dans le but d'obtenir une vision claire des causes et des effets.
En parallèle avec la configuration générale du réseau - capacité appropriée du réseau, NIC rapides, paramétrage full duplex dans le but de réduire les collisions, cohérence dans les vitesses de communication entre les switches et les hubs, etc. - une des optimisations les plus importantes côté client est la taille des buffers de transfert des données par NFS, spécifiées par les options rsize et wsize de la commande mount
Optimisation des vitesses de transfert
Les options de montage rsize et wsize de la commande mount spécifient la taille des blocs de données que s'échangent le client et le serveur. Si ces options ne sont pas spécifiées, les valeurs par défaut varient en fonction de la version de NFS utilisée. La valeur par défaut la plus répandue est 4Ko (4096 octets), bien que dans le cas des montages basés sur TCP dans les noyaux 2.2, et pour tous les montages avec les noyaux commençants à 2.4, la taille des blocs par défaut est spécifiée par le serveur.
La limite théorique pour le protocole NFS version 2 est de 8Ko. Pour le protocole version 3, la limite est spécifique au serveur. Sur un serveur Linux, la taille maximum des blocs est définie par la constante du noyau NFSSVC_MAXBLKSIZE trouvée dans le fichier source du noyau ./include/linux/nfsd/const.h.
La taille des blocs maximum actuelle pour le noyau à partir de 2.4.17, est 8Ko (8192 octets), mais le patch pour implémenter NFS sur le transport TCP/IP dans les versions 2.4.x utilise comme taille maximum des blocs une valeur de 32 Ko (définie dans le patch par 32*1024). Tous les postes client à la version 2.4 supportent jusqu'à 32 Ko pour la taille des blocs de transfert, permettant des transferts au standard de 32 Ko dans les montages NFS en provenance d'autres serveurs, tels que Solaris, sans modification du client.
Les valeurs par défaut peuvent être trop grandes ou trop faibles, en fonction de la combinaison entre matériel et noyaux. D'un côté, certaines combinaisons des noyaux Linux et des cartes réseau (plus particulièrement sur les vieilles machines) ne peuvent pas gérer des blocs aussi gros. D'un autre côté, si la gestion de blocs plus importants est possible, les échanges seront plus rapides. Au cas où vous aimeriez tester et trouver les valeurs de rsize et wsize qui fonctionnent tout en étant aussi rapides que possible, vous pouvez utiliser quelques commandes simples, si votre environnement réseau n'est pas surchargé. Notez que vos résultats peuvent largement varier sauf à utiliser des benchmarks plus complexes tels que Bonnie, Bonnie++, ou IOzone.
La première de ces commandes tranfère 16384 blocs de 16 ko chacun depuis le fichier spécial /dev/zero (lequel si vous le lisez, crache simplement des zéros vraiment très rapidement) vers la partition montée. Nous allons mesurer le temps nécessaire avec time. Ainsi depuis la machine cliente, taper :
# time dd if=/dev/zero of=/mnt/home/testfile bs=16k count=16384
Cela crée un fichier de 256 Mo ne contenant que des octets zéro. En général, vous devriez créer un fichier qui est au moins deux fois plus grand qu'il y a de RAM sur le serveur, mais assurez vous d'avoir assez d'espace disque ! Puis retournez le fichier dans le grand trou sans fond /dev/null de la machine cliente en tapant la commande suivante :
# time dd if=/mnt/home/testfile of=/dev/null bs=16k
Répétez cela plusieurs fois et faites la moyenne du temps nécessaire. Assurez vous de démonter puis de remonter le système de fichiers à chaque fois (à la fois sur le client et aussi, si vous êtes zélé, localement sur le serveur), ce qui devrait vider les caches. Ensuite, démontez et remontez à nouveau avec des blocs plus grands et plus petits. Ils doivent être multiples de 1024, et pas plus grands que le maximum permis par votre système. Notez que NFS Version 2 est limité au maximum de 8 Ko, indépendamment de la taille maximum définie par NFSSVC_MAXBLKSIZE; la Version 3 supporte jusqu'à 64 Ko si permis. La taille des blocs devrait être une puissance de deux puisque la plupart des paramètres qui la concerne (tels que la taille des blocs du système de fichiers et la taille des paquets réseau) sont aussi des puissances de deux. Cependant, certains utilisateurs ont rapporté avoir de meilleurs résultats avec des multiples de la taille des blocs du système de fichiers et de la taille des paquets réseau.
Directement après le montage avec une taille supérieure, tapez cd dans le système de fichiers monté et faites des choses comme ls, explorez un peu le système de fichiers pour vous assurer que tout est correct. Si les valeurs rsize/wsize sont trop importantes les symptômes sont très étranges et pas évidents à 100%. Un symptôme typique est une liste incomplète de fichiers après la commande ls, sans message d'erreur, ou l'échec mystérieux de la lecture de fichiers sans message d'erreur. Après avoir établi que les rsize/wsize donnés fonctionnent, vous pouvez a nouveau effectuer les tests de vitesse. Différentes plateformes de serveurs auront probablement des tailles optimales différentes. N'oubliez pas d'éditer le fichier /etc/fstab/ pour noter les rsize/wsize que vous avez trouvés étant les plus performants. Si les résultats semblent incohérents ou douteux, vous avez besoin d'analyser votre réseau plus en détail pendant les variations de rsize et de wsize. Dans ce cas, voici plusieurs liens vers des benchmarks qui peuvent s'avérer utiles :
- Bonnie: http://www.textuality.com/bonnie/
- IOZone File System Benchmark:http://www.iozone.org
- The official NFS benchmark, SPECsfs97: http://www.spec.org/osg/sfs97/
Le benchmark le plus facile avec le plus de fonctionnalités, y compris un large éventail de tailles de fichiers, et de types de I/O - lecture, écriture, relecture, ré-écriture, accès aléatoire, etc - semble être IOzone. L'invocation de IOzone (pour lequel vous devez avoir les droits administrateur) inclut le montage et démontage du répertoire en test, dans le but d'effacer les caches entre les tests, et inclut dans les mesures l'heure de fermeture du fichier. En supposant que vous avez déjà exporté /tmp dans chaque client depuis le serveur foo, et que vous avez installé IOzone dans le répertoire local, ceci devrait fonctionner :
# echo "foo:/tmp /mnt/foo nfs rw,hard,intr,rsize=8192,wsize=8192 0 0" >> /etc/fstab # mkdir /mnt/foo # mount /mnt/foo # ./iozone -a -R -c -U /mnt/foo -f /mnt/foo/testfile > logfile
Le benchmark devrait prendre 2 ou 3 heures au plus, mais vous aurez besoin de l'exécuter pour chaque valeur de rsize et de wsize qui présentent un intérêt. Le site web donne une documentation complète sur les paramètres, mais les options utilisées ci-dessus sont :
- -a : mode entièrement automatique, il teste les tailles de fichiers de 64Ko à 512Mo, utilisant des tailles enregistrées de 4Ko à 16Mo
- -R : génère un rapport au format de la feuille de calcul Excel (l'option "surface plot" pour les graphes est préférable)
- -c : Inclut l'heure de fermeture des fichiers dans les tests, récupérée auprès de l'heure validée par NFS version 3 .
- -U : utilise le point de montage donné pour démonter et remonter entre les tests, il efface les caches
- -f : Lors de l'utilisation du démontage, vous devez situer le fichier test dans le système de fichiers monté.
Taille des paquets et pilotes de réseau
Alors que beaucoup de pilotes de cartes réseau pour Linux sont excellents, certains laissent à désirer, y compris certains pour des cartes répandues. Cela vaut la peine d'expérimenter directement avec votre carte réseau pour découvrir comment elle peut gérer au mieux le trafic. Essayer de 'pinger' dans les deux sens entre les deux machines avec de grands paquets en utilisant les options -f et -s avec ping (voir ping(8) pour plus de détails) et voir si beaucoup de paquets sont perdus, ou si la réponse demande beaucoup de temps. Si c'est le cas, vous pouvez avoir un problème de manque de performance avec votre carte réseau. Pour une analyse plus détaillée du comportement de NFS en particulier, utilisez la commande nfsstat pour examiner les transactions de nfs, les statistiques du client et du serveur, les statistiques réseau, et autres choses.
L'option -o net vous donnera le nombre de paquets perdus par rapport au nombre total de transactions. Dans les transactions UDP, les statistiques les plus importantes sont le nombre de retransmissions, en raison des paquets perdus, les débordements de tampon mémoire de connexion, la congestion du serveur, les dépassements de temps, etc... Cela aura un impact considérable sur la performance de NFS et doit être soigneusement surveillé. Notez que nfsstat n'implémente pas encore l'option -z, qui remettrait tous les compteurs à zéro, aussi vous devez relever le compteur en cours de nfsstat avant d'exécuter des benchmarks.
Pour corriger des problèmes de réseau, vous pouvez désirer reconfigurer la taille des paquets utilisée par votre carte réseau. Très souvent, il y a des contraintes ailleurs dans le réseau (par exemple dans un routeur) qui imposent une taille maximum des paquets plus petite que ce qu'accepte la carte. TCP devrait s'autoconfigurer avec la taille des paquets la plus appropriée pour le réseau, mais UDP restera à la valeur par défaut. Aussi, déterminer la taille des paquets la plus appropriée est spécialement important si vous utilisez NFS sur UDP. Vous pouvez tester la taille des paquets réseau en utilisant la commande tracepath : Depuis la machine cliente, exécutez :
$ tracepath server
1: server (x.x.x.x) 0.274ms pmtu 1500
1: x.x.x.x (x.x.x.x) 0.494ms
2: x.x.x.x (x.x.x.x) 0.424ms
3: x.x.x.x (x.x.x.x) 1.042ms
4: server (x.x.x.x) 0.421ms reached
Resume: pmtu 1500 hops 4 back 4
$
et le MTU (maximum transmission unit = la taille maximale (en octets) du paquet pouvant être transmis en une seule fois) du chemin est reporté en bas (pmtu).Vous pouvez aussi définir le MTU de votre carte réseau égale au MTU du chemin, en utilisant l'option MTU de la commande ifconfig, et voir si moins de paquets sont perdus. Voir les pages man de ifconfig pour plus de détails sur comment ré-initialiser le MTU. De plus, netstat -s vous donnera les statistiques du trafic dans tous les protocoles supportés. Vous pouvez aussi regarder dans /proc/net/snmp pour y trouver les informations actuelles au sujet du réseau, voir le chapitre suivant pour plus d'informations.
Dépassement de paquets fragmentés
Utiliser des rsize ou wsize plus grands que le MTU de votre réseau (souvent fixé à 1500 dans la plupart des réseaux) provoquera la fragmentation des paquets IP en utilisant NFS sur UDP. La fragmentation des paquets IP et leur ré-assemblage consomme une part importante des ressources CPU aux deux extrémités de la connexion. De plus, la fragmentation des paquets expose votre réseau à une plus grande vulnérabilité, puisqu'une requête RPC complète doit être transmise si un fragment de paquet UDP est perdu quelqu'en soit la raison. Tout accroissement des retransmissions RPC, conjugué à la possibilité d'un accroissement des dépassements de temps (timeouts), sont les pires obstacles à la performance de NFS sur UDP.
Les paquets peuvent être perdus pour de multiples raisons. Si la topographie de votre réseau est complexe, les routes des fragments peuvent différer, et il peuvent ne pas tous arriver au serveur pour le réassemblage. La capacité du serveur NFS peut aussi être un problème, puisque le noyau a une limite du nombre de fragments qu'il peut mémoriser avant de rejeter les paquets. Avec les noyaux qui supportent le système de fichiers /proc, vous pouvez surveiller les fichiers /proc/sys/net/ipv4/ipfrag_high_thresh et /proc/sys/net/ipv4/ipfrag_low_thresh. Une fois que le nombre de paquets fragmentés non traités atteint le nombre spécifié par ipfrag_high_thresh (en octets), le noyau rejettera simplement les paquets fragmentés jusqu'à ce que le nombre de paquets incomplets atteigne le nombre spécifié par ipfrag_low_thresh. Un autre compteur à surveiller est IP: ReasmFails dans le fichier /proc/net/snmp, ceci est le nombre d'échecs de réassemblages. S'il monte trop vite pendant une activité importante sur les fichiers, vous pouvez avoir un problème.
NFS sur TCP
Une nouvelle caractéristique, disponible pour les noyaux 2.4 et 2.5 mais pas encore généralisée aux derniers noyaux au moment de la rédaction, est NFS sur TCP. Utiliser TCP possède un avantage et un inconvénient par rapport à UDP. L'avantage est qu'il fonctionne beaucoup mieux que UDP sur les réseaux peu fiables. Avec TCP, un paquet perdu isolément peu être retransmis, sans la retransmission de la requête RPC complète,. De plus TCP gérera mieux que UDP les différences de vitesse du réseau, en raison du contrôle des flux au niveau du réseau. L'inconvénient de l'utilisation de TCP est que ce n'est pas un protocole statique comme UDP. Si le serveur plante en cours de transmission d'un paquet, le client restera dans l'attente et tous les partages devront être démontés et remontés. Les sur-débits encourus par le protocole TCP peuvent provoquer une légère moindre performance que UDP dans des conditions de réseau idéales, mais la différence est faible et souvent pas détectable sans mesures précises. Si vous utilisez un réseau Ethernet gigabit d'une extrémité à l'autre, vous pouvez aussi envisager l'utilisation des trames étendues, puisque la haute vitesse du réseau permet des tailles de trames plus importantes sans rencontrer d'augmentation du taux de collisions, particulièrement si vous avez réglé le réseau en full duplex.
Valeurs de retransmission et de dépassement de temps
Deux options de la commande mount timeo et retrans, contrôlent le comportement des requêtes d' UDP lors des dépassements de temps du client en raison des paquets perdus, de la congestion du réseau et autres. L'option -o timeo permet de désigner la durée du temps, en dixièmes de secondes, pendant lequel le client doit attendre avant de décider qu'il n'aura pas de réponse du serveur, et doit tenter d'envoyer la requête à nouveau. La valeur par défaut est 7 dixièmes de secondes. L'option -o retrans permet de désigner le nombre de retransmissions permises avant que le client n'abandonne, et affiche le message de non réponse du serveur. La valeur par défaut est 3 tentatives. Une fois que le client affiche ce message, il continue d'essayer d'envoyer la requête, mais seulement une fois avant d'afficher le message d'erreur si un autre dépassement de temps se produit. Quand le client rétablit le contact, il reprend la valeur correcte de retrans, et affiche le message Serveur OK
Si vous rencontrez un nombre de retransmissions excessif (voir la sortie de la commande nfsstat), ou désirez accroître la taille de transfert des blocs sans rencontrer de retransmissions ni de dépassements de temps, vous pouvez ajuster ces valeurs. Les réglages optimisés dépendent de votre environnement, mais dans la majorité des cas, les valeurs par défaut sont appropriées.
Nombre d'instances du démon serveur NFSD
La plupart des scripts de démarrage, Linux et autres, démarrent 8 instances de nfsd. Lors de débuts de NFS, SUN décida de conserver ce nombre comme règle empirique, et tout le monde copia. Il n'existe pas de mesures valables pour définir combien d'instances sont optimum, mais un serveur de gros trafic peut en nécessiter plus. Vous devez utiliser au strict minimum un démon par processeur, mais quatre à huit par processeur est une bonne règle empirique. Si vous utilisez un noyau version 2.4 ou supérieure et que vous voulez voir la charge d'utilisation de chaque thread de nfsd, vous pouvez regarder le fichier /proc/net/rpc/nfsd. Les dix derniers nombres de la ligne th de ce fichier indiquent le nombre de secondes pendant lesquelles l'utilisation de ce thread fut à ce pourcentage du maximum possible. Si les trois nombres du haut sont grands, vous pouvez avoir intérêt à augmenter le nombre d'instances de nfsd. Cela se fait en démarrant nfsd en précisant le nombre d'instances sur la ligne de commande, ce qui est spécifié dans le script de démarrage de NFS (/etc/rc.d/init.d/nfs sur Red Hat), sous le nom RPCNFSDCOUNT. Pour plus d'informations, voir les pages man de nfsd(8).
Limites mémoire sur la file d'attente en entrée
Sur les noyaux 2.2 et 2.4, la connexion de la file d'attente en entrée, où les requêtes attendent le résultat de leur exécution, a une limite de taille par défaut (rmem_default), faible, de 64 ko. Cette file d'attente est importante pour les clients ayant une charge importante en lecture, et pour les serveurs ayant une charge importante en écriture. A titre d'exemple, si vous exécutez 8 instances de nfsd sur le serveur, chacun n'aura que 8 Ko pour écrire les requêtes pendant qu'il les exécute. De plus, la connexion de la file d'attente en sortie - importante pour les clients ayant une charge importante en écriture, et pour les serveurs ayant une charge importante en lecture - a aussi une limite de taille par défaut (wmem_default) faible.
Plusieurs publications de benchmarks de NFS réalisés avec SPECsfs97 spécifient l'usage d'une valeur plus importante pour les variables de lecture et d'écriture [r/w]mem_default et [r/w]mem_max. Vous pouvez envisager augmenter ces valeurs jusqu'à au moins 256 Ko. Les limites sont définies dans /proc, par exemple dans les fichiers /proc/sys/net/core/rmem_default et /proc/sys/net/core/rmem_max. La valeur rmem_default peut être augmentée en trois étapes, la méthode suivante est un peu brutale mais devrait fonctionner sans causer de problèmes :
1 - augmenter les tailles listées dans les fichiers :
# echo 262144 > /proc/sys/net/core/rmem_default # echo 262144 > /proc/sys/net/core/rmem_max
2 - Redémarrer NFS par la méthode indiquée dans la documentation de votre distribution 3 - Il est préférable de revenir aux tailles limites normales au cas où d'autres systèmes en dépendent. Cette dernière étape peut être nécessaire car des machines ont planté ou ont eu des problèmes quand ces variables restent inchangées pendant de longues périodes.
# echo 65536 > /proc/sys/net/core/rmem_default # echo 65536 > /proc/sys/net/core/rmem_max
Arrêter l'Autonégociation de NICS et des Hubs
Si les cartes réseau autonégocient mal avec les hubs et les switches, et que les ports fonctionnent à des vitesses différentes, ou avec des configurations duplex différentes, les performances en seront sévèrement affectées en raison de collisions, de paquets perdus, etc. excessifs. Si vous constatez dans la sortie de nfsstat un nombre excessif de paquets perdus, ou un réseau de piètre performance en général, essayez différentes configurations pour la vitesse du réseau et pour les paramètres du duplex. Si possible, attachez vous à établir un sous réseau en 100BaseT full duplex, l'élimination virtuelle des collisions en full duplex enlèvera le plus puissant inhibiteur de performances de NFS sur UDP. Soyez attentif quand vous enlevez l'autonégociation sur un carte, le hub ou le switch auquel la carte est reliée se reportera alors à d'autres mécanismes (tels que la détection parallèle) pour déterminer les paramètres du duplex, et pour certaines cartes, du half duplex car il est plus probable qu'il soit supporté par les anciens hubs. La meilleure solution, si le pilote le supporte, est de forcer la carte à négocier le 100BaseT full duplex.
Fonctionnement synchrone ou asynchrone de NFS
L'export par défaut utilisé par exportfs dans les versions de nfs-utils antérieures à nfs-utils-1.0.1 est "asynchrone" pour les protocoles NFS Version 2 et Version 3. Cela permet au serveur de répondre aux requêtes du client aussitôt celles-ci traitées et envoyées au système de fichiers local, sans attendre que les données soient écrites sur un stockage sûr. Ceci est indiqué par l'option async précisée dans la liste d'export du serveur. Elle amène une meilleure performance au prix d'une corruption possible des données si le serveur reboot alors qu'il possédait encore des données non écrites et/ou des métadonnées dans ses caches. Cette corruption possible de données n'est pas détectable au moment des faits, puisque l'option async ordonne au serveur de mentir au client, lui disant que toutes les données ont été écrites sur un stockage sûr, indépendamment du protocole utilisé.
Afin d'avoir un fonctionnement synchrone, utilisé par défaut pour la plupart des systèmes propriétaires supportant NFS (Solaris, HP-UX, RS/6000, etc.), et maintenant utilisé par défaut dans la dernière version de exportfs, le système de fichiers du serveur Linux doit être exporté avec l'option sync. Notez que spécifier un export synchrone se traduit par l'absence d'option dans la liste d'export du serveur :
- Export de deux systèmes de fichiers vers tout le monde, en utilisant des options légèrement différentes :
# /usr/sbin/exportfs -o rw,sync *:/usr/local # /usr/sbin/exportfs -o rw *:/tmp
- Maintenant nous pouvons voir à quoi ressemblent les paramètres du système de fichiers exporté
# /usr/sbin/exportfs -v /usr/local *(rw) /tmp *(rw,async)
Si votre noyau est compilé avec le système de fichiers /proc, alors le fichier /proc/fs/nfs/exports montrera aussi la liste complète des options d'export. Quand le mode synchrone est spécifié, le serveur ne terminera pas une requête (c'est à dire ne répondra pas au client) selon le protocole NFS version 2 tant que le système de fichiers local n'a pas écrit toutes les données/métadonnées sur le disque. Le serveur terminera une requête selon le protocole NFS version 3 sans ce délai, et retournera les statuts des données pour informer le client au sujet des données qui doivent rester dans son cache, et les données qu'il est sûr de pouvoir effacer. Il existe 3 valeurs possibles pour les statuts, définies par nfs3_stable_how, de type énumération, dans le fichier include/linux/nfs.h. Les valeurs et le détail des actions prises par la suite en conséquence, sont les suivantes :
- NFS_UNSTABLE :
Les données/métadonnées n'ont pas été validées vers une mémoire stable sur le serveur, et doivent être gardées en cache sur le client jusqu'à ce qu'une requête de validation ultérieure par le client assure que le serveur envoyé bien les données vers une mémoire stable.
- NFS_DATA_SYNC :
Les métadonnées n'ont pas été validées vers une mémoire stable et doivent être gardées en cache sur le client. Une validation ultérieure est nécessaire, comme requis ci-dessus
- NFS_FILE_SYNC :
Aucune donnée/métadonnée n'a besoin d'être gardée en cache, et un validation ultérieure n'a pas besoin d'être envoyée pour tout ce qui concerne cette requête.
En plus de la définition ci-dessus du mode synchrone, le client peut explicitement insister sur un mode synchrone total, indépendamment du protocole, en ouvrant tous les fichiers avec l'option O_SYNC. Dans ce cas, toutes les réponses aux requêtes du client devront attendre jusqu'à ce que les données aient atteint le disque du serveur, indépendamment du protocole utilisé (ce qui signifie que, dans NFS version 3, toutes les requêtes seront du type NFS_FILE_SYNC, et exigeront que le serveur retourne ce statut). Dans ce cas, les performances de NFS Version 2 et NFS Version 3 seront presque identiques.
Si, cependant, le vieux mode par défaut async est utilisé, l'option O_SYNC n'a aucun effet, quelque soit la version de NFS, puisque le serveur répondra au client sans attendre la fin de l'écriture. Dans ce cas, les différences de performances entre les versions disparaissent.
Enfin, remarquez que, pour les requêtes de protocole NFS version 3, une requête de validation ultérieure du client NFS au moment de la cloture du fichier, ou au moment du fsync(), obligera le serveur d'écrire toute donnée/métadonnée pas encore écrites sur le disque, et le serveur ne répondra pas au client avant que cela soit fait, aussi longtemps que le mode sync est actif. Si async est utilisé, la validation est essentiellement ineffective, puisqu'une fois encore le serveur ment au client, en lui disant que les données ont été envoyées en mémoire stable. Cela, a nouveau, expose le client et le serveur à la corruption de données, puisque les données en cache peuvent être effacées chez le client du fait qu'il croit que le serveur possède les données en mémoire stable.
Moyens indépendants de NFS d'améliorer les performances de serveur
En général, les performances du serveur et sa vitesse d'accès au disque auront un effet important sur les performances de NFS. Offrir des pistes d'amélioration d'un serveur de fichiers est hors du propos de ce document, mais quelques points méritent d'être mentionnés :
- Si vous utilisez le RAID, utilisez le RAID 1/0 à la fois pour la vitesse d'écriture et la redondance, RAID 5 donne une bonne vitesse de lecture mais une médiocre vitesse d'écriture.
- Un système de fichiers journalisé réduira considérablement le temps de reboot en cas de plantage du système. Actuellement, ext3 fonctionnera correctement avec NFS version 3. De plus Reiserfs fonctionnera correctement avec NFS version 3 sur les noyaux 2.4.7 ou postérieurs (des patches sont disponibles pour les noyaux précédents). Les versions antérieures de Reiserfs n'ont pas la place pour les nombres de génération dans les inodes, risquant la non détection de données corrompues lors du reboot du serveur.
- En plus, les systèmes de fichiers journalisés peuvent être configurés pour maximiser les performances en utilisant l'avantage du fait que les mises à jour du journal sont tout ce qui est nécessaire pour la protection des données. un exemple est d'utiliser ext3 avec data=journal afin que toutes les mises à jour aillent d'abord dans le journal, et plus tard dans le système de fichiers principal. Une fois le journal mis à jour, le serveur NFS peut en toute sécurité émettre la réponse aux clients, et la mise à jour du système de fichiers principal peut se faire quand le serveur le décide. Le journal d'un système de fichiers journalisé peut aussi résider sur un périphérique séparé tel qu'une mémoire flash, de sorte que les mises à jour du journal ne requièrent normalement pas de recherches. Avec seulement les temps de rotation imposant un coût, ceci donne des performances d'IO synchrones raisonnablement bonnes. Remarquez qu'actuellement, ext3 supporte le relocation du journal, et Reiserf la supportera bientôt (officiellement).
- Utiliser un automonteur (tel que autofs ou amd) peut éviter un blocage si vous montez/croisez des fichiers (soit à dessein ou par erreur) et qu'une des machine s'arrête. voir Automount Mini-HOWTO pour plus de détails.
- Certains fabricants (Network Appliance, Hewlett Packard, et autres) fournissent des accélérateurs de NFS sous forme de RAM non volatile. NVRAM accélérera l'accès à la mémoire stable au niveau de l'accès async.
NFS et la sécurité
Cette liste de conseils et d'explications ne rendront pas votre site complètement sûr, RIEN ne rendra votre site complètement sûr. Lire ce chapitre peut vous aider à vous faire une idée des problèmes de sécurité avec NFS. Ceci n'est pas un guide complet et il est en changement permanent. Si vous êtes sur un réseau sans accès sur l'extérieur (pas même un modem) et que vous faites confiance à toutes les machines et à tous les utilisateurs, alors ce chapitre ne vous servira à rien. Cependant, nous pensons qu'il y a très peu de réseaux dans cette situation, aussi nous suggérons de lire ce chapitre en détails à tous ceux qui mettent NFS en place.
Avec NFS, il y a deux étapes nécessaires pour un client afin d'accéder à un fichier contenu dans un répertoire distant sur un serveur. La première étape est d'accéder au montage. Le montage est réalisé par le client qui tente une liaison au serveur. La sécurité pour cela est assurée par le fichier /etc/exports. Ce fichier liste les noms ou adresses IP des machines autorisées à accéder au partage. Si l'adresse IP du client correspond à une des entrées dans la liste d'accès, alors il sera autorisé au montage. Ce n'est pas très sûr. Si quelqu'un est capable de simuler ou de prendre le contrôle d'une adresse de confiance, alors il pourra accéder à vos points de montage. Pour donner un exemple de ce type "d'authentification" dans le monde réel, ceci est équivalent à quelqu'un se présentant lui-même, et vous croiriez ce qu'il prétend être parce qu'il porte un badge disant "Bonjour, mon nom est ...". Une fois que la machine cliente a monté un volume, son système d'exploitation aura accès à tous les fichiers du volume (avec une exception possible sur ceux possédés par root, voir ci-dessous) et également accès en écriture, si le volume a été exporté avec l'option rw.
La seconde étape est l'accès aux fichiers. C'est une fonction normale de contrôle d'accès au système de fichiers du client et non pas une fonction spéciale de NFS. Une fois le lecteur monté, les permissions du groupe et de l'utilisateur sur les fichiers déterminent le contrôle d'accès. Un exemple : Bob sur le serveur a pour UID 9999. Bob crée un fichier sur le serveur qui n'est accessible qu'a l'utilisateur (comme si il avait tapé chmod 600 filename). Un client est autorisé à monter le lecteur où le fichier est stocké. Sur le client, l'UID de Mary est 9999. Cela signifie que Mary, utilisateur sur le client, peut accéder au fichier de Bob qu'il a marqué comme accessible à lui seul. Il y a pire : Si quelqu'un est administrateur sur le client, il peut taper su - username et devenir n'importe quel utilisateur. NFS laissera faire. Ce n'est pas si terrible. Il y a quelques mesures que vous pouvez prendre sur le serveur pour écarter le danger des clients. Nous allons les évoquer prochainement. Au chapitre suivant, nous parlerons de la sécurité de portmapper, puis de la sécurité du serveur et celle du client. Enfin nous parlerons brièvement de la configuration correcte du parefeu pour NFS.
Portmapper
Portmapper conserve une liste des services en exécution et des ports qu'ils utilisent. Cette liste est utilisée par une machine se connectant pour connaître les ports à utiliser pour accéder a certains services. Portmapper n'est plus en aussi mauvaise forme qu'il y a quelques années, mais reste un point d'inquiétude pour beaucoup d'administrateurs système. Portmapper, comme NFS et NIS, ne devrait pas recevoir de connexions en dehors d'un réseau local de confiance. Si vous devez les exposer au monde extérieur, soyez attentif et surveillez vos systèmes.
Toutes les distributions Linux ne sont pas des créations d'égale sécurité. Certaines, apparemment à jour, ne comprennent pas de portmapper sécurisé. Une façon facile de vérifier si votre portmapper est bon est d'exécuter strings(1) et de voir s'il lit les fichiers pertinents /etc/hosts.deny et /etc/hosts.allow. En supposant que votre portmapper est placé dans /sbin/portmap vous pouvez le vérifier avec la commande suivante. Une machine sûre donnera une sortie comme celle-ci :
# strings /sbin/portmap | grep hosts. /etc/hosts.allow /etc/hosts.deny @(#) hosts_ctl.c 1.4 94/12/28 17:42:27 @(#) hosts_access.c 1.21 97/02/12 02:13:22 #
Premièrement, éditons /etc/hosts.deny et ajoutons la ligne suivante au fichier :
portmap: ALL
Qui interdira l'accès à quiconque. Pendant qu'il est fermé, exécutez :
juste pour vérifier que votre portmapper lit et obéit vraiment à ce fichier. rpcinfo ne devrait donner aucune sortie, ou éventuellement un message d'erreur. Les fichiers /etc/hosts.deny et /etc/hosts.allow prennent effet immédiatement après leur sauvegarde. Aucun démon ne doit être redémarré.
Fermer le portmapper à tout le monde est un peu sévère, aussi on l'ouvre à nouveau en éditant /etc/hosts.allow, mais nous devons imaginer quoi mettre à l'intérieur. Il faudrait lister toutes les machines autorisées à accéder à portmapper. Très peu de machines ont besoin de tous les accès en permanence. Les gestionnaires de portmapper nfsd, mountd, ypbind/ypserv, rquotad, lockd (visible sous le nom de nlockmgr), statd (visible sous le nom de status) et les services 'r' comme ruptime et rusers. Parmi eux, seuls nfsd, mountd, ypbind/ypserv et peut-être rquotad,lockd et statd portent à conséquence. Toutes les machines qui nécessitent un accès sur votre machine devraient être autorisées à faire cela. Disons que l'adresse de votre machine est 192.168.0.254 et qu'elle appartient au sous-réseau 192.168.0.0, et que toutes les machines du sous-réseau doivent y avoir accès. Alors nous écrivons :
portmap: 192.168.0.0/255.255.255.0
dans /etc/hosts.allow. Si vous ne connaissez pas votre réseau ou votre masque de réseau, vous pouvez utiliser la commande ifconfig pour déterminer le masque et la commande netstat pour déterminer le réseau. Par exemple, pour le périphérique eth0 sur la machine ci-dessus, ifconfig indique :
...
eth0 Link encap:Ethernet HWaddr 00:60:8C:96:D5:56
inet addr:192.168.0.254 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:360315 errors:0 dropped:0 overruns:0
TX packets:179274 errors:0 dropped:0 overruns:0
Interrupt:10 Base address:0x320
...
et netstat -rn indique :
Kernel routing table Destination Gateway Genmask Flags Metric Ref Use Iface ... 192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 174412 eth0 ...
(l'adresse du réseau est la première colonne). Les fichiers /etc/hosts.deny et /etc/hosts.allow sont décrits dans les pages man de même nom. IMPORTANT : Ne rien mettre d'autre que des adresses IP dans les lignes portmap de ces fichiers. Les consultations de noms d'hôtes peuvent indirectement causer de l'activité à portmap, lequel déclenchera des consultations de noms d'hôtes qui peuvent indirectement causer de l'activité à portmap, lequel déclenchera ....
Les versions 0.2.0 et suivantes du paquetage nfs-utils utilisent aussi les fichiers /etc/hosts.deny et /etc/hosts.allow, vous devriez donc aussi mettre des entrées dans ces fichiers pour ockd, statd, mountd, et rquotad. Pour un exemple complet, voir le chapitre 4 "Configurer un client NFS"
Les informations ci-dessus devraient rendre votre serveur plus sûr. Le seul problème restant est si quelqu'un obtient l'accès administrateur a l'une des machines clientes de confiance et est capable d'envoyer des requêtes NFS boguées. Le chapitre suivant traite des sécurités pour contrer ce problème.
Sécurité du serveur: nfsd et mountd
Sur le serveur on peut décider de ne pas faire confiance à toutes les requêtes faites sous root depuis un client. On peut paramétrer cela en utilisant l'option root_squash dans /etc/exports:
/home slave1(rw,root_squash)
C'est en fait le paramétrage par défaut. Il devrait toujours être utilisé, a moins d'avoir une très bonne raison de l'enlever. Pour l'enlever utiliser l'option no_root_squash.
Maintenant, si un utilisateur avec l'UID 0 (par ex. le numéro ID de l'utilisateur root) sur un client tente d'accéder (lire, écrire, effacer) au système de fichiers, le serveur lui substitue l'UID du compte "nobody" du serveur. Ce qui signifie que l'utilisateur root sur le client ne peut accéder ni modifier les fichiers que seul root sur le serveur peut accéder ou modifier. Mais, direz-vous, l'utilisateur root sur un client peut toujours utiliser su et devenir n'importe quel autre utilisateur et ainsi accéder ou modifier les fichiers de cet utilisateur ! Ce à quoi la réponse est : Oui, C'est de cette façon que cela fonctionne, que fonctionnent Unix et NFS. Cela implique une conséquence importante : Tous les fichiers importants doivent être possédés par root, et non pas par bin ou un autre compte non root, puisque le seul compte que les utilisateurs root des clients ne peuvent pas accéder est le compte root du serveur. Dans les pages man de exports(5), il y a plusieurs autres options de squash listées, ainsi vous pouvez décider de ne pas faire confiance à qui vous voulez parmi les clients.
Les ports TCP 1-1024 sont réservés pour root (et ainsi souvent désignés comme "ports sûrs"). Un utilisateur non root ne peut pas être associé à ces ports. Ajouter l'option secure dans /etc/exports signifie que seules seront prises en compte les requêtes venant des ports 1-1024 du client, ainsi un utilisateur malicieux, non root, sur un client ne peut pas s'introduire en usurpant une adresse IP pour un échange NFS sur un port non réservé.
Sécurité du client
L'option nosuid de mount
Sur le client, on peut décider de deux façons de ne pas faire confiance au serveur, avec les options de mount. Par exemple, on peut interdire, avec l'option nosuid, aux programmes suid de fonctionner sur le système de fichiers exporté avec NFS. Certains programmes Unix, tels que passwd, sont appelés programmes "suid" : ils donnent à celui qui les exécutent les droits du propriétaire du fichier. Si un fichier programme est possédé par root et est suid, alors le programme sera exécuté avec les droits root, si bien qu'il peut réaliser des opérations (comme modifier le fichier password) que seul root est autorisé à faire. L'option nosuid est recommandée pour tous les montages NFS. Cela signifie que l'utilisateur root sur le serveur ne peut réaliser de programmes suid sur les fichiers exportés, se loguer sur le client comme utilisateur ordinaire puis utiliser le programme suid pour devenir root également sur le client.
On pourrait aussi interdire l'exécution de fichiers dans le système de fichiers monté avec l'option noexec. Mais c'est d'un usage beaucoup moins pratique que pour nosuid car un système de fichiers contient probablement au moins quelques scripts ou programmes qui doivent être exécutés.
L'option broken_suid de mount
Certains vieux programmes (dont xterm) ont l'habitude de compter sur le fait que root peut écrire partout. Ce n'est plus le cas avec les nouveaux noyaux au sujet du montage NFS. Les implications sécuritaires font que les programmes capables de ce type d'action suid peuvent potentiellement être utilisés pour modifier votre uid apparent sur les serveurs nfs réalisant le mappage uid. Aussi la configuration par défaut a été d'invalider le broken_suid dans les noyaux Linux.
Si vous utilisez une vieille distribution Linux, il se pourrait que le montage se fasse avec l'option broken_suid. Les distributions récentes possèdent des programmes xterm ou de même type sous forme d'un exécutable normal sans statuts suid. Vous entrez les options ci-dessus dans la colonne options, avec rsize et wsize, séparés par une virgule.
Sécurisation de portmapper, rpc.statd, et rpc.lockd sur le client
Dans les implémentations actuelles (2.2.18+) de NFS, le verrouillage total du fichier est supporté. Ceci signifie que rpc.statd et rpc.lockd doivent être exécutés sur le client pour que le verrouillage fonctionne correctement. Ces services nécessitent le fonctionnement de portmapper. Aussi la plupart des problèmes avec NFS que vous trouverez sur le serveur vous donneront aussi des soucis sur le client. Lisez le chapitre sur portmapper ci-dessus pour plus de détails sur sa sécurisation.
NFS et les pare feu (ipchain et netfilter)
Ipchain (noyaux 2.2.X) et netfilter (noyaux 2.4.x) autorisent un bon niveau de sécurité, au lieu de compter sur le démon (ou peut-être son enveloppe TCP) pour déterminer quelles machines peuvent se connecter, la connexion tentée est autorisée ou interdite à un plus bas niveau. Dans ce cas vous pouvez arrêter la connexion plus facilement et plus globalement, ce qui peut vous protéger contre toutes formes d'attaques.
Décrire comment configurer un pare feu Linux va bien au-delà des prétentions de ce document. Les lecteurs intéressés peuvent lire Firewall-HOWTO ou IPCHAINS-HOWTO Les utilisateurs du noyau 2.4 et supérieur peuvent lire le site de netfilter.
Si les notions de ipchains ou de netfilter vous sont familières, ce chapitre vous donnera quelques astuces sur la configuration des démons de NFS afin de mieux les protéger avec le pare feu.
Une bonne règle à suivre pour la configuration du pare feu est de tout interdire puis d'autoriser certaines choses, ceci est une aide pour éviter d'accidentellement en autoriser plus que souhaité.
Pour comprendre comment protéger les démons NFS avec un pare feu, voyons brièvement comment ils sont reliés aux ports. Quand un démon démarre, il demande un port libre à portmapper. Celui-ci attribue un port au démon et garde la trace du port en cours d'utilisation par ce démon. Quand d'autres hôtes ou processus veulent communiquer avec le démon, ils demandent le numéro du port auprès de portmapper. Aussi l'attribution des ports change constamment car différents ports peuvent être libres à différents moments et portmapper les attribuera différemment à chaque fois. c'est une difficulté pour paramétrer un pare feu. Si vous ne savez jamais où sont les démons, alors vous ne pouvez pas savoir à quels ports il faut autoriser l'accès. Ce n'est peut-être pas un gros problème pour ceux qui utilisent un réseau local protégé ou isolé, mais c'est horrible pour ceux qui utilisent un réseau public.
Dans les noyaux 2.4.13 et suivants, avec nfs-utils 0.3.3 ou plus récent, vous n'avez plus à vous inquiéter de l'attribution des ports par portmapper. Maintenant tous les démons dépendants de nfs peuvent être "épinglés" à un port. La plupart d'entre eux, prennent une option -p quand ils sont démarrés, ceux qui sont démarrés par le noyau reçoivent des arguments ou des options du module. Ils sont décrits ci-dessous. Certains démons impliqués dans le partage des données via nfs sont déjà liés à un port. portmap est toujours sur le port 111 tcp et udp. nfsd est toujours sur le port 2049 TCP et UDP (cependant, à partir du noyau 2.4.17, NFS sur TCP est considéré expérimental et n'est pas utilisable en production). Les autres démons, statd, mountd, lockd, et rquotad, doivent normalement se voir attribuer le premier port disponible dont ils sont informés par portmapper.
Pour obliger statd à prendre un port particulier, utilisez l'option -p portnum. Pour obliger statd à répondre sur un port particulier, utilisez l'option -o portnum à son démarrage.
Pour obliger mountd à prendre un port particulier, utilisez l'option -p portnum. Par exemple, pour obliger statd à émettre sur le port 32765 et à écouter sur le port 32766, et mount à écouter sur le port 32767, vous tapez :
# statd -p 32765 -o 32766 # mountd -p 32767
lockd est démarré par le noyau quand c'est nécessaire. En conséquence, pour obliger lockd à n'écouter ou répondre que sur certains ports, vous devez indiquer les options au module (s'il est construit comme un module) ou au noyau. Si vous utilisez des modules chargeables et que vous vouliez spécifier ces options dans le fichier /etc/modules.conf ajoutez une ligne comme celle-ci au fichier :
options lockd nlm_udpport=32768 nlm_tcpport=32768
Cette ligne impose à lockd d'utiliser le port 32768 pour udp et tcp Si vous n'utilisez pas les modules chargeables ou si vous avez compilé lockd dans le noyau au lieu de le construire comme module alors vous aurez besoin de lui passer une option sur la ligne de boot du noyau. Comme ceci :
vmlinuz 3 root=/dev/hda1 lockd.udpport=32768 lockd.tcpport=32768
Le numéro des ports n'a pas besoin d'être le même, mais cela ajouterai une complication inutile s'ils étaient différents. Si vous utilisez les quotas et rpc.quotad pour les rendre visibles via nfs, vous devez en tenir compte pour le pare feu. Il existe deux arborescences sources de rpc.rquotad. L'une est maintenue dans l'arborescence nfs-utils, l'autre dans l'arborescence quota-tools. Elles n'opèrent pas de la même façon. Celle fournie avec nfs-utils autorise l'attribution d'un port au démon avec l'option -p; l'autre non. Consultez la documentation de votre distribution pour savoir laquelle vous possédez.
Décrivons maintenant un réseau et la configuration du pare feu pour protéger le serveur nfs. Notre serveur nfs est 192.168.0.42; notre client est 192.168.0.45 uniquement. Comme dans l'exemple ci-dessus, statd est démarré, ainsi il n'est relié qu'au port 32765 pour les requêtes entrantes et il doit répondre sur le port 32766. mountd est forcé sur le port 32767. Les paramètres du module de lockd ont été réglés pour le port 32768. nfsd est bien sûr sur le port 2049 et portmapper sur le port 111. Nous utilisons les quotas.
L'utilisation de IPCHAINS, un pare feu simple pourrait ressembler à ceci :
ipchains -A input -f -j ACCEPT -s 192.168.0.45 ipchains -A input -s 192.168.0.45 -d 0/0 32765:32768 -p 6 -j ACCEPT ipchains -A input -s 192.168.0.45 -d 0/0 32765:32768 -p 17 -j ACCEPT ipchains -A input -s 192.168.0.45 -d 0/0 2049 -p 17 -j ACCEPT ipchains -A input -s 192.168.0.45 -d 0/0 2049 -p 6 -j ACCEPT ipchains -A input -s 192.168.0.45 -d 0/0 111 -p 6 -j ACCEPT ipchains -A input -s 192.168.0.45 -d 0/0 111 -p 17 -j ACCEPT ipchains -A input -s 0/0 -d 0/0 -p 6 -j DENY -y -l ipchains -A input -s 0/0 -d 0/0 -p 17 -j DENY -l
Les commandes équivalentes pour netfilter sont :
iptables -A INPUT -f -j ACCEPT -s 192.168.0.45 iptables -A INPUT -s 192.168.0.45 -d 0/0 32765:32768 -p 6 -j ACCEPT iptables -A INPUT -s 192.168.0.45 -d 0/0 32765:32768 -p 17 -j ACCEPT iptables -A INPUT -s 192.168.0.45 -d 0/0 2049 -p 17 -j ACCEPT iptables -A INPUT -s 192.168.0.45 -d 0/0 2049 -p 6 -j ACCEPT iptables -A INPUT -s 192.168.0.45 -d 0/0 111 -p 6 -j ACCEPT iptables -A INPUT -s 192.168.0.45 -d 0/0 111 -p 17 -j ACCEPT iptables -A INPUT -s 0/0 -d 0/0 -p 6 -j DENY --syn --log-level 5 iptables -A INPUT -s 0/0 -d 0/0 -p 17 -j DENY --log-level 5
La première ligne dit d'accepter tous les fragments de paquet (excepté le premier fragment de paquet qui sera traité comme un paquet normal). En théorie, aucun paquet ne peut passer au travers avant d'être ré-assemblé, et il ne sera pas ré-assemblé tant que le premier fragment de paquet n'est pas passé. Bien sûr il existe des attaques qui sont générées en surchargeant une machine avec des fragments de paquets. Mais NFS ne fonctionnera pas correctement à moins que vous ne laissiez passer les fragments. Voir la section 7 "Dépannage" pour plus de détails.
Les autres lignes permettent des connexions spécifiques depuis n'importe quel port du client vers les ports que nous avons rendus disponibles sur le serveur. Cela signifie que si, disons, 192.158.0.46 tente de contacter le serveur NFS, il ne pourra pas se monter ni voir quels montages sont disponibles. Avec les nouvelles possibilités d'attribution des ports il est de toute évidence plus facile de contrôler quels hôtes sont autorisés à monter vos partages NFS. Il faut préciser que le serveur NFS n'est pas un protocole crypté et n'importe qui sur le même réseau physique peut capter le trafic et ré-assembler les informations qui y transitent.
Tunnelisation de NFS au travers de SSH
Une méthode pour crypter le trafic NFS sur un réseau est d'utiliser les possibilités de redirection des ports de ssh. Cependant, comme nous allons le voir, cela présente un inconvénient sérieux si vous ne faites pas une totale confiance aux utilisateurs en local du serveur. La première étape est d'exporter les fichiers vers le localhost. Par exemple, pour exporter la partition /home, entrer cela dans /etc/exports :
/home 127.0.0.1(rw)
La deuxième étape consiste à utiliser ssh pour rediriger les ports. Par exemple, ssh peut dire au serveur de rediriger un port du client vers n'importe quel port sur n'importe quelle machine. Supposons, comme dans le précédent chapitre, que notre serveur est 192.168.0.42, et que nous avons associé mountd au port 32767 en utilisant l'argument -p 32767. Alors sur le client, on tape :
# ssh root@192.168.0.42 -L 250:localhost:2049 -f sleep 60m # ssh root@192.168.0.42 -L 251:localhost:32767 -f sleep 60m
La commande ci-dessus commande à ssh sur le client de prendre toutes les requêtes dirigées vers le port 250 du client et de les rediriger, premièrement via sshd sur le serveur, puis sur le port 2049 du serveur. La seconde ligne commande une redirection similaire entre les requêtes dirigées vers le port 251 du client et le port 32767 du serveur. localhost se réfère au serveur, ceci dit, la redirection sera faite vers le serveur lui-même.
Le port aurait pu sinon avoir été configuré pour rediriger vers toute autre machine, et les requêtes auraient donné l'impression au monde extérieur de provenir du serveur. Ainsi, les requêtes apparaîtront à NFSD sur le serveur comme si elles venaient du serveur lui-même. Notez que pour obtenir une association sur le client avec un numéro de port inférieur à 1024, nous devons exécuter cette commande sous root sur le client. Faire cela sera nécessaire si nous avons exporté les systèmes de fichiers avec l'option par défaut secure.
Enfin, nous faisons appel à une astuce avec la dernière option, -f sleep 60m. Normalement, lorsqu'on utilise ssh, même avec l'option -L, nous ouvrons un shell sur la machine distante. Mais au lieu de cela, nous voulons simplement que le port indiqué ensuite s'exécute en arrière plan afin qu'on récupère au plus vite notre shell sur le client. Aussi, nous disons à ssh d'exécuter une commande qui le fait dormir pendant 60 minutes, en arrière plan sur le serveur. Cela redirigera le port pendant 60 minutes jusqu'à ce qu'il obtienne une connexion; à ce moment, le port continuera à être redirigé jusqu'à ce que la connexion meure ou que les 60 minutes soient atteintes, suivant ce qui se produira en premier. La commande ci-dessus peut être mise dans les scripts de démarrage sur le client, sitôt après le démarrage du réseau.
Ensuite nous devons monter le système de fichiers sur le client. Pour cela, nous disons au client de monter un système de fichiers sur le localhost, mais à un port différent de l'habituel 2049. Une entrée dans /etc/fstab ressemble à :
localhost:/home /mnt/home nfs rw,hard,intr,port=250,mountport=251 0 0
Après avoir fait cela, on peut comprendre pourquoi cette entrée est non sécurisante si nous avons des utilisateurs ordinaires qui peuvent se connecter localement au serveur. S'ils le peuvent, rien ne les empêche de faire ce que nous avons fait et en utilisant ssh de rediriger un port privilégié sur leur propre machine cliente (où ils sont root en toute légalité) vers les ports 2049 et 32767 sur le serveur. Ainsi, tout utilisateur ordinaire sur le serveur peut monter le système de fichiers sur le client avec les mêmes droits que root. Si vous utilisez un serveur NFS qui ne permet pas aux utilisateurs ordinaires de s'y connecter, et que vous souhaitez utiliser cette méthode, il y a deux problèmes supplémentaires : Premièrement les données vont du client vers le serveur via sshd; vous devez donc laisser le port 22 (où sshd écoute) ouvert à votre client sur le pare feu. Cependant, vous ne devez pas laisser les autres ports, tels que 2049 et 32767, ouverts. Deuxièmement, le verrouillage des fichiers ne fonctionnera plus. Il n'est pas possible de demander à statd ou au gestionnaire du verrouillage de faire des requêtes sur un port particulier pour un montage particulier; cependant, toute requête de verrouillage provoquera la connexion de statd sur statd sur localhost, c'est à dire lui-même, et il échouera en donnant un message d'erreur. Toute tentative de corriger cela nécessiterait une large réécriture de NFS.
Il est aussi possible d'utiliser IPSEC pour crypter le trafic réseau entre le client et le serveur, sans compromettre la sécurité locale sur le serveur, cela ne sera pas traité ici. Voir FreeS/Wan pour plus de détails.
Récapitulatif
Si vous utilisez hosts.allow, hosts.deny, root_squash, nosuid et des ports de configuration privilégiées avec le logiciel portmapper/NFS, vous évitez beaucoup des bogues connus de NFS et pouvez presque vous sentir en sécurité. Mais même après cela, si un intrus accède à votre réseau, il peut faire apparaître d'étranges commandes dans votre .forward ou lire votre courrier si /home ou /var/mail est exporté via NFS. Pour la même raison, vous ne devriez jamais accéder à votre clé privée de logiciel de chiffrement via NFS. NFS et portmapper forment un sous système complexe et il n'est donc pas impossible que de nouveaux bogues soient découverts soit dans la conception de base soit dans l'implémentation que nous utilisons.. Il peut même y avoir des failles connues maintenant et dont quelqu'un abuse. Mais c'est la vie.
Dépannage
Ce chapitre essaye d'être un guide pas à pas de ce qu'il faut faire quand les choses vont mal. Habituellement les problèmes se montrent d'abord du coté client, aussi, le diagnostic commencera par là.
Impossible de voir les fichiers d'un système de fichiers monté
Premièrement, vérifier que le système de fichiers est bien monté. Il existe plusieurs façons de le faire. Le plus fiable est de regarder le fichier /proc/mounts, qui liste tous les fichiers montés et donne des détails à leur sujet. Si cela ne fonctionne pas (par exemple le système de fichiers /proc n'est pas compilé dans le kernel), vous pouvez taper mount -f mais vous aurez moins d'informations. Si le système de fichiers est bien monté, alors vous avez peut-être monté un autre système de fichiers par dessus (auquel cas vous devrez démonter et remonter les deux volumes), ou vous avez peut-être exporté le système de fichiers sur le serveur avant qu'il n'y soit monté, auquel cas NFS exporte le point de montage (dans ce cas vous devez redémarrer NFS sur le serveur).
Si le système de fichiers n'est pas monté, tentez de le monter, si cela ne marche pas, voir le chapitre 7.3.
Impossible d'accéder aux fichiers
Ceci habituellement signifie que le client est incapable de communiquer avec le serveur. Voir le chapitre 7.3 - b.
Impossible de monter un système de fichiers
Il existe deux types d'erreurs communes indiquées par mount quand il est incapable de monter un volume. Ils sont :
1 - Echec, raison donnée par le serveur : Permission denied (permission refusée)
Cela signifie que le serveur ne reconnaît pas que vous avez accès au volume.
- Vérifiez le fichier /etc/exports et assurez vous que le volume est exporté et que le client a les droits d'accès nécessaires. Par exemple, si un client n'a que les droits de lecture seule alors vous devez monter le volume avec l'option ro plutôt que rw.
- Assurez vous d'avoir dit à NFS d'enregistrer les changements effectués dans /etc/exports depuis le démarrage de nfsd, en exécutant la commande exportfs . Soyez certain de taper exportfs -ra pour être tout à fait sûr que les exports ont été relus.
- vérifiez le fichier /proc/fs/nfs/exports et assurez vous que le volume et le client sont correctement mentionnés. (vous pouvez aussi regarder le fichier /var/lib/nfs/xtab pour avoir une liste non abrégée de la façon dont toutes les options d'export actives sont établies). S'ils ne le sont pas, alors vous n'avez pas exporté correctement, s'ils le sont, assurez vous que le serveur reconnaît le client comme étant la machine à laquelle vous pensez. Par exemple, vous pouvez avoir une entrée périmée pour le client dans /etc/hosts qui trompe le serveur, ou vous pouvez ne pas avoir donné l'adresse complète du client et la résolution des noms peut aboutir sur une machine d'un autre domaine. Une astuce consiste à se connecter au serveur depuis le client via ssh ou telnet; si alors vous tapez who, une des listes est votre session avec le nom du client tel que le voit le serveur. Essayez d'utiliser ce nom de machine dans l'entrée du fichier /etc/exports. Enfin, essayez, depuis le serveur, la commande ping avec l'adresse du client, et depuis le client avec l'adresse du serveur. Si cela ne fonctionne pas, ou si des paquets sont perdus, vous avez sans doute un problème de réseau bas niveau.
- Il n'est pas possible d'exporter à la fois un répertoire et ses enfants (par exemple /usr et /usr/local). Vous devez exporter le répertoire parent avec les permissions nécessaires, et tous ses sous répertoires peuvent alors être montés avec ces mêmes permissions.
2 RPC: Program Not Registered (ou une autre erreur de "RPC")
Ceci signifie que le client ne détecte pas l'exécution de NFS sur le serveur. Cela peut être pour plusieurs raisons :
- Premièrement, vérifier que NFS est en cours d'exécution sur le serveur en tapant rpcinfo -p sur le serveur. Vous devriez voir quelque chose comme cela :
program vers proto port
100000 2 tcp 111 portmapper
100000 2 udp 111 portmapper
100011 1 udp 749 rquotad
100011 2 udp 749 rquotad
100005 1 udp 759 mountd
100005 1 tcp 761 mountd
100005 2 udp 764 mountd
100005 2 tcp 766 mountd
100005 3 udp 769 mountd
100005 3 tcp 771 mountd
100003 2 udp 2049 nfs
100003 3 udp 2049 nfs
300019 1 tcp 830 amd
300019 1 udp 831 amd
100024 1 udp 944 status
100024 1 tcp 946 status
100021 1 udp 1042 nlockmgr
100021 3 udp 1042 nlockmgr
100021 4 udp 1042 nlockmgr
100021 1 tcp 1629 nlockmgr
100021 3 tcp 1629 nlockmgr
100021 4 tcp 1629 nlockmgr
Cela nous dit que nous avons NFS versions 2 et 3, rpc.statd version 1, network lock manager (le nom du service pour rpc.lockd) versions 1, 3, et 4. Il y a aussi différents services de cités suivant que NFS est porté par TCP ou UDP. UDP est habituellement (mais pas toujours) le choix par défaut, à moins que TCP soit explicitement requis.
Si vous ne voyez pas à minima portmapper, nfs, et mountd, vous devez redémarrer NFS. Si vous ne pouvez pas redémarrer avec succès, procéder suivant le chapitre 7.9.
- Maintenant assurez vous de voir le serveur depuis le client. Sur le client, tapez rpcinfo -pserver où server est le nom DNS ou l'adresse IP du serveur. Si vous obtenez une liste, alors assurez vous que le type de montage que vous tentez de réaliser est supporté. Par exemple, si vous essayez de monter en utilisant la version 3 de NFS, assurez vous que la version 3 est listée; si vous essayez de monter en utilisant NFS porté par TCP, assurez vous qu'il est mentionné. Tapez man rpcinfo pour avoir plus d'informations sur l'interprétation de la sortie. Si le type de montage que vous tentez d'utiliser n'est pas listé, essayez un type de montage différent.
Si vous obtenez l'erreur No Remote Programs Registered, vous devez alors vérifier les fichiers /etc/hosts.allow et /etc/hosts.deny sur le serveur et vous assurer que le client a bien les autorisations d'accès. Encore une fois, si les entrées apparaissent correctes, vérifiez /etc/hosts sur le serveur DNS pour vous assurer que la machine est correctement listée et vérifiez que vous pouvez contacter le serveur par la commande ping depuis le client. Consultez les messages dans les journaux d'erreurs. Les erreurs d'authentification en raison d'entrées erronées dans le fichier /etc/hosts.allow apparaissent habituellement dans /var/log/messages mais peuvent apparaître ailleurs suivant la configuration des journaux. Les pages man de syslog peuvent vous aider à comprendre comment les journaux sont configurés. Enfin, certains vieux systèmes d'exploitation peuvent mal se comporter quand les routes entre les deux machines sont asymétriques. Essayez de taper tracepath [server] depuis le client et regardez si le mot "asymétrique" apparaît quelque part dans la sortie. Si c'est le cas, cela peut provoquer la perte de paquets. Cependant, les routes asymétriques ne sont pas un problème pour les distributions récentes de Linux.
Si vous obtenez l'erreur Remote system error - No route to host, mais que vous pouvez joindre correctement le serveur avec ping, vous êtes alors victime du zèle d'un pare feu. Vérifiez tous les pare feu, sur le serveur et aussi sur tous les routeurs entre le serveur et le client. Vous trouverez de l'aide en consultant les pages man de ipchains, netfilter, et ipfwadm, ainsi que IPChains-HOWTO et Firewall-HOWTO
Je n'ai pas la permission d'accéder aux fichiers du volume monté
Cela peut être du à l'un des deux problèmes suivants. Si c'est un problème de permission d'écriture, vérifier les options d'export sur le serveur en examinant le fichier /proc/fs/nfs/exports pour vous assurer que le système de fichiers n'est pas exporté en écriture seule. Si c'est le cas, vous devez le ré-exporter en lecture/écriture (ne pas oublier d'exécuter exportfs -ra après l'édition de /etc/exports ). Vérifier aussi /proc/mounts pour vous assurer que le volume est monté en lecture/écriture (bien que s'il est monté en lecture seule, vous devriez avoir un message d'erreur plus spécifique). Si ce n'est pas le cas, alors vous devez refaire le montage avec l'option rw.
Le second problème est en relation avec le mappage des noms d'utilisateurs, et est différent suivant que vous êtes sous root ou en utilisateur non root. Si vous êtes non root, alors les noms d'utilisateurs peuvent ne pas être synchronisés entre le client et le serveur. Tapez id [user] sur le client et sur le serveur et vérifier que le numéro UID est le même. S'ils diffèrent, vous avez un problème avec NIS, NIS+, rsync, ou tout autre système que vous utilisez pour synchroniser les noms d'utilisateurs. Vérifiez aussi les noms de groupes pour vous assurer qu'ils correspondent aussi. Contrôlez aussi que vous n'exportez pas avec l'option all_squash. Si les noms d'utilisateurs correspondent, alors l'utilisateur a des problèmes de permission plus généraux non liés à NFS.
Si vous êtes root, alors vous n'exportez probablement pas avec l'option no_root_squash; vérifiez /proc/fs/nfs/exports ou /var/lib/nfs/xtab sur le serveur et assurez vous que l'option est indiquée. En général, être capable sous root d'écrire sur le serveur NFS est une mauvaise idée à moins d'un besoin urgent, c'est pourquoi Linux NFS l'interdit par défaut. Voir le chapitre 6 "Sécurité et NFS " pour plus de détails.
Si vous avez l'option root_squash, que vous désirez garder et que vous essayez seulement de devenir root pour avoir les mêmes permissions sur les fichiers que l'utilisateur nobody aurait, alors souvenez vous que c'est le serveur qui détermine quel UID est attribué à root. Par défaut, le serveur utilise les UID et GID de nobody présents dans le fichier /etc/passwd, mais il est possible de passer outre avec les options anonuid et anongid présentes dans le fichier /etc/exports. Assurez vous que le client et le serveur sont en accord au sujet de l'UID attribué à nobody.
Quand je transfère des fichiers très volumineux, NFS sature le CPU sur le serveur et il s'arrête brutalement
Ceci est un problème avec la fonction fsync() dans les noyaux 2.2 qui provoque l'accumulation de toutes les requêtes de synchronisation sur le disque, il en résulte un temps d'écriture qui est le carré de la taille du fichier. Si vous le pouvez, évoluez vers le noyau 2.4. Aussi, exporter avec l'option no_wdelay oblige le programme d'utiliser o_sync() à la place, ce qui peut s'avérer plus rapide.
Messages étranges d'erreurs ou dans les journaux
- Messages au format suivant :
Jan 7 09:15:29 server kernel: fh_verify: mail/guest permission failure, acc=4, error=13 Jan 7 09:23:51 server kernel: fh_verify: ekonomi/test permission failure, acc=4, error=13
Cela arrive quand une opération setattr de NFS est tentée sur un fichier dont vous n'avez pas les droits d'écriture. Le message est anodin.
- Le message suivant apparaît fréquemment dans les journaux :
kernel: nfs: server server.domain.name not responding, still trying kernel: nfs: task 10754 can't get a request slot kernel: nfs: server server.domain.name OK
Le message "can't get a request slot" (NdT : ne peut obtenir le créneau requis) signifie que le code RPC du côté client a détecté un grand nombre de dépassements de temps (peut-être dus à une congestion du réseau ou à une surcharge du serveur), et rejette de plus en plus de requêtes simultanément en souffrance dans le but d'alléger la charge. La cause de ces messages est essentiellement une piètre performance. Voir le chapitre 5 "Optimisation des performances de NFS" pour plus de détails.
- Après un montage le message suivant apparaît sur le client :
nfs warning: mount version older than kernel
(NdT : avertissement NFS : version de mount plus ancienne que le noyau) :
Il signifie ce qui est dit Vous devriez mettre à jour votre paquetage mount et/ou am-utils. ( Si la mise à jour est un problème, vous pouvez seulement les recompiler pour que les nouvelles fonctionnalités du noyau soient reconnues)
- Erreurs concernant lockd dans le journal de démarrage/arrêt
nfslock: rpc.lockd startup failed
Ils sont inoffensifs. Les anciennes versions de rpc.lockd avaient besoin d'être démarrées à la main, mais les nouvelles sont démarrées automatiquement par nfsd. De nombreux scripts de démarrage essayent encore de démarrer lockd à la main, au cas ou ce serait nécessaire. Vous pouvez modifier votre script de démarrage si vous ne voulez plus voir le message.
- Le message suivant apparaît dans les journaux :
kmem_create: forcing size word alignment - nfs_fh
Ceci est la conséquence de la manipulation d'un fichier en 16 bits au lieu d'un multiple de 32 bits, qui fait grimacer le noyau. C'est inoffensif.
Les permissions réélles ne correspondent pas à ce qui est dans /etc/exports
/etc/exports est très sensible aux caractères "espace", aussi les instructions suivantes ne sont pas les mêmes :
/export/dir hostname(rw,no_root_squash) /export/dir hostname (rw,no_root_squash)
La première garantit que hostname aura un accès en lecture/écriture à /export/dir sans modifier les privilèges root (no_root-squash). La seconde garantit que hostname aura un accès en lecture/écriture en écrasant les droits root et elle garantit aussi à tous les autres un accès en lecture/écriture sans modifier les privilèges root. Formidable non ?
Comportement farfelu et non fiable
Des commandes simples comme ls fonctionnent, mais tout ce qui déplace une grande quantité d'informations provoque le blocage du point de montage Cela peut être du à deux problèmes :
- Cela peut arriver si ipchains est en service sur le serveur et/ou sur le client et vous n'autorisez pas les paquets fragmentés à traverser la chaîne de traitement. Autorisez les fragments depuis l'hôte distant et le fonctionnement reprendra. Voir le chapitre 5 "Optimisation des performances de NFS" pour plus de détails sur la mise en œuvre.
- Vous utilisez peut-être dans les options de montage, des valeurs de rsize et wsize plus grandes que ce que le serveur supporte. Essayez de les réduire à 1024 et voyez si le problème est résolu. Si c'est le cas, alors augmentez les progressivement jusqu'à une valeur raisonnable.
nfsd ne démarre pas
Vérifiez le fichier /etc/exports et assurez vous que root a les permissions de lecture. Vérifiez les binaires et assurez vous qu'ils sont exécutables. Assurez vous aussi que le noyau a été compilé avec le support du serveur NFS. Vous pouvez avoir besoin de réinstaller les binaires si aucunes de ces idées ne sont efficaces.
Corruption de fichier lors de l'utilisation de plusieurs clients
Si un fichier a été modifié moins d'une seconde après la modification précédente tout en conservant la même taille, il continuera à générer le même numéro d'inode. A cause de cela, les répétitions de lectures et d'écritures sur un même fichier par de nombreux clients peuvent provoquer la corruption du fichier. Résoudre ce bogue nécessite de profonds changements dans la couche du système de fichiers, c'est donc pour la prochaine version.


