====== 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** * [[http://aput.net/~jheiss/krbldap/|Replacing NIS with Kerberos and LDAP HOWTO]] * [[http://www-theorie.physik.unizh.ch/~dpotter/howto/kerberos|Kerberos/LDAP/NFSv4 HOWTO]] * [[http://www.freesoftwaremagazine.com/blogs/securing_nfs]] * [[http://mailman.mit.edu/pipermail/kerberos/2007-May/011581.html]] * [[http://gentoo-wiki.com/HOWTO_NFSv4|HOWTO NFSv4]] * [[http://www.citi.umich.edu/projects/nfsv4/linux/faq/|Linux NFSv4 FAQ]] ===== 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 **[[http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=413838|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 **[[http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=413838|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