Ici je détaille la création d’un partage avec authentification via Kerberos.
- Serveur
- système : Gentoo
- hostname : max-serveur
- domain : lan
- Kerberos « realm » : LAN
- Client
- système : Archlinux
- hostname : laptop
- domain : lan
- Kerberos « realm » : LAN
- utilisateur/login : max
Les démon nécessaire pour NFSv4 sont :
- sur le serveur :
- rpc.nfsd : le démon principal
- rpc.svcgssd : pour Kerberos
- rpc.idmapd : fait correspondre les utilisateurs du système client avec ceux du serveur. Voir la section dédiée.
- rpc.mountd : NFSv4 n’a normalement plus besoins de rpc.mountd. Cependant, il s’avère que dans l’implémentation de NFSv4 utilisée sous Gentoo, rpc.mountd est tout de même necessaire. C’est expliqué sur la mailling list nfsv4 de l’IETF.
- sur le client :
Sources :
- Expériences personnels
- tutorial de l’université de Munich
- tutotrial CentOS
Configuration
Kerberos
Voir la page dédiée.
Il faut que chaque machine ai un fqdn et puisse résoudre ceux des autres (et faire des requête inverse).
BIND
TODO a écrire
bind doit être installé
hosts
Si vous n’avez pas de serveur DNS administrable sur votre réseau et que votre architecture est simple, vous pouvez utiliser les fichiers /etc/hosts.
127.0.0.1 localhost
::1 localhost
192.168.1.102 server.lan server
192.168.1.100 laptop.lan laptop
Définissez les entrés correspondant au client dans le /etc/hosts du server et vice-versa.
Principals
Création des « principals », ces opérations peuvent être faite sur le client ou le serveur, du moment qu’on est dans un kadmin c’est pareille.
root@server # kadmin
Authenticating as principal root/admin@LAN with password.
Password for root/admin@LAN:
kadmin: addprinc -randkey nfs/server.lan
WARNING: no policy specified for nfs/server.lan@LAN; defaulting to no policy
Principal "nfs/server.lan@LAN" created.
kadmin: addprinc -randkey nfs/laptop.lan
WARNING: no policy specified for nfs/laptop.lan@LAN; defaulting to no policy
Principal "nfs/laptop.lan@LAN" created.
kadmin: addprinc max
WARNING: no policy specified for max@LAN; defaulting to no policy
Enter password for principal "max@LAN":
Re-enter password for principal "max@LAN":
Principal "max@LAN" created.
kadmin: quit
Dans l’ordre :
- création du « principal »
nfs/server.lan@LANpour le serveur NFS - création du « principal »
nfs/laptop.lan@LANpour la machine cliente - création du « principal »
max@LANpour l’utilisateur du partage sur la machine cliente
Sur le serveur, enregistrement de la clé du principal nfs/server.lan@LAN dans le « keytab »
root@server # kadmin
Authenticating as principal root/admin@LAN with password.
Password for root/admin@LAN:
kadmin: ktadd nfs/server.lan
Entry for principal nfs/server.lan with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
Entry for principal nfs/server.lan with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
Entry for principal nfs/server.lan with kvno 2, encryption type des3-cbc-sha1 added to keytab FILE:/etc/krb5.keytab.
Entry for principal nfs/server.lan with kvno 2, encryption type arcfour-hmac added to keytab FILE:/etc/krb5.keytab.
kadmin: quit
Sur le client, enregistrement de la clé du principal nfs/laptop.lan@LAN dans le « keytab »
root@laptop # kadmin
Authenticating as principal root/admin@LAN with password.
Password for root/admin@LAN:
kadmin: ktadd nfs/laptop.lan
Entry for principal nfs/laptop.lan with kvno 3, encryption type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
Entry for principal nfs/laptop.lan with kvno 3, encryption type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
Entry for principal nfs/laptop.lan with kvno 3, encryption type des3-cbc-sha1 added to keytab FILE:/etc/krb5.keytab.
Entry for principal nfs/laptop.lan with kvno 3, encryption type arcfour-hmac added to keytab FILE:/etc/krb5.keytab.
kadmin: quit
Serveur
Noyau
Vérifier les options de compilation du noyau. Au minimum :
.config - Linux/x86 4.2.5-gentoo Kernel Configuration
> File systems > Network File Systems qqqqqqqqqqqqqqqqqqqqqqqqqqqq
lqqqqqqqqqqqqqqqqqqqqqq Network File Systems qqqqqqqqqqqqqqqqqqqqk
x … x
x lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x
x x --- Network File Systems x x
x x … x x
x x [*] NFS server support x x
x x … x x
x x [*] NFS server support for NFS version 4 x x
x x … x x
x x [*] Secure RPC: Kerberos V mechanism x x
x x x x
x mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj x
tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqu
x <Select> < Exit > < Help > < Save > < Load > x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj
Sur certain tuto il est indiqué que « Secure RPC: Kerberos V mechanism » doit être compilé comme module noyau sinon le couplage NFS↔Kerberos ne fonctionne pas. Ce n’est pas le cas sur mon installation. L’élément est compilé en dure et tous fonctionne parfaitement.
Source : wiki Gentoo
idmapd
Les paramètre important du fichier /etc/idmapd.conf sont Domain et Local-Realms.
[General]
Domain = lan
Local-Realms = LAN
[Mapping]
Nobody-User = nobody
Nobody-Group = nobody
[Translation]
Method = nsswitch
[Static]
[UMICH_SCHEMA]
LDAP_server = ldap-server.local.domain.edu
LDAP_base = dc=local,dc=domain,dc=edu
La présence de idmapd ne signifie pas que les noms, uid et gid peuvent être différent entre le serveur et le client. Avec Kerberos on ne se base que sur les noms des utilisateurs, il faut donc que les noms soit identique sur le client et le serveur. Sans Kerberos on se base en plus sur les uid et gid, il faut donc que les noms soit identique mais aussi les uid/gid.
L’utilisation de montage NFS implique l’utilisation de deux niveau/type d’opérations.
Il y a les opérations RPC et les opérations NFS.
Au niveau NFS (haut niveau), les opérations qui ont besoin d’identifier un utilisateur utilise sont nom, il n’y a pas de notion de uid ou gid.
Au niveau RPC (bas niveau) ça dépend.
Si on se sert de Kerberos c’est le nom de l’utilisateur qui est utilisé (en fait c’est le principal… mais celui-ci dépend du nom), c’est pourquoi l’utilisateur à besoin d’un ticket pour naviguer dans les répertoires monté en NFS.
Si on ne s’en sert pas (on se sert alors donc de auth_unix) ce sont l’uid et les gid qui sont utilisé.
Les accès (lecture, écriture, exécution) au fichier et dossier sont assuré au niveau RPC. En revanche, la gestion/affichage des ACL, des owner/group des fichier/dossier est fait au niveau NFS.
Exemple d’Alessio Gaeta, sans Kerberos. Pour faire simple, l’affichage est géré au niveau NFS, on à donc une correspondance au niveau des nom. Mais au niveau de l’éxécution des opération, les manipulation de fichier, les uid sont utilisé. « valentina client » devient donc l’équivalent de « alberto server » même si ça ne correspond pas à ce qui est afficher dans point de montage du client.
root@server # id alberto
uid=1002(alberto) …
root@server # id valentina
uid=1005(valentina) …
root@server # ls -l
… alberto … alberto-dir
… valentina … valentina-dir
root@server # ls -n
… 1002 … alberto-dir
… 1005 … valentina-dir
root@client # id alberto
id: alberto: no such user
root@client # id valentina
uid=1002(valentina) …
valentina@client % ls -l
… nobody … alberto-dir
… valentina … valentina-dir
valentina@client % ls -n
… 65534 … alberto-dir
… 1002 … valentina-dir
valentina@client % ls valentina-dir
ls: cannot open directory valentina-dir: Permission denied
valentina@client % ls -l alberto-dir
… nobody … file1
… nobody … file2
valentina@client % ls -n alberto-dir
… 65534 … file1
… 65534 … file2
valentina@client % touch valentina-dir/newfile
touch: cannot touch 'valentina-dir/newfile': Permission denied
valentina@client % touch alberto-dir/newfile
root@server # ls -l alberto-dir
… alberto … file1
… alberto … file2
… alberto … newfile
root@server # ls -n alberto-dir
… 1002 … file1
… 1002 … file2
… 1002 … newfile
TODO : faire la même chose avec kerberos (pour l’instant mes utilisateurs on les même uid/gid)
Démons
Avant de démarrer les démon vérifié que le répertoire dont le nom est contenu dans le fichier /proc/fs/nfsd/nfsv4recoverydir est bien présent :
root@server # cat /proc/fs/nfsd/nfsv4recoverydir
/var/lib/nfs/v4recovery
root@server # mkdir -p /var/lib/nfs/v4recovery
Sans cela vous risquez d’obtenir une erreur :
NFSD: Unable to create client record on stable storage: -110
systemd
Pour ceux qui ont fait le choix d’utiliser systemd.
Il faut modifier le fichier de configuration /etc/conf.d/nfs.
Noté que j’ai du changer les noms des variables par rapport à la version OpenRC.
root@server # grep -v -e '^#' -e '^$' /etc/conf.d/nfs
RPCNFSDARGS="--no-udp -N 2 -N 3 3"
RPCMOUNTDARGS="-N 2 -N 3"
RPCIDMAPDARGS=""
SVCGSSDARGS=""
--no-udpdésactive les connexions UDP-N 2désactive NFS version 2 (on ne s’en sert pas, on est en full v4)-N 3désactive NFS version 3 (on ne s’en sert pas, on est en full v4)4nombre de démonnfsdà lancer en parallèle-Srestreintidmapdau mode serveur.
Note that on more recent kernels only the NFSv4 server uses rpc.idmapd. The NFSv4 client instead uses nfsidmap, and only falls back to rpc.idmapd if there was a problem running the nfsidmap program.
J’ai aussi dû éditer le unit-file de nfs-serveur pour faire en sorte qu’il ne démarre que les démons voulue.
root@server # systemctl edit --full nfs-server.service
root@server # systemd-delta
…
[OVERRIDDEN] /etc/systemd/system/nfs-server.service → /usr/lib/systemd/system/nfs-server.service
--- /usr/lib/systemd/system/nfs-server.service 2015-12-01 05:55:13.640200202 +0100
+++ /etc/systemd/system/nfs-server.service 2016-01-31 18:15:07.326798346 +0100
@@ -1,10 +1,7 @@
[Unit]
Description=NFS server and services
-Requires= network.target proc-fs-nfsd.mount rpcbind.target
-Requires= nfs-mountd.service
-Wants=rpc-statd.service nfs-idmapd.service auth-rpcgss-module.service
-Wants=rpc-gssd.service gssproxy.service rpc-svcgssd.service
-Wants=rpc-statd-notify.service
+Requires= network.target proc-fs-nfsd.mount nfs-mountd.service
+Wants= nfs-idmapd.service rpc-svcgssd.service
After= network.target proc-fs-nfsd.mount rpcbind.target nfs-mountd.service
After= nfs-idmapd.service rpc-statd.service
…
Note : ici je suis obligé d’utiliser systemctl edit --full car, comme indiqué dans le man systemd.unit :
Note that dependencies (After=, etc.) cannot be reset to an empty list, so dependencies can only be added in drop-ins. If you want to remove dependencies, you have to override the entire unit.
Lancement et ajout du processus au démarrage.
root@server # systemctl start nfs-server.service
root@server # systemctl enable nfs-server.service
OpenRC
Si vous utilisez OpenRC et non systemd.
Le fichier /etc/conf.d/nfs permet de configurer les démons à démarrer et leurs options.
NFS_NEEDED_SERVICES="rpc.idmapd rpc.svcgssd"
OPTS_RPC_NFSD="--no-udp -N 2 -N 3 4"
OPTS_RPC_MOUNTD="-N 2 -N 3"
OPTS_RPC_IDMAPD="-S"
OPTS_RPC_SVCGSSD=""
EXPORTFS_TIMEOUT=30
- en plus des démon standards, démarre
rpc.idmapdqui sert à mapper les utilisateur du client avec ceux du serveur - en plus des démon standards, démarre
rpc.svcgssdqui gère l’interfaçage avec Kerberos --no-udpdésactive les connexions UDP-N 2désactive NFS version 2 (on ne s’en sert pas, on est en full v4)-N 3désactive NFS version 3 (on ne s’en sert pas, on est en full v4)4nombre de démonnfsdà lancer en parallèle-Srestreintidmapdau mode serveur.
Note that on more recent kernels only the NFSv4 server uses rpc.idmapd. The NFSv4 client instead uses nfsidmap, and only falls back to rpc.idmapd if there was a problem running the nfsidmap program.
Démarrage des démons et activation au boot :
root@server # /etc/init.d/nfs start
* Starting rpcbind ... [ ok ]
* Starting svcgssd ... [ ok ]
* Starting idmapd ... [ ok ]
* Exporting NFS directories ... [ ok ]
* Starting NFS mountd ... [ ok ]
* Starting NFS daemon ... [ ok ]
* Starting NFS smnotify ... [ ok ]
root@server # rc-update add nfs default
Exports
/etc/exports
/export -fsid=0,ro,async,all_squash,no_subtree_check,sec=krb5 192.168.1.0/24 2001:470:1f13:1e5::/64
/export/max -rw,async,no_subtree_check,sec=krb5 192.168.1.0/24 2001:470:1f13:1e5::/64
/export/ddext -rw,async,no_subtree_check,sec=krb5 192.168.1.0/24 2001:470:1f13:1e5::/64
fsid=0obligatoire et unique, tous les autres répertoires partagés doivent se trouvé sous celui-ciropartage en lecture seulasyncn’attend pas d’avoir effectué l’opération pour retourner la réponse au client. Si un client demande la création d’un fichier, le serveur lui répond avant même que le fichier ne soit écrit sur le disque (« Reply to requests before any changes made by that request have been committed to stable storage »).all_squashtoutes les requêtes sont exécuté en temps que nobody:nobody sur le serveurno_subtree_checkbien expliqué dans la doc…sec=krb5authentification de la machine cliente et des utilisateur via Kerberos. krb5i et krb5p sont d’autre possibilités.krb5iajoute la vérification d’intégrité des opération NFS àkrb5etkrb5pajoute le chiffrement du traffic réseau àkrb5i.rwpartage en lecture et écriture
Firewall
Le client n’est pas protégé par un firewall. Sur le serveur j’accepte les connexions sur le démon nfsd (2049).
-A INPUT -s 192.168.1.0/24 -p tcp --dport nfs -j ACCEPT
Pour kerberos, allez voir la page dédiée.
Client
/etc/conf.d/nfs-common.conf
root@laptop # cat /etc/conf.d/nfs-common.conf
…
GSSD_OPTS=""
…
root@laptop # systemctl enable --now rpc-gssd.service
/etc/fstab
server.lan:/max /mnt/server nfs defaults,_netdev,nfsvers=4,nolock,users,noauto,lazytime,sec=krb5 0 0
server.lan:/ddext /mnt/ddext nfs defaults,_netdev,nfsvers=4,nolock,users,noauto,lazytime,sec=krb5 0 0
Montage du partage
max@laptop % mount /mnt/ddext
max@laptop % ls /mnt/ddext
ls: cannot open directory /mnt/ddext: Permission denied
Authentification de l’utilisateur dans Kerberos. Pour pouvoir parcourir le montage.
max@laptop % kinit
Password for max@LAN:
max@laptop % ls /mnt/ddext
test1 test2 …
Sources :
nolock
Vous aurez peut-être remarqué l’option nolock dans le fstab du client. Sans cette option, je me retrouve avec :
max@laptop % mount /mnt/server
Job for rpc-statd.service failed. See "systemctl status rpc-statd.service" and "journalctl -xe" for details.
mount.nfs: rpc.statd is not running but is required for remote locking.
mount.nfs: Either use '-o nolock' to keep locks local, or start statd.
mount.nfs: an incorrect mount option was specified
NFSv2 et NFSv3 utilise le « NLM sideband protocol » pour géré le système de lock de fichier. Dans NFSv4, le locking est intégré au protocol, il n’y a plus besoin de NLM.
In NFS version 4, file locking is supported directly in the main NFS protocol, and the NLM and NSM sideband protocols are not used.
Si, l’option nolock n’est pas présente, mount utilise NLM.
rpc.statd est le service responsable de ce protocole, systemd essaie donc de le démarrer mais échoue car rpcbind n’est pas pas démarré (ainsi que toutes les dépendances habituel necessaire à un client NFSv2 ou NFSv3).
If neither option is specified (or if lock is specified), NLM locking is used for this mount point.
pam_krb5
Il est possible de faire en sorte de récupérer automatiquement le ticket de l’utilisateur au login de celui-ci.
Installer le paquet pam-krb5.
TODO a écrire (dans la page Kerberos… pas celle de NFS)
Invalid argument
Si la commande mount retourne Invalid argument alors que tous les argument semble bon.
Vérifier que rpc.gssd est démarré.
max@laptop % mount -v /mnt/server
mount.nfs: timeout set for Sat Sep 10 18:45:28 2016
mount.nfs: trying text-based options 'nolock,sec=krb5,vers=4,addr=2001:…,clientaddr=2001:…'
mount.nfs: mount(2): Invalid argument
mount.nfs: an incorrect mount option was specified
J’ai eu un problème avec rpc-gssd.service qui ne se lancé pas. J’ai indiqué la solution dans le bug tracker Archlinux.
Résumé
Ajout d’un nouveau client
Sur le serveur :
root@server # systemctl start krb5-kadmind.service
root@server # kadmin
Authenticating as principal root/admin@LAN with password.
Password for root/admin@LAN:
kadmin: addprinc -randkey nfs/max-test.lan
WARNING: no policy specified for nfs/max-test.lan@LAN; defaulting to no policy
Principal "nfs/max-test.lan@LAN" created.
kadmin: quit
Sur le client :
max@max-test % cat /etc/krb5.conf
[libdefaults]
default_realm = LAN
[realms]
LAN = {
admin_server = server.lan
default_domain = lan
kdc = server.lan
}
[domain_realm]
.lan = LAN
lan = LAN
max@max-test % grep server.lan /etc/hosts
2001:… server.lan
root@max-test # kadmin
Authenticating as principal root/admin@LAN with password.
Password for root/admin@LAN:
kadmin: ktadd nfs/max-test.lan
Entry for principal nfs/max-test.lan with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
Entry for principal nfs/max-test.lan with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
kadmin: quit
max@max-test % yaourt -S nfs-utils
max@max-test % grep server /etc/fstab
server.lan:/max /mnt/server nfs defaults,nfsvers=4,nolock,_netdev,users,noauto,lazytime,sec=krb5 0 0
max@max-test % sudo systemctl start rpc-gssd.service
max@max-test % sudo mkdir /mnt/server
max@max-test % kinit
Password for max@LAN:
max@max-test % mount /mnt/server
Débug
En générale avec NFS, si vous pensez avoir une bonne conf mais que ça ne fonctionne pas… reboot. Ça m’est arrivé plusieurs fois de rebooter pour que d’un coup tout fonctionne. Il y a certainement des caches et des buffers qu’il faudrait vider pour éviter le redémarrage mais je ne sais pas comment faire.
Serveur
Activation des options de debug
/etc/conf.d/nfs
NFS_NEEDED_SERVICES="rpc.idmapd rpc.svcgssd"
OPTS_RPC_NFSD="--no-udp -N 2 -N 3 8 -d"
OPTS_RPC_MOUNTD="--no-udp -N 2 -N 3 -d all"
OPTS_RPC_STATD=""
OPTS_RPC_IDMAPD="-vvvv"
OPTS_RPC_GSSD=""
OPTS_RPC_SVCGSSD="-vvvv"
OPTS_RPC_RQUOTAD=""
EXPORTFS_TIMEOUT=30
/etc/conf.d/rpcbind
RPCBIND_OPTS="-vvvv"
Arrêt des démons
root@server # /etc/init.d/rpcbind stop
* Stopping NFS mountd ... [ ok ]
* Stopping NFS daemon ... [ ok ]
* Unexporting NFS directories ... [ ok ]
* Stopping svcgssd ... [ ok ]
* Stopping idmapd ... [ ok ]
* Stopping rpcbind ... [ ok ]
root@server # pgrep -f -a 'nfs'
root@server # pgrep -f -a '\/rpc'
Redémarrage des démons
root@server # /etc/init.d/nfs start
* Starting rpcbind ... [ ok ]
* Starting svcgssd ... [ ok ]
* Starting idmapd ... [ ok ]
* Exporting NFS directories ... [ ok ]
* Starting NFS mountd ... [ ok ]
* Starting NFS daemon ... [ ok ]
* Starting NFS smnotify ... [ ok ]
Vérification des démons qui sont lancés et leurs options
root@server # pgrep -f -a '\/rpc'
1467 /sbin/rpcbind -vvvv
1550 /usr/sbin/rpc.svcgssd -vvvv
4571 /usr/sbin/rpc.idmapd -vvvv
15095 /usr/sbin/rpc.mountd --no-udp -N 2 -N 3 -d
N’exporter qu’un seul répertoire de façon très simple
/etc/exports
/export/max gss/krb5(fsid=0,rw,insecure,no_subtree_check)
Ré-exports
root@server # exportfs -ra
Désactivation du firewall et vérification
root@server # /etc/init.d/iptables stop
…
root@server # iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Client
Activation des options de debug
/etc/conf.d/nfs-common.conf
STATD_OPTS=""
SMNOTIFY_OPTS=""
IDMAPD_OPTS=""
GSSD_OPTS="-vvvv"
/etc/conf.d/rpcbind
RPCBIND_ARGS="-vvvv"
Arrêt des démons
max@laptop % sudo systemctl stop rpcbind
Warning: Stopping rpcbind.service, but it can still be activated by:
rpcbind.socket
max@laptop % sudo systemctl stop nfs-client.target
max@laptop % pgrep -f -a rpc
153 rpciod
15461 /usr/sbin/rpc.gssd
15462 /usr/sbin/rpc.svcgssd
max@laptop % sudo kill 15461 15462
Redémarrage des démons
root@laptop # systemctl start rpcbind.service
root@laptop # systemctl start nfs-clients.target
Vérification des démons qui sont lancés et leurs options
max@laptop % pgrep -f -a rpc
153 rpciod
15461 /usr/sbin/rpc.gssd -vvvv
15508 /usr/bin/rpcbind -w -vvvv
Monter un répertoire de façon très simple
max@laptop % mkdir /tmp/test
max@laptop % sudo mount -vvv -t nfs4 -o sec=krb5 server.lan:/ /tmp/test
Notes
À chaque échec redémarré les démon du client (et potentiellement du serveur). Ils possèdent un cache que peu foutre la merde (notamment pour les résolution DNS).
Commandes
exportfsgère les export-rréexporte les répertoires déjà exportés-aexporte les nouveau répertoire ajouté au fichier/etc/exportset « désexporte » ceux qui on été supprimés (il semble qu’il fasse aussi un reexport des répertoires déjà exportés)
nfsstataffiche des stats… pas très utile selon moinfsiostatpendant deiostatpour nfs
showmount ne peut plus être utilisé sur un serveur full NFSv4.