Table of Contents
Autenticazione Kerberos per NFSv4
La versione 4 del protocollo NFS si distingue dalla precedente versione 3 soprattutto per l'uso obbligatorio di una sicurezza forte (basata su Kerberos versione 5) e di un migliore meccanismo di locking (mandatory locking invece di advisory locking). L'uso del protocollo TCP su una sola porta facilita il passaggio attraverso i firewall.
In questo esempio semplificato il Kerberos Distribution Center (KDC) dove gira il demone è lo stesso host su cui gira il servizio NFS. Non esistono KDC slave, solo il master.
La distribuzione di riferimento è una GNU/Linux Debian Lenny.
Web references
Verifiche preliminari
- NTP installato e ora sincronizzata tra server e client.
- Il comando
hostname --fqdn
deve restituire un nome completo di dominio sul server e sul client.
Installazione server
Questi i pacchetti Debian da installare sul server:
- krb5-kdc: Kerberos key server
- krb5-admin-server: Kerberos admin daemon e altri comandi di amministrazione
Si deve creare il realm (dominio a cui apparterranno i server e i client) e alcuni principal (credenziali di utenti e servizi). L'installazione del pacchetto krb5-config richiede il nome del realm il nome dei Kerberos servers e dell'Administrative server, queste informazioni vengono scritte in due file di configurazione:
/etc/krb5.conf
file di configurazione per tutte le utility (client) Kerberos/etc/krb5kdc/kdc.conf
file di configurazione del demone KDC
In Debian abbiamo il comodo script krb5_newrealm che crea il database con gli account /var/lib/krb5kdc/principal, lo stash (un file che contiene la master key) /etc/krb5kdc/stash ed avvia i demoni eseguendo nell'ordine:
- kdb5_util create -s
- /etc/init.d/krb5-kdc start
- /etc/init.d/krb5-admin-server start
Ecco in dettaglio la creazione del realm con la richiesta della master key:
# kdb5_util create -s Loading random data Initializing database '/var/lib/krb5kdc/principal' for realm 'MYREALM.ORG', master key name 'K/M@MYREALM.ORG' You will be prompted for the database Master Password. It is important that you NOT FORGET this password. Enter KDC database master key:
Lo script crea anche un file con le ACL /etc/krb5kdc/kadm5.acl
, è consuetudine scommentare l'ultima riga per dare diritto di accesso a tutti i principal (account) il cui nome sia del tipo nome/admin:
# This file Is the access control list for krb5 administration. # When this file is edited run /etc/init.d/krb5-admin-server restart to activate # One common way to set up Kerberos administration is to allow any principal # ending in /admin is given full administrative rights. # To enable this, uncomment the following line: */admin *
Quindi si deve creare anche un account a cui dare questi privilegi, ad esempio root/admin@MYREALM.ORG. Si utilizza l'utilty kadmin.local
, come mostrato nel paragrafo successivo.
A questo punto sul server abbiamo tre demoni in esecuzione:
- /usr/sbin/krb5kdc in ascolto sulle porte 88 UDP (Kerberos v5) e 750 UDP (Kerberos v4)
- /usr/sbin/kadmind in ascolto sulla porta 749 TCP
- /usr/sbin/krb524d in ascolto sulla porta 4444 UDP (demone per la conversione delle credenziali da v.5 a v.4, non esiste più in Debian Squeeze, krb5-kdc versione 1.8.3)
Dump e restore del database Kerberos
Per salvare tutti i principals in un file ASCII:
kdb5_util dump -verbose kerberos_principals.dump
Per effettuare il restore su una macchina appena installata, senza aver creato il database in precedenza:
kdb5_util load -verbose kerberos_principals.dump
Per completare il restore bisogna recuperare anche il file con lo stash (gli eventuali messaggi di errore indicano la mancanza della master key) e le ACL, si tratta dei file:
/etc/krb5kdc/stash
/etc/krb5kdc/kadm5.acl
Modificare il lifetime dei ticket
La durata predefinita di un ticket è di 10 ore (installazione Debian). Per modificarla sono necessarie diverse operazioni.
Editare il file /etc/krb5kdc/kdc.conf
e modificare il max_life del realm predefinito. Questo parametro viene usato per creare i nuovi principal (non serve riavviare alcun servizio):
[realms] RIGACCI.ORG = { max_life = 16h 0m 0s
Modificare il maxlife
del principal krbtgt/REALM@REALM
, ad esempio con kdamin.local
:
getprinc krbtgt/RIGACCI.ORG@RIGACCI.ORG Maximum ticket life: 0 days 10:00:00 ... modprinc -maxlife "0 days 16 hours" krbtgt/RIGACCI.ORG@RIGACCI.ORG
Modificare il maxlife
di tutti i principal creati in precedenza.
Creazione account utente
L'utility kadmin.local consente di creare nuovi account (nella terminologia Kerberos sono chiamati principal). Si esegue con i privlegi di root sul server che ospita il KDC e non richiede alcuna ulteriore autenticazione.
kadmin.local: addprinc niccolo@MYREALM.ORG WARNING: no policy specified for niccolo@MYREALM.ORG; defaulting to no policy Enter password for principal "niccolo@MYREALM.ORG": Re-enter password for principal "niccolo@MYREALM.ORG": Principal "niccolo@MYREALM.ORG" created. kadmin.local: addprinc root@MYREALM.ORG ... kadmin.local: addprinc root/admin@MYREALM.ORG ... kadmin.local: listprincs K/M@MYREALM.ORG kadmin/admin@MYREALM.ORG kadmin/changepw@MYREALM.ORG kadmin/history@MYREALM.ORG krbtgt/TEXNET.ORG@MYREALM.ORG niccolo@MYREALM.ORG root/admin@MYREALM.ORG root@MYREALM.ORG
Come si vede esistono altri principal di servizio, oltre a quelli esplicitamente creati da noi.
Dopo aver aggiunto dei principal è possibile delegare le funzioni di amministratore ad altri utenti aggiungendo le opportune ACL in /etc/krb5kdc/kadm5.acl
. L'utente delegato userà l'utility kadmin. È convenzione diffusa dare privilegi di amministratore a tutti gli utenti del tipo name/admin@REALM.
Per gestire i ticket Kerberos si usano le utility kinit, klist e kdestroy.
Policy di default
Conviene definire una policy di default, da cui tutti i nuovi account ereditano alcune caratteristiche, ad esempio la lunghezza minima della password. Per gli account già creati bisogna esplicitamente settare la nuova policy:
add_policy -minlength 5 -minclasses 2 default get_policy default modify_principal -policy default niccolo@MYREALM.ORG
Installazione client
Questi i pacchetti Debian da installare sul client:
- krb5-user programmi per l'autenticazione Kerberos, gestione dei ticket, cambio della password.
- krb5-config prepara la configurazione per le utility Kerberos.
L'installazione scrive in /etc/krb5.conf
il realm e il server KDC predefinito.
Creazione account per server e client NFS
Sul server KDC si creano due account, uno per il server NFS e uno per il client (nella terminologia Kerberos un account viene detto principal), il nome dell'account è del tipo service_name/hostname@REALM. Sul server e sul client NFS bisogna invece creare le rispettive chiavi, che verranno salvate nei rispettivi file /etc/krb5.keytab
.
Giusto per fare un esempio, una parte la eseguiamo sul server KDC (che nel nostro esempio è anche server NFS) da utente root con kadmin.local
:
# kadmin.local addprinc -randkey nfs/inside.mydomain.org@MYREALM.ORG WARNING: no policy specified for nfs/inside.mydomain.org@MYREALM.ORG; defaulting to no policy Principal "nfs/inside.mydomain.org@MYREALM.ORG" created. kadmin.local: listprincs kadmin.local: ktadd -e des nfs/inside.mydomain.org@MYREALM.ORG Entry for principal nfs/inside.mydomain.org@MYREALM.ORG with kvno 3, encryption type DES cbc mode with RSA-MD5 added to keytab WRFILE:/etc/krb5.keytab. kadmin.local: exit
Il comando ktadd aggiunge una chiave nel file locale /etc/krb5.keytab
. Questa chiave deve stare sul server NFS, non confondiamoci col fatto che KDC e server NFS sono sullo stesso host in questo esempio.
ATTENZIONE al bug 413838:
Notare l'uso del comando ktadd
con l'opzione -e des . Il risultato è la creazione di una sola entry nella keytab, associata alla crittografia DES; l'impostazione predefinita sarebbe quella di creare due entry, una delle quali con crittografia triplo DES. Il server NFS supporta solo il DES: un bug nella procedura di negoziazione Kerberos causa il fallimento del mount se è presente anche la chiave triplo DES.
La seconda parte la eseguiamo sul client NFS, con il comando kadmin
(ovviamente richiede la password di amministratore Kerberos). È necessario usare l'utente root perché si deve aggiungere una chiave al file locale /etc/krb5.keytab
:
# kadmin -p root/admin@MYREALM.ORG Authenticating as principal root/admin@MYREALM.ORG with password. Password for root/admin@MYREALM.ORG: kadmin: addprinc -randkey nfs/ulisse.mydomain.org@MYREALM.ORG WARNING: no policy specified for nfs/ulisse.mydomain.org@MYREALM.ORG; defaulting to no policy Principal "nfs/ulisse.mydomain.org@MYREALM.ORG" created. kadmin: ktadd nfs/ulisse.mydomain.org@MYREALM.ORG Entry for principal nfs/ulisse.mydomain.org@MYREALM.ORG with kvno 5, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/etc/krb5.keytab. Entry for principal nfs/ulisse.mydomain.org@MYREALM.ORG with kvno 5, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/etc/krb5.keytab.
Il comando addprinc genera un nuovo account sul server KDC remoto, il comando ktadd invece aggiunge una chiave nel file /etc/krb5.keytab
locale.
Verificare che funzioni la risoluzione del nome DNS ulisse.mydomain.org, sia diretta che inversa.
Per vedere chiavi memorizzate localmente in /etc/krb5.keytab
:
k5srvutil list Keytab name: FILE:/etc/krb5.keytab KVNO Principal ---- -------------------------------------------------------------------------- 3 nfs/ulisse.mydomain.org@MYREALM.ORG 3 nfs/ulisse.mydomain.org@MYREALM.ORG
Per eliminare delle chiavi si usa il comando k5srvutil delete
.
Configurazione server NFS
Si configura il server NFS in modo che sappia trovare il server KDC (dovrebbe già essere così in seguito all'installazione), nel file /etc/krb5.conf
:
[libdefaults] default_realm = MYREALM.ORG [realms] MYREALM.ORG = { kdc = inside.mydomain.org admin_server = inside.mydomain.org } [login] krb4_convert = false krb4_get_tickets = false
Infine il file /etc/exports
deve richiedere l'autenticazione Kerberos e usare le opzioni specifiche di NFSv4:
/home gss/krb5(fsid=0,rw,sync,no_root_squash,no_subtree_check)
Notare che dal kernel 2.6.23 la sintassi gss/krb5 è deprecata, si deve usare l'opzione sec= come suggerito da man exports(5).
Per vedere quali directory risultano esportate:
showmount -e 127.0.0.1 Export list for 127.0.0.1: /home gss/krb5
ATTENZIONE: Non esportare sottodirectory di directory già esportate, specialmente mescolando tipi di accesso diverso (host e gss/krb5, NFSv3 e NFSv4). Si potrebbe incappare nell'errore che la sottodirectory non risulta esportata come ci si aspetta. In questo esempio si pensava di esportare /home
e invece NFS cerca di esportare /
:
mountd[2937]: refused mount request from 192.168.1.2 for /home (/): not exported
Altro possibile errore: se sul server non è attivo rpc.gssd oppure rpc.svcgssd il client non viene riconosciuto:
mountd[1116]: mount request from unknown host 192.168.1.2 for /home (/home)
Ricordarsi di attivare anche rpc.idmapd, altrimenti tutti i file esportati risulteranno appartenere a nobody:nogroup.
In Debian questo significa impostare NEED_SVCGSSD=yes in /etc/default/nfs-kernel-server
e NEED_IDMAPD=yes e NEED_GSSD=yes in /etc/default/nfs-common
.
Configurazione client NFS
È indispensabile attivare il demone rpc.idmapd, impostando NEED_IDMAPD=yes in /etc/default/nfs-common
. Altrimenti user e group degli oggetti nel filesystem montato non sono corretti.
Bisogna attivare anche il demone rpc.gssd, con Debian è sufficiente impostare NEED_GSSD=yes in /etc/default/nfs-common
. Altrimenti si incappa nel seguente errore:
# mount -v -t nfs4 inside.mydomain.org:/ /nfs/inside/home -o rw,sec=krb5 mount.nfs4: Connection timed out
ATTENZIONE: Con NFSv4 la directory esportata con l'opzione fsid=0 diventa la radice NFSv4, pertanto va montata come tale, senza specificare il percorso. Altrimenti questo è il messaggio di errore:
mount -t nfs4 inside.mydomain.org:/home /nfs/inside/home -o rw,sec=krb5 mount.nfs4: mounting inside.mydomain.org:/home failed, reason given by server: No such file or directory
Quindi per montare una tantum la directory:
mount -v -t nfs4 inside.mydomain.org:/ /net/inside -o rw,sec=krb5 mount.nfs4: pinging: prog 100003 vers 4 prot tcp port 2049 inside.mydomain.org:/ on /nfs/inside type nfs4 (rw,sec=krb5)
oppure per montarla ad ogni boot si mette in /etc/fstab
:
inside.mydomain.org:/ /net/inside nfs4 rw,sec=krb5 0 0
Troubleshooting
Se si sospettano problemi di permessi conviene controllare cosa dice il demone rpc.gssd sul client. Avviare il demone con l'opzione -vvv (Debian: impostando RPCGSSDOPTS=“-vvv” in /etc/default/nfs-common
).
Ad esempio il seguente errore si risolve rinnovando il ticket Kerberos con il comando kinit(1)
:
rpc.gssd[13175]: ERROR: GSS-API: error in gss_acquire_cred(): The referenced credential has expired - No error
Qui abbiamo un problema con la risoluzione dei nomi; un nome risolve in un dirizzo IP il cui reverse lookup non risolve nel nome stesso:
# host cheope.rigacci.org cheope.rigacci.org has address 192.168.200.245 # host 192.168.200.245 245.200.168.192.in-addr.arpa domain name pointer ldap.rigacci.org.
risultano i seguenti errori nel /var/log/auth.log
del server:
krb5kdc[27119]: TGS_REQ (7 etypes {18 17 16 23 1 3 2}) 172.16.6.2: UNKNOWN_SERVER: authtime 1200091396, nfs/bari.rigacci.org@RIGACCI.ORG for nfs/ldap.rigacci.org@RIGACCI.ORG, Server not found in Kerberos database krb5kdc[27119]: TGS_REQ (1 etypes {1}) 172.16.6.2: UNKNOWN_SERVER: authtime 1200091396, nfs/bari.rigacci.org@RIGACCI.ORG for nfs/ldap.rigacci.org@RIGACCI.ORG, Server not found in Kerberos database
e i seguenti sul client:
rpc.gssd[7053]: rpcsec_gss: gss_init_sec_context: (major) Unspecified GSS failure. Minor code may provide more information - (minor) Server not found in Kerberos database
Altro errore legato al bug 413838: la negoziazione della crittografia DES (l'unica supportata dal server NFS) fallisce se sul server NFS esiste anche una chiave triple DES.
rpc.gssd[7053]: WARNING: Failed to create krb5 context for user with uid 0 with any credentials cache for server cheope.rigacci.org
sul server si legge
rpc.svcgssd[9833]: leaving poll rpc.svcgssd[9833]: handling null request rpc.svcgssd[9833]: WARNING: gss_accept_sec_context failed rpc.svcgssd[9833]: ERROR: GSS-API: error in handle_nullreq: gss_accept_sec_context(): Unspecified GSS failure. Minor code may provide more information - Key version number for principal in key table is incorrect rpc.svcgssd[9833]: sending null reply