Hack #61. Share Files Securely in Unix

Use SFS to help secure your remote filesystems.

If you are using Unix systems and sharing files on your network, you are most likely using the Network File System (NFS). However, NFS has many security problems, not only with individual implementations, but also in the design of the protocol itself. For instance, if a user can spoof an IP address and mount an NFS share that is only meant for a certain computer, that user will essentially have root access to all the files on that share. In addition, NFS employs secret file handles that are used with each file request. Since NFS does not encrypt its traffic, it’s easy for attackers to guess these file handles. If they guess correctly, they effectively gain total root access to the remote filesystem.

The Self-certifying File System (SFS), available at http://www.fs.net, fixes all of these problems by employing a drastically different design philosophy. NFS was created with the notion that you can (and should) trust your network. SFS has been designed from the beginning with the idea that no network should ever be trusted until it can definitively prove its identity.

To accomplish this level of security, SFS makes use of public keys on both the client and server ends. It uses these keys to verify the identity of servers and clients, and it also provides access control on the server side. One particularly nice side effect of such strong encryption is that SFS provides a much finer-grained level of access control than NFS. With NFS, you are limited to specifying which hosts can or cannot connect to a given exported filesystem. In order to access an SFS server, a user must create a key pair and then authorize the key by logging into the SFS server and registering the key manually.

Building SFS can take up quite a lot of disk space. Before you attempt it, make sure you have at least 550 MB of space available on the filesystem on which you’ll be compiling SFS. You will also need to make sure that you have the GNU Multiple Precision (GMP) math library (http://www.swox.com/gmp/) installed.

Before you begin to build SFS, you also need to create a user and group for SFS’s daemons. By default, these are both called sfs. If you want to use a different user or group, you can do this by passing options to the configure script.

Once your system is ready, check out the most recent version of the SFS code (hit Enter at the password prompt):

$ cvs -d :pserver:sfscvs@cvs.fs.net:/cvs login
Logging in to :pserver:sfscvs@cvs.fs.net:2401/cvs
CVS password: 

$ cvs -z5 -d :pserver:sfscvs@cvs.fs.net:/cvs co -P sfs1
         

Then, change to the sfs1 directory and build SFS by running this command:

$ sh ./setup && ./configure && make
         

Once that process is finished, become root and type make install.

If you want to use a user and group other than sfs, you can specify these with the --with-sfsuser and --with-sfsgroup options:

$ ./configure --with-sfsuser=
            
               nobody
            
             --with-sfsgroup=
            
               nobody
            
         

Building SFS can take quite a bit of time, so you might want to take the opportunity to enjoy a cup of coffee, a snack, or maybe even a full meal, depending on the speed of your machine and the amount of memory it has.

After SFS has finished building and you have installed it, you can test it out by connecting to the SFS project’s public server. To do this, start the SFS client daemon, sfscd , and then change to the directory under which the SFS server will be mounted:

# sfscd
# cd /sfs/@sfs.fs.net,uzwadtctbjb3dg596waiyru8cx5kb4an
# ls
CONGRATULATIONS  cvs  pi0  reddy  sfswww
# cat CONGRATULATIONS
You have set up a working SFS client.
#

sfscd automatically creates the /sfs directory and the directory for the SFS server.

Tip

SFS relies on the operating system’s portmap daemon and NFS mounter; you’ll need to have those running before running the client.

To set up an SFS server, first log into your server and generate a public and private key pair:

# mkdir /etc/sfs
# sfskey gen -P /etc/sfs/sfs_host_key
         

sfskey will ask you to bang on the keys for a little while in order to gather entropy for the random number generator.

Now, you will need to create a configuration file for sfssd, the SFS server daemon. Create a file in /etc/sfs called sfsrwsd_config, which is where you’ll configure the filesystem namespace that SFS will export to other hosts.

If you want to export the /home filesystem, create a configuration file like this:

Export /var/sfs/root /
Export /home /home

Then, create the /var/sfs/root and /var/sfs/home directories. After that, create NFS exports so that the /home filesystem can be mounted under /var/sfs/root/home. These are then re-exported by sfssd. The NFS exports need to allow mounting only from localhost.

Here’s what /etc/exports looks like for exporting /home:

/var/sfs/root    localhost(rw)
/home        localhost(rw)

This exports file is for Linux. If you are running the SFS server on another operating system (such as Solaris or OpenBSD), consult your operating system’s mountd manpage for the proper way to add these shares.

Now, start your operating system’s NFS server. Once NFS has started, you can start sfssd. After attempting to connect to the sfssd server, you should see some messages like these in your logs:

Jun 10 10:14:47 colossus : sfssd: version 0.8pre, pid 30880
Jun 10 10:14:47 colossus : rexd: version 0.8pre, pid 30882
Jun 10 10:14:47 colossus : sfsrwsd: version 0.8pre, pid 30884
Jun 10 10:14:47 colossus : rexd: serving @colossus.nnc,kkvt3kzmqry5gy4s3es97yu9gip2f967
Jun 10 10:14:47 colossus : rexd: spawning /usr/local/lib/sfs-0.8pre/ptyd
Jun 10 10:14:47 colossus : sfsauthd: version 0.8pre, pid 30883
Jun 10 10:14:47 colossus : sfssd: listening on TCP port 4
Jun 10 10:14:47 colossus : sfsauthd: dbcache_refresh_delay = 0
Jun 10 10:14:47 colossus : sfsauthd: Disabling authentication server cache refresh...
Jun 10 10:14:47 colossus rpc.mountd: authenticated mount request from localhost.localdomain:956 for /var/sfs/root (/var/sfs/root)
Jun 10 10:14:47 colossus : sfsauthd: serving @colossus.nnc,kkvt3kzmqry5gy4s3es97yu9gip2f967
Jun 10 10:14:47 colossus rpc.mountd: authenticated mount request from localhost.localdomain:956 for /home (/home)
Jun 10 10:14:47 colossus : sfsrwsd: serving /sfs/@colossus.nnc,kkvt3kzmqry5gy4s3es97yu9gip2f967

The last log entry shows the path that users can use to mount your filesystem. Before mounting any filesystems on your server, users will have to create a key pair and register it with your server. They can do this by logging into your server and running the sfskey command:

$ sfskey register
sfskey: /home/andrew/.sfs/random_seed: No such file or directory
sfskey: creating directory /home/andrew/.sfs
sfskey: creating directory /home/andrew/.sfs/authkeys
/var/sfs/sockets/agent.sock: No such file or directory
sfskey: sfscd not running, limiting sources of entropy
Creating new key: andrew@colossus.nnc#1 (Rabin)
       Key Label: andrew@colossus.nnc#1
Enter passphrase: 
           Again: 

sfskey needs secret bits with which to seed the random number generator.
Please type some random or unguessable text until you hear a beep:
DONE            
UNIX password: 
colossus.nnc: New SRP key: andrew@colossus.nnc/1024
wrote key: /home/andrew/.sfs/authkeys/andrew@colossus.nnc#1

Alternatively, if you already have an existing key pair on another server, you can type sfskey user @ otherserver instead. This command retrieves the key from the remote machine and registers it with the server you are currently logged into.

Now that you have registered a key with the server, you can log into the SFS server from another machine. This is also done with the sfskey program:

$ sfskey login andrew@colossus.nnc
Passphrase for andrew@colossus.nnc/1024: 
SFS Login as andrew@colossus.nnc

Now, try to access the remote server:

$ cd /sfs/@colossus.nnc,fd82m36uwxj6m3q8tawp56ztgsvu7g77
$ ls
home

As you can see, SFS is a powerful tool for sharing files across a network, and even across the Internet. Not only does it provide security, but it also provides a unique and universal method for referencing a remote host and its exported filesystems. You can even put your home directory on an SFS server, simply by linking the universal pathname of the exported filesystem /home.