Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 Jul 2009 12:31:57 -0400 (EDT)
From:      Rick Macklem <rmacklem@uoguelph.ca>
To:        freebsd-fs@freebsd.org
Subject:   Kerberized NFS doc (raw text before I get it on a wiki)
Message-ID:  <Pine.GSO.4.63.0907031228190.8643@muncher.cs.uoguelph.ca>

next in thread | raw e-mail | index | archive | help
Ok, here's the raw text that I plan on putting on a wiki as a starting
point for documenting how to use set up Kerberized NFS on FreeBSD8.

Any comments w.r.t. it are welcome. I'll probably put it:
http://code.google.com/p/macnfsv4 under the wiki tab
in a day or so.

Hopefully it is some use, rick
--- first draft of doc ---
Setting up Kerberized NFS (more correctly: NFS using RPCSEC_GSS authentication
via the kerberos5 mechanism) on FreeBSD8/CURRENT:

Before we get started, here are a few preliminary things you need to know:
(Lets assume the default Realm is CIS.UOGUELPH.CA with systems called
nfs-client.cis.uoguelph.ca and nfs-server.cis.uoguelph.ca, plus a user
called ricktst that exists in the password database on all systems with
uid == 502.)

In the GSSAPI there are two kinds of principal names, User and Host_Based.
A User principal name normally refers to a user and looks like:
 	ricktst <-- which becomes ricktst@CIS.UOGUELPH.CA in KerberosV
It normally has credentials in a credentials cache file (/tmp/krb5cc_502)
created by kinit or during the user's login process.
A Host_Based principal name also has the fully qualified host domain name
in it (so it can only be used on that host) and looks like:
 	nfs@nfs-server.cis.uoguelph.ca <-- which becomes
 		nfs/nfs-server.cis.uoguelph.ca@CIS.UOGUELPH.CA in KerberosV
and normally has credentials in a keytab file created on the KDC and
transferred to the system via some secure means. (Since this principal
will only work on the system called nfs-server.cis.uoguelph.ca, the damage
done if the keytab file is compromised on nfs-server.cis.uoguelph.ca is
is limited to that system, which has already been compromised anyhow.) These
principals have the advantage that their credentials can always be refreshed
until a new keytab entry is generated for the principal on the KDC.

For RPCSEC_GSS, there are 3 types of service which, for KerberosV are:
krb5	- Use KerberosV for user authentication, but only protect the
 	  RPC header from compromise.
krb5i	- Use KerberosV for user authentication, but also use excrypted
 	  checksums on the RPC data to protect against "man in the middle"
 	  attacks involving replacement of the RPC data.
krb5p	- Use KerberosV for user authentication, but also encrypt the RPC
 	  data, so that it isn't on the wire in clear text.

Setup:
1 - The client and server system(s) will need to be running kernels
built with the following in their kernel config(5) files:
 	options		KGSSAPI
 	device		crypto

2 - KerberosV will need to be configured on all the systems, with them all
in the same default REALM (I believe cross-REALM authentication isn't going
to work well, since the uid<->user-principal-name translations won't work
out). This can be confirmed via kinit working ok on them.

3 - All systems will need to be running the gssd daemon. The daemon can be
started at boot time by setting:
 	gssd_enable="YES"
in the /etc/rc.conf file.

4 - The server(s) will need a host based entry for "nfs" in their default
keytab file (see above).

5 - The server(s) will need "-sec" options added to the lines in /etc/exports
for the file systems being exported for Kerberized NFS access. If AUTH_SYS
access is to be allowed as well, "sys" must be specified too. For example:
 	/exp	-sec=sys:krb5:krb5i:krb5p nfs-client.cis.uoguelph.ca
 	/exp	-sec=krb5i:krb5p
would allow nfs-client.cis.uoguelph.ca to use any authentication, but other
clients would be required to use krb5i or krb5p.
For NFSv4, the "V4:" line(s) will have to have the "-sec" option added,
as well. This controls what authentication methods can be used for the
system related operations that do not have any associated file handle.
It might look like:
 	V4:	/	-sec=sys:krb5:krb5i:krb5p
(See "man exports" and "man nfsv4" for more info.)

5 - In the client, for NFSv3, the mount can usually be done by "root" using
AUTH_SYS, since that is what most mountd servers handle. However, accesses
to the file system may require that the users have valid TGTs in their
credential cache file. For example (on the client):
 	# mount -t nfs -o nfsv3,sec=krb5 nfs-server.cis.uoguelph.ca:/exp /mnt
 	- where "root" does not have a TGT
Then "ricktst" can:
 	% kinit
 	- enter KerberosV password when prompted
 	% cd /mnt
 	- and use the file system until the TGT expired
(Exactly what is allowed is determined by the NFS server, as above.)

For NFSv4, the situation is somewhat different, since there is no mountd
protocol and there are system operations related to Opens and Locks that
need to keep working until the file system is dismounted.
There are basically two ways to do this (with a third variant):
(A) - A user with a valid TGT may do the mount. For this case, the file system
     should be dismounted before the TGT expires. To do this:
 	# sysctl vfs.usermounts=1	<-- done by root
 	- Then, as the user logged in with a valid TGT
 	% mount -t nfs -o nfsv4,sec=krb5i nfs-server.cis.uoguelph.ca:/exp mydir
 	- where "mydir" is owned by the user
 	  - This will generate a warning about the mount table not being
 	    updated, but that isn't a serious problem imho.
     There are open source programs like "krenew" that can be used to help
     ensure that the TGT doesn't expire before dismounting one of these mounts.
This is the only variant supported by FreeBSD8 "out of the box".
(The entire mount path must be allowed to use the specified authentication
flavour for the mount to work. In particular, Netapp filers tend to only
allow AUTH_SYS (aka "sys") for the root directory by default and this must
be changed for the mount to work. The FreeBSD8 NFSv4 client does not know
how to switch authentication flavours dynamically, based on the server
returning NFS4ERR_WRONGSEC (err# 10016).)

(B) - Use a host based principal name in the default keytab file on the client,
     to allow the mount to be done by "root". This mount should continue to
     work, since the credentials for the host based principal in the default
     keytab file can continue to be refreshed.
     To do this form of NFSv4 mount, the kernel on the client will have to
     be patched with ftp://ftp.cis.uoguelph.ca/pub/nfsv4/freebsd-rpcsec.patch
     (available anonymous ftpable).
     It will also need an entry like:
 	nfs/nfs-client.cis.uoguelph.ca@CIS.UOGUELPH.CA in the client machine's
     default keytab file. (For the client, the first component doesn't need
     to be "nfs". For example, Solaris10 typically uses "root".)

     Then you must set the sysctl variable vfs.rpcsec.keytab_enctype to the
     numeric value for the encryption type used when creating the keytab
     entry on the KDC. (The patch is not in FreeBSD8 partly because it requires
     this pesky business of setting the encryption type. I haven't figured
     out a way to make it work without doing gss_krb5_set_allowable_enctypes()
     calls to every client side credential acquired.)
     The numeric values for the encryption types look like:
 	#define	ETYPE_DES_CBC_CRC	1
     and can be found in sys/kgssapi/krb5/kcrypto.h. (This must be done
     before the gssd daemon is started on the system.)
     Then, the mount command looks like:
     # mount -t nfs -o nfsv4,sec=krb5,gssname=nfs nfs-server.cis.uoguelph.ca:/exp /mnt

     Now, the system operations will be performed using the host based
     credential, but other operations will be performed using credentials
     for the appropriate user, such as ricktst, via their TGT.
     (This is the style used by the Solaris10 and Linux clients.)

(C) - Is a variant of (B), where the "allgssname" mount option is specified,
     which means that all accesses to the file system use the host based
     principal name in the default keytab file. This case may be useful when the
     client is actually some kind of system that runs batch processes, where the
     user's are not normally logged with valid TGTs when running them.
     The mount command would look like:
     # mount -t nfs -o nfsv4,sec=krb5i,gssname=root,allgssname nfs-server.cis.uoguelph.ca:/exp /mnt

Here are some gotchas to be aware of:
- The time of day clocks for all systems must be synchronized to within the
   clock skew specified in /etc/krb5.conf.
- KerberosV principal names are case sensitive, although DNS names are not.
   The simplest way to avoid grief is to use all lower case characters in
   your DNS host names and all upper case characters for your KerberosV
   REALM name.
- The host name resolver functions must return the fully qualified host
   name i.e. nfs-server.cis.uoguelph.ca and not nfs-server.
   If you are using /etc/hosts, put the fully qualified name first, like:
 	131.104.48.99	nfs-server.cis.uoguelph.ca nfs-server
- What to do w.r.t. ticket encryption types is beyond my limited KerberosV
   expertise, however if you stick with des-cbc-crc initially and get that
   working, you can try others later. I have been told that some Netapp filers
   only handle des-cbc-crc. (When creating keytab file entries on the KDC,
   be careful to specify the chosen encryption type and then set that type
   as the first/only type for the "default-etypes" entry in /etc/krb5.conf.)
   Also, if you are using the host based principal patch, be sure to set
   the encryption type used for the keytab entry, as above.
   If using dec-cbc-crc:
 	# sysctl vfs.rpcsec.keytab_enctype=1

Good luck with it, rick



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.GSO.4.63.0907031228190.8643>