Table of Contents

Traditional NFS contains essentially no security features. NFS assumes that the physical network is secure, and all machines on it are uncompromised. If an attacker has root access to any machine on the network, he can read or write to any location on the NFS file system. To allow NFS to be used on insecure networks, version 4 of that protocol added optional security extensions using Kerberos. This document will describe how to configure FreeBSD to use secure NFS as either a client or a server. There are three steps: authentication, authorization, and NFS.

Authentication

With NFSv4, the problem of authenticating a user is solved by Kerberos. Kerberos is a trusted third party authentication service. An NFS server and an NFS user separately prove their identities to a KDC server, which issues them cryptographically signed tickets asserting their successful authentication. Then the server and user can trust each other. Any secure NFS network must contain a Kerberos KDC server. Configuring Kerberos on FreeBSD is described at https://www.freebsd.org/doc/handbook/kerberos5.html. From Kerberos's perspective, both NFS servers and NFS clients are Kerberos clients. After configuring your NFS machines as Kerberos clients, you must create a static NFS service ticket on any NFS servers. If your KDC server is Heimdal, start kadmin and use these commands:

kadmin> add --random-key --keytab=/tmp/my_nfs_server.keytab nfs/my_nfs_server.mydomain.com
kadmin> ext_keytab nfs/my_nfs_server.mydomain.com

then copy the keytab file to your my_nfs_server and either move it to /etc/krb5.keytab or merge it to an existing /etc/krb5.keytab with one of the following commands:

# Move the temporary keytab file to /etc/krb5.keytab
mv /tmp/my_nfs_server.keytab /etc/krb5.keytab
chown root:wheel /etc/krb5.keytab
chmod 600 /etc/krb5.keytb
# OR, merge the temporary keytab file with an existing /etc/krb5.keytab
ktutil copy /tmp/my_nfs_server.keytab /etc/krb5.keytab
rm /tmp/my_nfs_server.keytab

Authorization

Authentication is the process of determining whether a user is whom says he says he is. Authorization, on the other hand, is the process of determining which operations are allowed for which users. Kerberos does not provide authorization, and NFSv4 does not specify how authorization is to be performed. On FreeBSD, it is performed by the kernel using the traditional UNIX file attributes, but there is a catch: unlike NFSv3, NFSv4 does not transmit UIDs across the wire. Instead, it transmits user identifiers as strings in the format “username@domain”. FreeBSD must translate these strings into UIDs, and that is handled by PAM. There are many ways to configure PAM to manage users; here are the most common. As a rule of thumb, if you can do id <username> for any user, then you've successfully configured PAM and NFSv4 will work for that user.

Local users only

The simplest setup is to manage users separately on all machines, using the regular pw, adduser, etc utilities. This method requires no special configuration, but is tedious as changes must be synchronized on multiple machines. In particular, each account must have the same UID on all machines. This method is only practical for the smallest networks.

NIS

NIS is a mature directory service that is well integrated into FreeBSD. If you follow the directions at https://www.freebsd.org/doc/handbook/network-nis.html , then NFSv4 user mapping will work with no further modifications.

ActiveDirectory

ActiveDirectory is a proprietary product from Microsoft that combines Kerberos, LDAP, and other protocols into a single package. It can be used to manage users on networks with mixed Windows and Unix machines. From FreeBSD's perspective, ActiveDirectory is both the KDC and LDAP server. To use ActiveDirectory with Kerberos, add these lines to the [libdefaults] section of /etc/krb5.conf on every machine. Your Windows Domain is identical to your Kerberos Realm.

default_realm = <MY_WINDOWS_DOMAIN>
dns_lookup_realm = true
dns_lookup_kdc = true
forwardable = yes

As described above, you will need to generate a static NFS service ticket. This is significantly different than with Heimdal. Follow these instructions:

  1. Using ActiveDirectory's GUI, create a Computer account named nfs<SERVERNAME>. For example, if your NFS server is named frank.example.com, create a Computer account named nfsFrank.
  2. From the Windows CLI, run ktpass -princ nfs/<FQDN>@<REALM_DOMAIN> mapuser <REALM>\<ACCOUNT>$ +rndPass -out <ACCOUNT>.keytab. For example, if your NFS server is named frank.example.com and your Windows Domain is “EXAMPLE.COM”, you would run ktpass -princ nfs/frank.example.com@EXAMPLE.COM mapuser EXAMPLE\nfsFrank$ +rndPass -out nfsFrank.keytab
  3. Transfer the temporary keytab file to the NFS server
  4. As described above, move or merge the temporary keytab file to /etc/krb5.keytab.

TODO: describe how to connect PAM to ActiveDirectory for user id mapping

NFS

Strictly speaking, we haven't been dealing with NFS at all up until this point. Once Kerberos and PAM are configured, NFS can be configured like normal according to nfsv4(4), exports(5), and mount_nfs(8). Unlike NFSv3, with Kerberized NFSv4 each user (not system) must have a Kerberos ticket in order to access the NFS file system. On a FreeBSD client, type “kinit” to check out a Kerberos ticket. The user who performs the mount must also have a Kerberos ticket. Optionally, you can use the static service ticket for mounting. This way, you can mount at boot time and the mount will stay available for as long as the static service ticket is valid (usually forever). To do this, use the gssname option in your client's /etc/fstab file.

Security Flavors

NFSv4 supports four flavors of security. Increasing levels provide more security but impose a performance penalty. You must choose the flavor appropriate for your installation. Security flavors are specified in /etc/exports on a per-export basis. That means they may vary per export, and also per client IP or network. The four flavors are:

Tips

vfs.nfsd.issue_delegations=1

Troubleshooting

The client can mount a share, but ls shows it to be empty, and dmesg shows nfsv4 client/server protocol prob err=10020

The server has mounted or unmounted its exports after starting mountd. The solution is to restart mountd.

A linux client says Remote I/O error during mount, and a packet trace shows that the server returned NFS4ERR_SERVERFAULT

Some linux clients seem to request krb5i even if you try to use plain krb5. Try setting sec=krb5,krb5i in the server's exports file.