lundi, mars 21, 2011

Serveur NFS v4 avec FreeBSD

NFS v4 possède quelques avantages bien sympa: En plus de la possibilité de s'appuyer sur kerberos, il utilise un seul port TCP (très pratique lorsqu'il se trouve derrière un firewall).
Cet exemple montre sa mise en place, et les problèmes rencontrés pour un fonctionnement sans l'authentification kerberos avec FreeBSD (8.1 et 8.2).
On commence par lire nfsv4(4), qui nous indique que pour activer le serveur NFS v4 il faut:

1. Ajouter 3 lignes dans le /etc/rc.conf:
nfs_server_enable="YES"
nfsv4_server_enable="YES"
nfsuserd_enable="YES"

2. Créer un fichier nfs-stablerestart (en root):

install -o root -g wheel -m 600 /dev/null /var/db/nfs-stablerestart

Maintenant on passe à la lecture du exports(5) qui, pour NFS v4 est un peu plus complexe.
Mon but est de partager le dossier /home/olivier en lecture seule, le fichier exports se résume donc à 2 lignes:
V4: /
/home/olivier -ro 127.0.0.1

Puis je lance les services:
/etc/rc.d/nfsd start
Starting mountd.
Starting nfsd.

/etc/rc.d/nfsuserd start
Starting nfsuserd.


Aucun message d'erreur, ça semble bon, maintenant affichons la liste des exports:
showmount -e
Exports list on localhost:

Rien :-(
Et aucun message dans les logs indiquant une erreur dans le fichier exports.

On va quand même essayer:
mount -o nfsv4 localhost:/home/olivier /mnt/
nfsv4 err=10029
mount_nfs: /mnt, : Input/output error

Le message d'erreur le plus intéressant ici est le «nfsv4 err=10029», je n'ai pas trouvé grand chose sur le net concernant ce message, sauf une petite note dans le draft nfsv4:

NFS4ERR_SYMLINK (Error Code 10029)
The current filehandle designates a symbolic link when the current operation does not allow a symbolic link as the target.

Je n'avais pas fait attention à un détail du exports(5):
«The pathnames must not have any symbolic links in them»

Et sur FreeBSD le dossier /home est un lien symbolique qui pointe sur /usr/home.
On corrige donc le fichier /etc/exports:
V4: /
/usr/home/olivier -ro 127.0.0.1

Et on demande à mountd de charger ce nouveau fichier:
/etc/rc.d/mountd reload

Vérifions si c'est mieux 
showmount -e
Exports list on localhost:
/usr/home/olivier                  127.0.0.1

Cool, maintenant je vais pouvoir le monter (en localhost pour débuter):
mount -o nfsv4 localhost:/usr/home/olivier /mnt/
mount | grep olivier
localhost:/usr/home/olivier on /mnt (newnfs)


Parfait, maintenant on liste les fichiers sur du dossier /mnt
ls /mnt/
ls: /mnt/: Input/output error

Bon, ça ne fonctionne toujours pas :-(
Qu'est que ce bordel ?
Voici la commande qui donne un indice sur ce problème:
netstat -a | grep nfsd
tcp6       0      0 localhost.nfsd         localhost.18082        ESTABLISHED
tcp6       0      0 localhost.18082        localhost.nfsd         ESTABLISHED
tcp6       0      0 localhost.621          localhost.nfsd         TIME_WAIT
tcp6       0      0 *.nfsd                 *.*                    LISTEN
tcp4       0      0 *.nfsd                 *.*                    LISTEN
udp6       0      0 *.nfsd                 *.*
udp4       0      0 *.nfsd                 *.*

Et oui, je n'ai autorisé que l'IP 127.0.0.1 à accéder à mon partage dans mon /etc/exports, et la commande mount localhost a utilisé l'IPv6 localhost (::1) pour s'y connecter.
On va donc forcer un montage en utilisant la pile IPv4:
umount /mnt/
mount -t nfs -o nfsv4 127.0.0.1:/usr/home/olivier /mnt/
ls /mnt
.complete                           .mailrc                                
.cshrc                              .profile                                   
.history                            .rhosts                              
.lesshst                            .shrc                                                    
.lftp                               .ssh                                
.login                              .viminfo                            
.login_conf                         .vimrc                              

Enfin, cela fonctionne en local :-)
Comme je veux le monter aussi en IPv6, j'ajoute donc ::1 à ma liste d'IP autorisées:
V4: /
/usr/home/olivier -ro 127.0.0.1 ::1

Maintenant que le montage local IPv4/IPv6 fonctionne, on édite le /etc/exports pour y autoriser les subnets du LAN:
V4: /

/usr/home/olivier -ro -network 2a01:e35:aaaa:aaaa::/64
/usr/home/olivier -ro -network 192.168.100.0

Puis on recharge mountd et vérifie que le fichier exports a été correctement interprété:
/etc/rc.d/mountd reload
showmount -e
Exports list on localhost:
/usr/home/olivier                  2a01:e35:aaaa:aaaa:: 192.168.100.0

Note concernant un client sous Linux, la syntaxe de la commande mount est la suivante:
mount -t nfs4 server-name:/usr/home/olivier/ /mnt

Donc, à noter pour la configuration NFS v4:
  1. Ne pas oublier de créer le fichier /var/db/nfs-stablerestart
  2. Ne pas déclarer de chemin utilisant des liens symboliques dans le fichier exports
  3. Si showmount -e n'indique rien suite au rechargement de mountd, ce n'est pas la peine de continuer
  4. Attention aux doubles piles IPv4/IPv6, n'oubliez pas de déclarer aussi les IPv6 dans votre exports
  5. Ce n'est pas parce que le montage s'effectue que vous êtes autorisé

Aucun commentaire: