Tunneling NFS over SSH

This recipe is for tunneling NFS traffic over SSH. This adds encryption and Public Key authentication to otherwise insecure NFS traffic.
For this recipe to work, requires NFSv4. Earlier versions were not tested, but I expect not all the functionality to work.
server configuration
Install packages:
- nfs-kernel-server
- ncat or netcat-openbsd
Configure /etc/exports. Add a line:
/export/path 127.0.0.1(insecure,... other options...)
/export/path: File system to export127.0.0.1: Loopback address, we only allow local connections.insecure: Normally, the NFS server only allows connections from ports less than 1024. This option removes that restriction. We need this because thesshtraffic is running as a normal user.
Additional NFS export options:
rw: Allow read/write accesssync: sync I/O (recommended to prevent data loss)no_subtree_check: When exporting full filesystem, this remove the subtree checks. This has to do with the fact thatNFSusesinodes. This check is needed to make sure that theinodeis within the exported filesystem sub-tree. However if you are exporting the entire filesystem, there should never be the case that aninodefalls outside thesubtree.no_root_squash: allow root accessmountpoint=/mount/path: Only export if a filesystem is mounted on/mount/path
Obtain a public/private key. Either use ssh-keygen or copy it from elsewhere.
Install authorized_keys on the account to be used for SSH/TCP forwarding:
command="nc -N localhost 2049",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa ...
This account does not need to be root. The additional settings make sure that this
key can only be used for forwarding traffic.
client configuration
This is for Ubuntu. Other distros may need different packages and/or approaches.
Install packages:
- nfs-common
- ncat (netcat-openbsd is not enough, ncat needs to support -e or -c)
Make sure the NFS server is in the SSH forwarder's known_hosts file. Use this command
to make sure this happens:
ssh -n -i $ssh_key -T \
-o StrictHostKeyChecking=accept-new \
-o BatchMode=yes \
-o ConnectTimeout=10 \
$nfs_server
In this approach we are using ncat to implement SSH forwarder. Run this
command from the /etc/rc.local file:
lport=4096
ssh_key=/path/to/ssh/private/key
ssh_opts="-o BatchMode=yes -o ConnectTimeout=10 -a -C"
nfs_srv=nfs-server
( ncat -l $lport -k --allow localhost -c "exec ssh -i $ssh_key $ssh_opts $nfs_srv" ) &
Options:
-a: disable agent forwarding-C: request compression-T: disable pty
An alternative to this is to use inetd.conf or use systemd.
At this point we are ready to mount NFS filesystems:
mount -t nfs \
-o nfsvers=4,nolock,nosuid,nodev,port=4096,sec=sys,tcp,soft,intr,fg \
localhost:/export/nfs/path \
/mnt
Options:
nfsvers=4: make sure we are running NFSv4nosuid: disable SUID executablesnodev: disable device filessec=sys: traditional UNIX security modestcp: use TCP protocolsoft,intr: how we handle CTRL+C and other errors
Caveats
showmountcommand does not show NFSv4 information.- I have not tried to use this with
autofs.autofsconfigure for NFS shares is in/etc/autofs/auto.net, but it usesshowmountcommand, so it probably would not work out of the box.
Notes
Some implementations of the nc command supports a -p source_port option. This would
remove the need to use the insecure option from the nfs export options. However this
requires netcat to run as root.
References: