Samba AD DC - Partage NFSv4 avec authentification Kerberos

Le partage de données se fait communément avec le protocole SMB (Server Message Block). Ce protocole a l'avantage d'être supporté par l'ensemble des plate-formes (Windows, Apple, Linux, Unix).

Une alternative à celui-ci est NFS (Network File System) qui, historiquement, est le protocole de partage de données dans le monde Unix et plus tard Linux. Ces trois premières versions manquaient cruellement de sécurité. La quatrième version apporte des éléments de sécurité concrets dont :

  • L'authentification des intervenants qui a pour but de vérifier l'identité de la personne ou de la machine avec qui l'on communique.
  • La signature des communications qui a pour but de détecter si la communication a été modifiée entre son émission et sa réception.
  • Le chiffrement des communications qui a pour but d'empêcher la compréhension de la communication si elle est interceptée.

Paramètres

Pour cette documentation, les paramètres suivants seront utilisés 1)

Nom de domaine Royaume (realm)
example.com EXAMPLE.COM
Nom de machine Adresse IP Role
ubndc01 192.0.2.11 Contrôleur de domaine
ubnfs01 192.0.2.12 Serveur de fichier
ubnws01 192.0.2.13 Machine client

Le répertoire partagé sera le répertoire /media/home/example présent sur le serveur de fichier et contenant les répertoires home des utilisateurs du domaine. Ce répertoire sera monté sur chaque machine du domaine afin de permettre à chaque utilisateur d'accéder à son répertoire home depuis n'importe quelle machine du domaine.

Le User Principal Name (UPN) est un identifiant unique pour l'identité de sécurité d'un utilisateur ou d'un ordinateur. Il existe deux type d'UPN

  • L' iUPN (implicit UPN) constitué de l'attribut samAccountName@<REALM>
  • L' eUPN (explicit UPN) défini par l'attribut userPrincipalName.

Dans le cas où deux objets auraient leur eUPN et iUPN en commun, l' eUPN a une priorité supérieure.

Le Service Principal Name (SPN) est un identifiant unique pour un service tournant sur un ordinateur. Il prend la forme <service>/<hostname>:<port>/<service_name>@<REALM> avec le champ hostname qui peut être juste le nom de l'ordinateur ou son nom pleinement qualifié (FQDN). Les champs port et service_name sont optionnels.

Un UPN permet de demander un ticket au serveur Kerberos afin de communiquer avec un SPN. Par défaut, les objets 'utilisateur' d'Active Directory possède un UPN. Mais, les objets 'ordinateur' d'Active Directory n'en possède pas par défaut. Dans le cadre de SSH, c'est l'utilisateur qui établit la communication avec le service distant. Dans le cadre de NFS avec Kerberos, c'est l'ordinateur qui établit la communication avec le service distant.

Installation du serveur NFS

L'installation de NFS se fait avec le paquet nfs-kernel-server

sudo apt-get install nfs-kernel-server

Définition des partages NFS

Avant de faire fonctionner NFS, il faut préparer le partage. NFSv4 base son partage sur une racine virtuelle définie. Bien qu'il soit possible d'utiliser des répertoires déjà existants, il est recommandé d'en créer un à la racine du système de fichier, par exemple /export. Ensuite pour chaque répertoire qui sera partagé, il faut créer un sous répertoire dans la structure NFS, par exemple /export/home/example.

sudo mkdir -p /export/home/example

A ce stade, les données partagées le seraient sur la partition Root ce qui n'est pas une bonne pratique. Afin de ne pas modifier le reste du serveur de fichier, il faut procéder à la jonction du répertoire /export/home/example avec le répertoire qui contiendra réellement les données, /home/example. Dans le cas où le répertoire contenant les données représente une partition entière, la partition peut alors être directement montée sur la structure NFS.

En ligne de commande

sudo mount --bind /home/example /export/home/example

Ou en ajoutant une ligne dans le fichier /etc/fstab pour que l'opération soit effectuée à chaque redémarrage

/etc/fstab
# Export NFS4
/home/example            /export/home/example        none       bind           0       0

Cette structure de répertoires sous /export doit être considérée comme une structure virtuelle permettant le fonctionnement de NFS et non pas comme une structure pour le stockage de fichiers directement. Ainsi, l'impact en espace disque sur la partition Root est quasi nul.

La configuration des partages se fait au travers du fichier /etc/exports

/etc/exports
/export                192.0.2.0/24(ro,sync,fsid=0,no_subtree_check,crossmnt,sec=krb5)
/export/home/example   192.0.2.0/24(rw,sync,no_subtree_check,sec=krb5)

La première ligne avec l'option fsid=0 (ou fsid=root) définit la racine virtuelle du système de fichiers partagés. Il n'y a aucune nécessité de donner des droits d'écriture sur cette racine. Tous les fichiers et répertoires sous /export sont accessibles par le partage NFS.

L'option sec=krb5 définit le niveau de sécurité exigé. Il en existe 3:

  • krb5: Authentification Kerberos
  • krb5i: Authentification Kerberos avec signature des communications (i pour integrity)
  • krb5p: Authentification Kerberos avec chiffrement des communications (p pour privacy)
Bien qu'encore utilisée, les notations gss/krb5, gss/krb5i et gss/krb5p sont dépréciées. Il est recommandé d'utiliser l'option sec=

Lancement du service NFS

A ce stade, le démarrage du serveur NFS ne devrait pas encore fonctionner.

sudo service nfs-kernel-server start
 * Exporting directories for NFS kernel daemon...                                        [ OK ] 
 * Starting NFS kernel daemon                                                            [fail] 

Afin de remédier au problème, il faut avant tout l'identifier correctement. Et pour ce faire, il faut accéder aux logs (fichiers d'historique d’événements).

/var/log/syslog
Oct  6 18:13:26 ubnfs01 rpc.svcgssd[25763]: unable to obtain root (machine) credentials
Oct  6 18:13:26 ubnfs01 rpc.svcgssd[25763]: do you have a keytab entry for nfs/<your.host>@<YOUR.REALM> in /etc/krb5.keytab?

Le service n'arrive pas à démarrer parce qu'il ne trouve pas son SPN (Service Principal Name) dans le fichier keytab par défaut (/etc/krb5.keytab) qui, par défaut, serait nfs/ubnfs01.example.com@EXAMPLE.COM. Plus clairement, le service ne trouve pas son identité afin de s'authentifier. Pour modifier le fichier keytab, il faut utiliser l'outil net avec les commandes ads keytab. Il faut également avoir les droits super-utilisateurs. Pour rappel, vu l'importance de ce fichier, les permissions sur celui-ci sont très restrictives root:root 600. Seul l'utilisateur root peut y accéder en lecture et écriture. Il faut également interagir avec le serveur Kerberos présent sur le DC. Pour cela, la meilleure façon de procéder consiste à s'authentifier avec un compte administrateur du domaine à chaque commande avec l'option -U Administrator.

sudo net ads keytab add nfs -U Administrator
Enter Administrator's password:

sudo net ads keytab list
Vno  Type                                        Principal
  6  des-cbc-crc                                 host/ubnfs01.example.com@EXAMPLE.COM
  ...
  6  arcfour-hmac-md5                            UBNFS01$@EXAMPLE.COM
  6  des-cbc-crc                                 nfs/ubnfs01.example.com@EXAMPLE.COM
  ...
  6  arcfour-hmac-md5                            nfs/ubnfs01@EXAMPLE.COM

La commande add <service> ajoute deux SPN au fichier keytab (un pour le hostname et un pour le fqdn). Parallèlement, deux attributs 'servicePrincipalName' sont ajoutés à l'object Active Directory représentant l'ordinateur (ubnfs01) (<service>/<hostname> et <service>/<fqdn>)..

La commande list liste les UPN et SPN présents dans le fichier keytab.

La commande flush vide le fichier keytab et supprime l'ensemble des SPN associés à la machine.

La commande create crée le fichier keytab par défaut avec l'iUPN et l'eUPN, si l'attribut userPrincipalName a été définit, et les SPN host/<hostname>@<REALM> et host/<fqdn>@<REALM>.

Conseils

Le service nfs-kernel-server lorsqu'il démarre va lire le fichier de configuration /etc/default/nfs-kernel-server. Par défaut, il ne faut rien y changer. Cependant, si l'on veut augmenter la quantité d'informations envoyées dans le fichier log. On peut ajouter l'option "très bavard" au démon rpc.svcgssd (responsable de l'authentification de la machine vis-à-vis du serveur Kerberos)

/etc/default/nfs-kernel-server
RPCSVCGSSDOPTS="-vvv"

De façon plus générale, la page de manuel du démon rpc.svcgssd propose d'autres options plus avancées.

Installation du client NFS

L'installation du client NFS se fait avec le paquet nfs-common

sudo apt-get install nfs-common

Montage du partage

Le partage se monte avec la commande mount et le type nfs4 qui va rediriger l'appel vers la commande spécifique mount.nfs4. Afin de test l'accès au partage, le partage sera monté sur /mnt/test au lieu de /home/example.com

sudo mount -t nfs4 -o sec=krb5 ubnfs01.example.com:/home/example /home/example

L'option sec=krb5 précise que le montage se fera avec authentification Kerberos.

Erreurs et solutions

Le résultat de la commande mount ci-dessus devrait être : "Access denied by server while mounting ubnfs01.example.com:/home/example"

Les raisons sont multiples et vont être parcourues ci-après

Activation du démon rpc.gssd

Le démon rpc.gssd est responsable de l'authentification par Kerberos. Il faut donc le démarrer manuellement (via son script Upstart, /etc/init/gssd.conf)

sudo start gssd

Ou de façon automatique en modifiant le fichier /etc/default/nfs-common

/etc/default/nfs-common
NEED_GSSD="yes"

A la lecture du script Upstart du démon rpc.gssd, on constate que ce démon va charger plusieurs modules dont rpcsec_gss_krb5 et que si le fichier /etc/fstab contient une ligne avec une option du type sec=krb5, le démon sera automatiquement démarré.

Afin de faciliter le dépannage en cas de problème avec ce démon, il est possible d'activer son mode "très, très bavard" avec l'option "-vvv".

sudo stop gssd
sudo rpc.gssd -vvv

La page de manuel de ce démon liste d'autres options plus avancées.

DNS inversé

Dans le fichier log, on identifie vite le problème

/var/log/syslog
Oct  6 22:09:42 ubnws01 rpc.gssd[3609]: ERROR: unable to resolve 192.0.2.12 to hostname: Name or service not known
Oct  6 22:09:42 ubnws01 rpc.gssd[3609]: ERROR: failed to read service info

La cause est l'absence de résolution inverse sur le serveur DNS (également fournit par Samba AD DC). Pour y remédier, il faut ajouter la zone 2.0.192.in-addr.arpa et le pointeur ubnfs01.example.com pour l'adresse 12

samba-tool dns zonecreate ubndc01 2.0.192.in-addr.arpa
Zone 2.0.192.in-addr.arpa created successfully

samba-tool dns add ubndc01 2.0.192.in-addr.arpa 12 PTR ubnfs01.example.com
Record added successfully

La commande samba-tool utilise le ticket kerberos de l'utilisateur pour réaliser ces opérations. Si l'utilisateur n'a pas de ticket Kerberos, il peut utiliser l'option -U Administrator.

A cause du Bug 9404 de Samba 4, la zone fraîchement créée n'est pas automatiquement chargée par le serveur DNS interne de Samba. Il faut redémarrer le service samba-ad-dc sur le contrôleur de domaine.

ssh ubndc01
...
sudo service samba-ad-dc restart
samba-ad-dc stop/waiting
samba-ad-dc start/running, process 11129
exit

Absence d'identité

Le démon rpc.gssd va chercher une identité dans le fichier /etc/krb5.keytab pour s'authentifier vis-à-vis du serveur Kerberos. Il essaie premièrement l'UPN de l'ordinateur <FQDN$>@<REALM> et ensuite les SPN root/<fqdn>@<REALM>, nfs/<fqdn>@<REALM> et host/<fqdn>@<REALM>.

/var/log/syslog
Oct  7 20:17:08 ubnws01 rpc.gssd[6173]: No key table entry found for UBNWS01.EXAMPLE.COM$@EXAMPLE.COM while getting keytab entry for 'UBNWS01.EXAMPLE.COM$@EXAMPLE.COM'
Oct  7 20:17:08 ubnws01 rpc.gssd[6173]: No key table entry found for root/ubnws01.example.com@EXAMPLE.COM while getting keytab entry for 'root/ubnws01.example.com@EXAMPLE.COM'
Oct  7 20:17:08 ubnws01 rpc.gssd[6173]: No key table entry found for nfs/ubnws01.example.com@EXAMPLE.COM while getting keytab entry for 'nfs/ubnws01.example.com@EXAMPLE.COM'
Oct  7 20:17:08 ubnws01 rpc.gssd[6173]: No key table entry found for host/ubnws01.example.com@EXAMPLE.COM while getting keytab entry for 'host/ubnws01.example.com@EXAMPLE.COM'
Oct  7 20:17:08 ubnws01 rpc.gssd[6173]: ERROR: gssd_refresh_krb5_machine_credential: no usable keytab entry found in keytab /etc/krb5.keytab for connection with host ubnfs01.example.com
Oct  7 20:17:08 ubnws01 rpc.gssd[6173]: ERROR: No credentials found for connection to server ubnfs01.example.com

Normalement, s'il a été crée, le fichier /etc/krb5.keytab contient le bien le SPN <host>/<fqdn>@<REALM>. L'erreur devient alors

/var/log/syslog
Oct  7 22:16:44 ubnws01 rpc.gssd[6173]: Success getting keytab entry for 'host/ubnws01.example.com@EXAMPLE.COM'
Oct  7 22:16:44 ubnws01 rpc.gssd[6173]: WARNING: Client 'host/ubnws01.example.com@EXAMPLE.COM' not found in Kerberos database while getting initial ticket for principal 'host/ubnws01.example.com@EXAMPLE.COM' using keytab 'FILE:/etc/krb5.keytab'
Oct  7 22:16:44 ubnws01 rpc.gssd[6173]: ERROR: No credentials found for connection to server ubnfs01.example.com

Le démon rpc.gssd est multi-usage. Dans le cas de NFSv4 avec Kerberos, il a besoin de l'UPN de l'ordinateur (cfr Notions Kerberos). Le fichier /etc/krb5.keytab possède déjà l' iUPN (<HOSTNAME$>@<REALM>) mais le démon rpc.gssd recherche l'UPN <FQDN$>@<REALM>. Il faut donc ajouter l' eUPN équivalent à l'objet représentant la machine cliente dans l'Active Directory. Ceci consiste à ajouter l'attribut 'userPrincipalName' avec la valeur <FQDN$>@<REALM>. Il y a une multitude de façon de procéder :

  • Utiliser une machine Windows dans le domaine avec les outils d'administrations pour Active Directory.
  • Utiliser un logiciel avec une interface graphique proche de ce que Windows propose, par exemple Apache Directory Studio, qui n'est pas inclus dans la distribution Ubuntu.
  • Utiliser les outils LDAP
ldapmodify -H ldap://ubndc01.example.com -U Administrator << EOF
dn: cn=ubnws01,cn=computers,dc=example,dc=com
changetype: modify
add: userPrincipalName
userPrincipalName: UBNWS01.EXAMPLE.COM\$@EXAMPLE.COM
EOF

Cette méthode ne modifie pas les identités existantes de la machine. On peut alors ajouter la nouvelle identité (eUPN) au fichier keytab avec la commande

sudo net ads keytab add UBNWS01.EXAMPLE.COM\$ -U Administrator
  • Utiliser la commande net ads join qui sert à joindre la machine au domaine.
sudo net ads join createupn=UBNWS01.EXAMPLE.COM\$@EXAMPLE.COM -U Administrator
Ceci va créer de nouvelles versions des identités liées à la machines (iUPN, eUPN et 2 SPN host/…). Ses nouvelles identités sont ajoutées au fichier /etc/krb5.keytab mais les anciennes ne sont pas automatiquement supprimées. On peut faire le ménage avec les commandes mais ceci risque d’interrompre les processus qui utilisaient les anciennes identités.
sudo net ads keytab flush -U Administrator
sudo net ads keytab create -U Administrator

Eureka

Après avoir résolu ces quelques problèmes, il est possible de monter le partage NFS et d'y accèder.

Automatisation

Deux approches sont possibles pour l'automatisation du montage des partages NFS.

  • Ajouter une ligne dans le fichier /etc/fstab
  • Utiliser autofs

La première possibilité implique que la machine doit avoir une connectivité réseau avant de procéder au montage. C'est typiquement le cas des serveurs mais pas des machines de bureau (fixes ou portables). De plus, il y a la problématique de la gestion des ressources. En effet, chaque partage monté consomme des ressources sur la machine cliente mais surtout sur la machine serveur. La seconde possibilité apporte donc une solution à ces deux problèmes.

Mise en oeuvre avec /etc/fstab

/etc/fstab
ubnfs01:/home/example        /home/example        nfs4        sec=krb5        0        0

Mise en oeuvre sur base de autofs

Installation du paquet autofs

sudo apt-get install autofs

Ajout d'une entrée dans le fichier maître /etc/auto.master

/etc/auto.master
/home/example        /etc/auto.home        --timeout=90

Définition de la règle auto.home

/etc/auto.home
*        -fstype=nfs4,sec=krb5 ubnfs01.example.com:/home/example/&

Sur le serveur DNS

Les lignes de codes de ce paragraphe s'appliquent uniquement au serveur DNS interne de Samba. Pour réaliser ces opérations sur tout autre serveur DNS, il faut se référer à la documentation du serveur DNS

Créer une zone DNS inversé

samba-tool dns zonecreate ubndc01 2.0.192.in-addr.arpa
Zone 2.0.192.in-addr.arpa created successfully

Ajouter un pointeur vers le serveur de fichier

samba-tool add ubndc01 2.0.192.in-addr.arpa 12 PTR ubnfs01.example.com
Record added successfully

Redémarrer le contrôleur de domaine pour pallier au Bug 9404

ssh ubndc01
sudo service samba-ad-dc restart
exit

Sur le serveur de fichier

Installation du paquets NFS server

sudo apt-get install nfs-kernel-server

Création de la structure de répertoire pour NFS

sudo mkdir -p /export/home/example

Jonction du répertoire réel avec la structure NFS

/etc/fstab
# Export NFS4
/home/example           /export/home/example        none       bind          0       0
sudo mount /export/home/example

Ajout du SPN dans le keytab

sudo net ads keytab add nfs -U Administrator

Lancement du service

sudo service nfs-kernel-server start

Sur les clients NFS

Installation du paquet NFS client

sudo apt-get install nfs-common

S'il n'est pas déjà définit dans l'Active Directory, définir l'eUPN de l'ordinateur

ldapmodify -H ldap://ubndc01.example.com -U Administrator << EOF
dn: cn=ubnws01,cn=computers,dc=example,dc=com
changetype: modify
add: userPrincipalName
userPrincipalName: UBNWS01.EXAMPLE.COM\$@EXAMPLE.COM
EOF

S'il n'est pas déjà présent dans le fichier /etc/krb5.keytab, ajouter l'eUPN au fichier

sudo net ads keytab add UBNWS01.EXAMPLE.COM\$ -U Administrator

Monter la ressource partagée manuellement

sudo mount -t nfs4 -o sec=krb5 ubnfs01.example.com:/home/example /home/example

Ou automatiquement (cfr Automatisation)

Contributeur principal : Qedinux


1)
Conformément aux RFC 2606 (Reserved Top Level DNS Names) et RFC 5737 (IPv4 Address Blocks Reserved for Documentation)
  • tutoriel/samba_ad_dc_nfs4_kerberized.txt
  • Dernière modification: Le 21/11/2017, 16:35
  • (modification externe)