NFS is a very useful tool, but its shortcomings must be kept in mind especially where security matters are concerned: all data goes over the network in the clear (a
sniffer can intercept it); the server enforces access restrictions based on the client's IP address (which can be spoofed); and finally, when a client machine is granted access to a misconfigured NFS share, the client's root user can access all the files on the share (even those belonging to other users) since the server trusts the username it receives from the client (this is a historical limitation of the protocol).
Since NFS trusts the information it receives from the network, it is vital to ensure that only the machines allowed to use it can connect to the various required RPC servers. The firewall must also block
IP spoofing so as to prevent an outside machine from acting as an inside one, and access to the appropriate ports must be restricted to the machines meant to access the NFS shares.
Other RPC services may be required for NFS to work optimally, including
rpc.mountd
,
rpc.statd
and
lockd
. However, these services use a random port (assigned by the
portmapper) by default, which makes it difficult to filter traffic targeting these services. The Falcot Corp administrators found a work-around for this problem, described below.
The first two services mentioned above are implemented by user-space programs, started respectively by
/etc/init.d/nfs-kernel-server
and
/etc/init.d/nfs-common
. They provide configuration options to force ports; the relevant files to modify to always use these options are
/etc/default/nfs-kernel-server
and
/etc/default/nfs-common
.
Example 11.23. The /etc/default/nfs-kernel-server
file
# Number of servers to start up
RPCNFSDCOUNT=8
# Options for rpc.mountd
RPCMOUNTDOPTS="-p 2048"
Example 11.24. The /etc/default/nfs-common
file
# Options for rpc.statd.
# Should rpc.statd listen on a specific port?
# If so, set this variable to a statd argument like: "--port 1000".
STATDOPTS="-p 2046 -o 2047"
# Are you _sure_ that your kernel does or does not need a lockd daemon?
# If so, set this variable to either "yes" or "no".
NEED_LOCKD=
Once these changes are made and the services are restarted,
rpc.mountd
uses port 2048;
rpc.statd
listens on port 2046 and uses port 2047 for outgoing connections.
The
lockd
service is handled by a kernel
thread (lightweight process); this feature is built as a module on Debian kernels. The module has two options allowing to always choose the same port,
nlm_udpport
and
nlm_tcpport
. In order for these options to be systematically used, there needs to be a
/etc/modprobe.d/lockd
file such as the following:
Example 11.25. The /etc/modprobe.d/lockd
file
options lockd nlm_udpport=2045 nlm_tcpport=2045
Once these parameters are set, it becomes easier to control access to the NFS service from the firewall in a fine-grained way by filtering access to ports 111 and 2045 through 2049 (both UDP and TCP).
The NFS server is part of the Linux kernel; in kernels provided by Debian it is built as a kernel module. If the NFS server is to be run automatically on boot, the
nfs-kernel-server package should be installed; it contains the relevant start-up scripts.
The NFS server configuration file,
/etc/exports
, lists the directories that are made available over the network (
exported). For each NFS share, only the given list of machines is granted access. More fine-grained access control can be obtained with a few options. The syntax for this file is quite simple:
/directory/to/share machine1(option1,option2,...) machine2(...) ...
Each machine can be identified either by its DNS name or its IP address. Whole sets of machines can also be specified using either a syntax such as
*.falcot.com
or an IP address range such as
192.168.0.0/255.255.255.0
or
192.168.0.0/24
.
Directories are made available as read-only by default (or with the
ro
option). The
rw
option allows read-write access. NFS clients typically connect from a port restricted to root (in other words, below 1024); this restriction can be lifted by the
insecure
option (the
secure
option is implicit, but it can be made explicit if needed for clarity).
By default, the server only answers an NFS query when the current disk operation is complete (
sync
option); this can be disabled with the
async
option. Asynchronous writes increase performance a bit, but they decrease reliability since there's a data loss risk in case of the server crashing between the acknowledgement of the write and the actual write on disk. Since the default value changed recently (as compared to the historical value of NFS), an explicit setting is recommended.
In order to not give root access to the filesystem to any NFS client, all queries appearing to come from a root user are considered by the server as coming from the
anonymous
user. This behaviour corresponds to the
root_squash
option, and is enabled by default. The
no_root_squash
option, which disables this behavior, is risky and should only be used in controlled environments. The
anonuid=uid
and
anongid=gid
options allow specifying another fake user to be used instead of
anonymous
.
Other options are available; they are documented in the
exports(5) manual page.
As with other filesystems, integrating an NFS share into the system hierarchy requires mounting. Since this filesystem has its peculiarities, a few adjustments were required in the syntaxes of the
mount
command and the
/etc/fstab
file.
Example 11.26. Manually mounting with the mount
command
#
mount -t nfs -o rw,nosuid arrakis.interne.falcot.com:/srv/shared /shared
Example 11.27. NFS entry in the /etc/fstab
file
arrakis.interne.falcot.com:/srv/shared /shared nfs rw,nosuid 0 0
The entry described above mounts, at system startup, the
/srv/shared/
NFS directory from the
arrakis
server into the local
/shared/
directory. Read-write access is requested (hence the
rw
parameter). The
nosuid
option is a protection measure that wipes any
setuid
or
setgit
bit from programs stored on the share. If the NFS share is only meant to store documents, another recommended option is
noexec
, which prevents executing programs stored on the share.
The
nfs(5) manual page describes all the options in some detail.