Skip to content

Instantly share code, notes, and snippets.

@thwarted
Last active November 21, 2017 14:59
Show Gist options
  • Save thwarted/8953045 to your computer and use it in GitHub Desktop.
Save thwarted/8953045 to your computer and use it in GitHub Desktop.
pure nfsv4 autofs dynamic map (doesn't rely on nfsv3 mountd)
#!/bin/bash
# name this script /etc/auto.nfs4 and make it executable
PATH=/bin
tryconnect() {
local host="$1"
# if you don't have nmap-ncat, but your bash does support pseudo-redirection
# from /dev/tcp, you can use the following
# timeout 1 bash -c "cat < /dev/null > /dev/tcp/$host/2049' >/dev/null 2>&1
ncat -w 1 "$host" 2049 < /dev/null >/dev/null 2>&1;
}
validkey() {
# make sure the key isn't empty and contains only
# alphanumeric, dot, and dash (valid DNS names)
local key="$1"
[[ -n "$key" ]] &&
echo "$key" | grep -sqvE '[^[:alnum:].-]'
}
key="$1"
if validkey "$key"; then
if tryconnect "$key"; then
logger -t auto.nfs4 "$key listening on 2049, trying to automount"
echo -fstype=nfs4,hard,intr,nodev,nosuid $key:/
exit 0
fi
logger -t auto.nfs4 "$key not listening on port 2049, assuming no nfsv4 server"
else
logger -t auto.nfs4 "\"$key\" is invalid, ignoring"
fi
exit 1
# If auto.master contains
# +dir:/etc/auto.master.d
# then this file can go in /etc/auto.master.d/net.autofs
/net program:/etc/auto.nfs4 fstype=nfs4 --timeout=30 noatime
# otherwise, put the above line in /etc/auto.master
# you'll also want to comment out any other /net entries
# in /etc/auto.master
# the --timeout=30 above will have autofs umount the filesystem
# after 30 seconds of inactivity. you may want to increase that.

autofs supports a -hosts map, which looks like this:

#
# NOTE: mounts done from a hosts map will be mounted with the
#       "nosuid" and "nodev" options unless the "suid" and "dev"
#       options are explicitly given.
#

/net   -hosts

This apparently invokes /etc/auto.net which uses (k)showmount to get a list of exported filesystems from the remote machine. Unfortunately, this requires the nfsv3 mountd to be running/available on the remote machine, which you may not have available on a pure nfsv4 setup.

Because of the way nfsv4 works with the pseudo-root filesystem that dynamically exposes the list of available filesystems on a per-client basis, just the root export needs to be exposed. The server enumerates the available filesystems for the client via the pseudo-root, so this just needs to know about, and attempt to mount, targetmachine:/, not all the paths listed in /etc/exports on the remote machine as is necessary for nfsv3.

But we only want to attempt to mount it if it looks like nfsv4 is running, otherwise the client program could pause while attempting to connect to an inaccessible machine. A simplistic TCP connect test, with a 1 second time out, is used to see if there is an nfsv4 server on the remote machine.

Inspiration from https://bugzilla.redhat.com/show_bug.cgi?id=643142

@NiceGuyIT
Copy link

This was exactly what I was looking for: a pure NFSv4 implementation for autofs. Thanks!

I ran into a few problems during implementation though. Since GitHub doesn't support issues on gists, I forked it and commenting here.

  • /bin is too restrictive. nc, ncat and timeout are in /usr/bin on CentOS 6.
  • tryconnect() now checks for nc, ncat and timeout in that order.
  • ncat 5.51 from the nmap RPM hangs in certain situations. Using /dev/zero fixes the issue for NFS on CentOS 6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment