This blog posting is a part of a series of blog postings:

Next it’s time to finally get files moving between the servers. For this we use NFSv4 that supports kerberos out-of-the-box also in Ubuntu. This part is based on the newest Lucid packages in the repositories, which should be pretty close to alpha 3 now.

The following documents were used to get the configuration working:

The goal of the setup is to have a single file server that shares the following directories to clients over NFSv4 with kerberos authentication:

  • /home/school1
  • /home/school2
  • /home/school3

The server will not allow root to access other users’ files which makes it possible to export the shares in potentially hostile environments as the compromise of a single client host does not expose all contents of the file server.

Server settings

The following packages are needed on the server:

apt-get install nfs-kernel-server nfs-common

Unlike NFSv3, NFSv4 uses a separate directory structure to share the directories. The actual content is mounted with mount –bind under this directory. Here we place the directories under /export:

sudo mkdir /export
sudo mkdir /export/home

Then we instruct in /etc/fstab that /home should be mounted under /export/home. The following should be added in bottom of /etc/fstab:

/etc/fstab

/home    /export/home   none    bind  0  0

After this /export/home can be mounted with the following command and it is also automatically mounted when the system boots:

sudo mount /export/home

Next configure the exports in /etc/exports to be exported to all nfs4 clients using kerberos:

/etc/exports

/export         gss/krb5(rw,fsid=0,async,subtree_check,no_root_squash,crossmnt)
/export/home    gss/krb5(rw,async,subtree_check,no_root_squash)
/export/home/school1	gss/krb5(rw,async,subtree_check,root_squash,crossmnt)
/export/home/school2	gss/krb5(rw,async,subtree_check,root_squash,crossmnt)
/export/home/school3	gss/krb5(rw,async,subtree_check,root_squash,crossmnt)

Next configure NFS to use kerberos:

/etc/default/nfs-common

NEED_STATD=
STATDOPTS=
NEED_IDMAPD=yes
NEED_GSSD=yes

/etc/default/nfs-kernel-server

RPCNFSDCOUNT=10
RPCNFSDPRIORITY=0
RPCMOUNTDOPTS=
NEED_SVCGSSD=yes
RPCSVCGSSDOPTS=

idmapd.conf needs to configured with proper Domain name for user/group name mappings:
/etc/idmapd.conf

[General]

Verbosity = 0
Pipefs-Directory = /var/lib/nfs/rpc_pipefs
Domain = EDU.EXAMPLE.ORG

[Mapping]

Nobody-User = nobody
Nobody-Group = nogroup

The NFS server version in Lucid supports only DES encryption which is not enabled by default. There is more information available in the bug reports:

For now DES can be enabled with the following settings:
/etc/krb5.conf

[libdefaults]
  allow_weak_crypto = true
  default_tgs_enctypes = des-cbc-crc
  default_tkt_enctypes = des-cbc-crc

Next we need to create kerberos principals for the server and the clients. In this example all the principals are created on the server and copied to the clients. It is also possible to use kadmin remotely from the client machines.

sudo kadmin.local -q "addprinc -randkey nfs/server.edu.example.org"
sudo kadmin.local -q "ktadd -e des-cbc-crc:normal nfs/server.edu.example.org"

sudo kadmin.local -q "addprinc -randkey nfs/client1.edu.example.org"
sudo kadmin.local -q "ktadd -e des-cbc-crc:normal -k client1.keytab nfs/client1.edu.example.org"

sudo kadmin.local -q "addprinc -randkey nfs/client2.edu.example.org"
sudo kadmin.local -q "ktadd -e des-cbc-crc:normal -k client2.keytab nfs/client2.edu.example.org"

Now copy the client1.keytab and client2.keytab to /etc/krb5.keytab on the client machines and make them only readable by root.

The server should now be ready after restarting the services:

sudo service gssd start
sudo service rpc_pipefs start
sudo /usr/sbin/rpc.gssd
sudo service idmapd start

sudo /etc/init.d/nfs-kernel-server restart

The server functionality can be tested by trying to mount one of the exported shares locally:

sudo mount -t nfs4 -o sec=krb5 server.edu.example.org:/home/school1 /mnt

Client settings

The following packages are needed on the client machines:

apt-get install nfs-common krb5-user

To avoid having to configure the kerberos server settings on each client separately, one can use DNS to store the settings as described in the previous posting.

/etc/krb5.conf

[libdefaults]
  default_realm = EDU.EXAMPLE.ORG
  allow_weak_crypto = true
  default_tgs_enctypes = des-cbc-crc
  default_tkt_enctypes = des-cbc-crc
  dns_lookup_kdc = true
  dns_lookup_realm = true

/etc/default/nfs-common – idmapd and gssd need to be enabled

NEED_STATD=
STATDOPTS=
NEED_IDMAPD=yes
NEED_GSSD=yes
RPCGSSDOPTS="-vvv -rrr"  # for debugging

/etc/idmapd.conf – Domain must match the name defined on the server for user and group name mapping to work

[General]

Verbosity = 0
Pipefs-Directory = /var/lib/nfs/rpc_pipefs
Domain = EDU.EXAMPLE.ORG

[Mapping]

Nobody-User = nobody
Nobody-Group = nogroup

After configuration nfs-common needs to be restarted (modules need to be loaded if they haven’t been loaded automatically):

sudo modprobe nfs
sudo modprobe rpcsec_gss_krb5

sudo service idmapd start
sudo service gssd start
sudo service portmap restart

Mounting the share should now work with mount command:

sudo mount -t nfs4 -o sec=krb5 server.edu.example.org:/home/school1 /home/school1

If there are problems, restarting the client machine may help as sometimes picking up the kerberos setting hasn’t worked for me. I’m probably missing some service that requires restarting..

At this point we have no kerberos ticket, so the user should not be able to enter his own home directory:

user$ cd /home/school1/user
-bash: cd: /home/school1/user: Permission denied

After getting the ticket it should work:

user$ kinit user@EDU.EXAMPLE.ORG
Password for user@EDU.EXAMPLE.ORG:
user$ cd /home/school1/user

Root squash should also prevent root from entering directories for other users on the client machine:

user$ cd /home/school1/otheruser
-bash: cd: /home/school1/otheruser: Permission denied

# cd /home/school1/otheruser
-bash: cd: /home/school1/otheruser: Permission denied

Now give it a reboot and try again. Everything should be now working.

Veli-Matti Lintu