NFS avec Kerberos

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é.

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, 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 :

1
2
3
4
5
6
7
8
9
#!/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 !

links

social