Spencer's notes on NFS theShepler

Monday Feb 07, 2005

Having received a couple of questions lately about Solaris support for ssh tunneling of NFS traffic, a short description of how it can be done and what happens to NFS when ssh tunneling is used.

First thing to do is to set up the tunnel on the NFS client:

# ssh -fN -L "3049:servername:2049" servername

This sets up the ssh tunnel with the client's local port of 3049 and connects to the NFS server named 'servername' on its port 2049 (the well-known NFS server port).

Remember that the server sshd needs to be configured to allow for port forwarding. If not in place, an update to /etc/ssh/sshd_config to ensure that the config file looks like this for the port forwarding entry:

# Port forwarding
AllowTcpForwarding yes

To restart the sshd in Solaris 10, use the following after the config file change:

svcadm restart network/ssh

Once the tunnel is in place, NFS mount syntax looks like this:

# mount -o port=3049 nfs://localhost/serverpath /localpath

Note that the mount syntax is different than usual. The usual mount to the server would look like this:

# mount servername:/serverpath /localpath

Obviously, since the ssh tunnel is the preferred transport, the mount syntax might look like this:

# mount -o port=3049 localhost:/serverpath /localpath

The problem with this is that the traditional NFS version 3 client will use the MOUNT protocol to obtain the mapping between /serverpath to filehandle. However, in Solaris, there a method to redirect the use of the MOUNT protocol to an alternate port does not exist. Therefore, with the above syntax, the mount command will attempt to contact the server localhost for the MOUNT program and this is done with regular RPC mechanisms (contact the rpcbind daemon, etc.). That doesn't work. Therefore the use of the NFS URL.

The NFS URL usage directs the mount command to use only the NFS protocol to map the /serverpath to the filehandle. This will be done with the port specified in the port=3049 option. The unfortunate side effect of using the NFS URL is that NFS file locking will not be used. The reason for this is that the NFS version 2 and 3 locking support uses another RPC program; two actually: NLM and NSM. As with the MOUNT protocol usage, the locking requests won't be tunneled since there isn't an option to direct the requests via the ssh tunnel.

NFS version 4 is better

NFS version 4 may not be better for everything, but in this case, it clearly is.

With NFSv4, all of the various protocols, MOUNT, NSM, NLM, ACL, were folding into a single protocol with the use of a single port. This means that if something like the ssh tunneling is used, all of the NFSv4 traffic will travel via the specified port in the mount options. So worries about loss of file locking support or issues with the MOUNT protocol. The regular mount syntax

# mount -o port=3049 localhost:/serverpath /localpath

will work via the ssh tunnel on port 3049.

For compatibility with clients or servers that may not yet support NFSv4, the NFS URL syntax will work for NFSv4.

Note that there is one piece of functionality that will be lost for NFSv4 when using ssh tunnels. Delegation support. NFSv4's file-level delegation support requires the use of a callback RPC program. As with the problems of MOUNT, NLM use in NFSv2/v3, NFSv4 file delegation will not work over the ssh tunnels. This is an area that is being addressed in the IETF NFSv4 Working Group with the use of the SESSIONS extension that has been proposed for a NFSv4 minor version.

[update]

Restricting access to the server only?

One other thing that is nice about this approach. Since the ssh tunnel re-writes the source address of incoming NFS requests, the NFS server will see the requests as if they were coming from the server (as a client). This means that the directories that are shared can be "locked" down to provide access to the local server only and only via the ssh tunnels. For example, the /etc/dfs/dfstab could have an entry like:

share -F nfs -o rw=servername /export

and the server will only allow NFS access to /export for clients connected from ssh tunnels.

Comments:

Since NFS security (as usually implemented) hinges on the security of the client, this "feature" hints that even if the NFS client is under reasonable control, it may not be terribly difficult to establish a tunnel from a non-trusted client to an NFS server using a trusted client as a proxy.

In other words, a non-trusted NFS client stack is talking to the NFS server while the NFS server thinks that it is talking to a trusted stack that is part of the trusted client. This is somewhat similar to what happens when running the SPEC-SFS benchmark, which implements its own NFS stack.

A perusal of nfsd(1M) offers a good suggestion:

     If the NFS_PORTMON variable  is  set  in  /etc/system,  then
     clients  are  required  to  use  privileged  ports  (ports <
     IPPORT_RESERVED) to get NFS services. This variable is equal
     to  zero  by  default. This variable has been moved from the
     "nfs" module to the "nfssrv" module. To  set  the  variable,
     edit the /etc/system file and add this entry:

          set nfssrv:nfs_portmon = 1

Posted by Mike Gerdts on February 07, 2005 at 10:01 PM CST #

Is there not a better solution for providing encrypted NFS on an unsecure network than SSH tunneling it? I'd have thought that suggesting something like SSH tunneling NFS to a hardcore NFS guy would get me shot... or worse.

Posted by benr on February 07, 2005 at 10:23 PM CST #

With respect to using ssh tunneling as an appropriate security mechanism, it certainly wouldn't be my first choice but it is easier to deploy than a Kerberos infrastructure for a small number of clients. A security mechanism that is integrated by using the RPCSEC_GSS layer is really the way to go. With RPCSEC_GSS, each RPC request is authenticated for the individual user. I will put RPCSEC_GSS on my list for a future entry.

Posted by Spencer Shepler on February 08, 2005 at 12:48 AM CST #

It is true that the client now has an "open" port that is being tunneled to the server. The use of an ssh tunnel only provides an encrypted communications link; there are no further checks of the identity of the user or if the tunnel is being used for its original intent. The use of the ssh tunnel should be very limited because of this.

Posted by Spencer Shepler on February 08, 2005 at 12:53 AM CST #

Does NFSv4 still require the use of RPC Portmapper to determine what port the client should use to contact the NFS server? We use NFS over SSH, not for the encryption, but to be able to Jumpstart boxes on subnets that do not have a jumpstart or DHCP server available.

Posted by Charles on February 08, 2005 at 11:04 AM CST #

The Solaris 10 implementation of NFSv4 (the mount command) does not require interaction with the portmap/rpcbind protocol. The Solaris client will only interact with port 2049, the NFS server, when mounting and further interaction.

Posted by Spencer Shepler on February 08, 2005 at 11:29 AM CST #

This is very interesting. I have not explored NFSv4 fully. This caught my interests and I'd like to know what else has changed with v4? Could you give some examples to show the power of it? I'm definitely interested in securing NFS. Does netapp support v4 yet?

Posted by Octave Orgeron on February 08, 2005 at 04:11 PM CST #

With respect to what else has changed with NFSv4...
Since there is interest in the security area, I plan on doing my next entry on NFSv4's use of the RPCSEC_GSS framework to provide access to security mechanisms like Kerberos. After that, it seems like it would be good to review the feature set of NFSv4 and how implementations are taking advantage of them.

Posted by Spencer Shepler on February 08, 2005 at 04:24 PM CST #

Post a Comment:
Comments are closed for this entry.