NFS avec Kerberos
=================
Date: 2016-07-23 18:21
Author: jdn06
Category: Logiciels libres
Tags: NFS, Kerberos, Archlinux, FreeBSD
Après plusieurs années passées à regretter le manque de sécurité de
mon partage NFS domestique, reposant sur les seules adresses IP, sans
authentification par défaut, et à lancer périodiquement un bref
regard sur Kerberos, avant d’en conclure rapidement que c’était
décidément trop compliqué, j’ai profité des vacances pour regarder de
plus près ce protocole intimidant – et pas seulement de nom…
Bon, je ne vais pas non plus mentir : je me suis cassé les dents deux
bonnes journées avant de parvenir à le faire marcher, mais a
posteriori, je dois dire que ce n’est finalement pas aussi difficile
qu’on pourrait le croire. Non que deux journées soient un temps
négligeable, mais simplement parce que j’ai beaucoup perdu de temps
sur des choses stupides, faute de chercher immédiatement les bons
outils de débogeage.
Je veux donc dire qu’en respectant quelques règles de bon sens, on
doit pouvoir faire beaucoup mieux. Je renvoie tout d’abord au
meilleur tutoriel en ligne que j’ai trouvé[1].
Quand on débute dans ce genre d’entreprise, il est inévitable de
tâtonner un peu et de commettre des erreurs. Le problème est de les
trouver sans tourner en rond pendant des heures. Or, la mise en place
d’un tel système requiert tout un ensemble de démons et de protocoles
qui coopèrent, en ne produisant par défaut que bien peu de traces
dans les logs.
Essayons de tracer brièvement les étapes de la mise en place d’un
serveur NFS Kerberisé sans FQDN, seulement avec des noms de machine
sur un réseau local. J’utilise par défaut Kerberos MIT (la présence
du concurrent Heimdal sur FreeBSD m’a posé d’ailleurs quelques
problèmes pour les clients sur FreeBSD…)
Une fois krb5 installé, il faut commencer par éditer /etc/krb5.conf.
Le realm qu’il faut créer sera en quelque sorte la marque de ce
serveur Kerberos, qui le distingue des autres serveurs Kerberos avec
lesquels les clients pourraient être en contact. De plus le fichier
doit contenir quelques éléments minimaux. La documentation (et les
conseils de débogeage) insistent beaucoup sur la nécessité d’utiliser
exclusivement des FQDN. En fait, il est possible d’utiliser des noms
de machines locales, à condition qu’elles figurent toutes dans les
/etc/hosts du serveur et des clients.
Cela donne donc en gros :
[realms]
MONREALM = {
kdc = mon_serveur_kerberos
admin_server = mon_serveur_kerberos
nfs-server = mon_serveur_kerberos
}
[domain_realm]
mon_serveur_kerberos = MONREALM
[logging]
default = /var/log/kerberos.log
kdc = /var/log/kerberos.log
admin_server = /var/log/kerberos.log
Il faut ensuite créer un fichier /var/lib/krb5kdc/kadm5.acl et placer
dedans : */admin@MONREALM *
Il faut aussi ouvrir les ports suivants sur le serveur Kerberos à
tous les clients potentiels et au serveur nfs : 88 et 749 en tcp et
en udp.
Puis on intialise la base de données avec un
sudo kdb5_util create -r MONREALM -s
et on peut alors se connecter en admin localement avec un simple
sudo kadmin.local
ce qui va nous permettre de lancer des commandes dans le shell de
Kerberos :
- listprincs permet de voir tous les principaux existants ; un
principal est en quelque sorte un utilisateur et un contexte.
- add_principal -randkey nfs/mon_serveur_nfs@MONREALM va permettre
d’ajouter un principal pour le serveur nfs. On utilise l’option
randkey car on ne veut pas créer un mot de passe, mais une
clé qui permettra au serveur nfs de s’authentifier tout seul.
- ktadd nfs/mon_serveur_nfs@MONREALM pour ajouter la clé au fichier
/etc/krb5.keymap
Il faudra ajouter comme principaux nfs/client1@MONREALM et
nfs/client2@MONREALM, à nouveau avec des clés exportées, puis
root/admin@MONREALM avec mot de passe (donc sans l’option -randkey),
afin de pouvoir se connecter depuis les autres machines.
Il faut ensuite configurer les autres machines (serveur nfs et
clients) pour pouvoir utiliser le serveur Kerberos. L’étape pour le
serveur nfs est inutile s’il est sur la même machine que le
serveur Kerberos. A chaque fois, il suffit de copier le fichier
/etc/krb5.conf du serveur sur ces différentes machines (et de
vérifier que leur fichier /etc/hosts est correctement complété) puis
de lancer sudo kadmin, d’indiquer le mot de passe de sudo, puis celui
que Kerberos demande. On importe ensuite la clé qui concerne cette
machine, avec par exemple la commande
ktadd nfs/client1@MONREALM
afin que Kerberos transfère la clé depuis le serveur vers le fichier
/etc/krb5.keymap du client1. Pour vérifier que cela a marché, on sort
de kadmin et on essaie, toujours depuis le client, un
sudo kinit -k nfs/client1@MONREALM
La commande ne doit pas produire d’erreur. On vérifie le résultat
avec sudo klist.
Une fois tout cela ajouté, et les vérifications faites, la partie
Kerberos proprement dite est terminée. Reste à faire marcher NFS avec
Kerberos. Théoriquement, c’est le plus facile. En pratique, c’est là
que j’ai beaucoup perdu de temps. Et comme je n’étais pas très l’aise
avec Kerberos, j’étais persuadé qu’il s’agissait d’un problème avec
la configuration de ce dernier, alors que ce n’était pas vraiment le
cas.
Tout d’abord, il faut utiliser la norme récente du fichier
/etc/exports, à savoir :
/srv/nfs4 192.168.1.0/24(ro,fsid=0,no_subtree_check,async,\
all_squash,sec=krb5)
et non :
/srv/nfs4 gss/krb5(ro,fsid=0,no_subtree_check,async,all_squash)
Ensuite, tout devrait fonctionner avec un simple
sudo mount -v -o ro -t nfs4 mon_serveur_nfs:/ \
/point_de_montage_nfs
depuis le client. Si le shell rend la main sans message d’erreur,
vous avez gagné. Il reste cependant à obtenir des droits pour les
autres utilisateurs que root sur la machine client. Pour cela, le
plus simple est de faire créer un principal utilisateur@MONREALM avec
mot de passe, dans le serveur Kerberos. Lorsque l’utilisateur veut se
connecter au partage NFS monté par root, il suffit qu’il tape kinit
dans une console et renseigne le mot de passe indiqué à la création
du principal en question. Le ticket ainsi créé lui donne ensuite un
accès de 24 heures.
Si vous avez moins de chance, il faut alors déboguer, et ça peut être
long et fastidieux. Mon premier réflexe, puisque c’est le serveur nfs
qui refuse le montage, a été de regarder, en m’inspirant du très bon
article du wiki d’archlinux.org[2], les logs du côté serveur et
client en activant :
- pour le serveur
sudo rpcdebug -m rpc -s all
sudo rpcdebug -m nfsd -s all
- et pour le client
sudo rpcdebug -m nfs -s all
Vu la verbosité du résultat, j’ai mis beaucoup de temps à comprendre
que l’erreur ne figurait pas dans ces logs et qu’il fallait chercher
ailleurs. Mais où ? Il faut regarder du côté des mécanismes qui
assurent la transisition entre Kerberos et NFS, à savoir sous
Archlinux les démons rpc-gssd (sur le client) et gssproxy (sur le
serveur). J’ai ajouté un fichier de configuration pour gssproxy avec
un mode debug, /etc/gssproxy/gssproxy.conf :
[gssproxy]
debug = true
[service/nfs-server]
mechs = krb5
socket = /run/gssproxy.sock
cred_store = keytab:/etc/krb5.keytab
trusted = yes
kernel_nfsd = yes
euid = 0
J’ai ensuite placé une option de debug dans le lanceur du
démon rpc-gssd (en faisant ça assez salement par un ajout
d’option dans le fichier /usr/lib/systemd/system/rpc-gssd.service
ExecStart=/usr/sbin/rpc.gssd $GSSDARGS -vvv) Avoir cette idée plus
vite m’aurait fait gagner beaucoup de temps, plutôt que de tâtonner
pendant des heures du côté de Kerberos, de RPC, de NFS et de leurs
logs. J’ai fini par trouver un problème rapporté depuis un bon moment
concernant la version 0.5.1 de gssproxy. En revenant à une ancienne
version, 0.4.1, le problème a disparu et tout s’est mis à fonctionner
selon mes attentes.
Happy end ? Par encore tout à fait, mais ça vient…
Il me restait encore à configurer mon client sous FreeBSD 10.3 ; or
ce dernier utilise par défaut la version Heimdal et non la version
MIT du protocole Kerberos. Tant que c’est le même protocole, tout
doit être compatible, me disais-je, avant de déchanter un peu. En
effet, toute utilisation de kadmin figeait le processus indéfiniment
sans aboutir. En réalité, kadmin n’est pas compatible entre ces deux
versions. Or, pour transférer la clé, il faut d’une manière ou d’une
autre l’utiliser. J’ai donc installé la version MIT depuis les ports
pour transférer la clé, puis l’ai désinstallée. Pour permettre le
montage NFS via Kerberos, il faut lancer trois démons :
- nfsclient
- nfsuderd
- gssd
Restait aussi un autre problème que j’ai contourné sans en comprendre
l’origine, à savoir le fait que le ticket n’était pas créé
automatiquement au montage NFS, provoquant l’échec de celui-ci. J’ai
donc créé le script suivant pour lancer le client NFS sous FreeBSD :
#!/bin/sh
sudo service nfsclient onestart
sudo service nfsuserd onestart
sudo service gssd onestart
sudo kinit -k nfs/client2@MONREALM
sudo mount_nfs -v -o nfsv4 mon_serveur_nfs:/ /point_de_montage_nfs
kinit
Et tout fonctionnait… enfin !
[1]
http://nfsv4.bullopensource.org/doc/kerberosnfs/krbnfs_howto_v3.pdf
[2]
https://wiki.archlinux.org/index.php/NFS/Troubleshooting