Friday, June 15, 2012

HowTO Secure NFS Server


Securing NFS

NFS (Network File System) allows servers to share files over a network. But like all network services using NFS involves risks.
Here are some basic rules:
- NFS should not be enabled if not needed.
- If you must use NFS, use TCP wrapper to restrict remote access.
- Make sure you export to only those machines that you really need to.
- Use fully qualified domain names to diminish spoofing attempts.
- Export only directories you need to export.
- Export read-only wherever possible.
- Use NFS over TCP.

If you don't have shared directories to export, ensure that the NFS service is NOT enabled and running:
# service nfs status
rpc.mountd is stopped
nfsd is stopped
rpc.rquotad is stopped
# chkconfig --list nfs
nfs             0:off   1:off   2:off   3:off   4:off   5:off   6:off

You probably don't need the portmap service as well which is used by NFS (the portmap daemon registers rpc-based services for services like NFS, NIS, etc.):
# service portmap status
portmap is stopped
# chkconfig --list portmap
portmap         0:off   1:off   2:off   3:off   4:off   5:off   6:off
#

Enabling and Starting NFS Server

If you must use NFS, it can be activated using the following commands on Red Hat Linux:
chkconfig portmap on

chkconfig nfs on

service portmap start

service nfs start
The "portmap" service starts the portmap daemon.
Depending on the Linux OS distribution and version, the "nfs" service starts the rpc.rquotad, nfsd, lockd, rpciod, rpc.mountd and rpc.idmapd daemons on Red Hat Fedora Core 3 which is the OS that Red Hat Advanced Server 4 is based on. On Red Hat Advanced Server 3, the NFS service starts rpc.mountd, nfsd and rpc.rquotad.

To probe the portmapper for all registered NFS related RPC programs, you can run rpcinfo. On Red Hat Advanced Server 3, the output will look like this:
# rpcinfo -p <server>
   program vers proto   port
    100000    2   tcp    111  portmapper
    100000    2   udp   111  portmapper
    100011    1   udp   607  rquotad
    100011    2   udp   607  rquotad
    100011    1   tcp    610  rquotad
    100011    2   tcp    610  rquotad
    100003    2   udp 2049  nfs
    100003    3   udp 2049  nfs
    100003    2   tcp  2049  nfs
    100003    3   tcp  2049  nfs
    100005    1   udp   623  mountd
    100005    1   tcp    626  mountd
    100005    2   udp   623  mountd
    100005    2   tcp    626  mountd
    100005    3   udp   623  mountd
    100005    3   tcp    626  mountd
#

Restricting Incoming NFS Requests

 The portmap program and some of the NFS programs include a built-in TCP wrapper. To verify if a program includes a TCP wrapper, you can run the following commands: 

# strings /sbin/portmap | egrep "hosts.deny | hosts.allow | libwrap"
hosts_allow_table
hosts_deny_table
/etc/hosts.allow
/etc/hosts.deny
# strings /usr/sbin/rpc.rquotad | egrep "hosts.deny | hosts.allow | libwrap"
libwrap.so.0
# ldd /usr/sbin/rpc.rquotad | grep libwrap
        libwrap.so.0 => /usr/lib/libwrap.so.0 (0x00874000)
#
If hosts.deny and hosts.allow are displayed, or if libwrap is displayed, then the program includes a built-in TCP wrapper. If none of these strings are displayed, then adding the program name to /etc/hosts.deny and /etc/hosts.allow will most probably have no effect.

To block all incoming requests by default, add the following line to /etc/hosts.deny if you have not done so yet:
  ALL: ALL
Verify from a remote server that portmapper does not list any registered RPC programs:
# rpcinfo -p <server>
No remote programs registered.
#

To allow NFS mounts from trusted servers and networks only, you have to configure the servers and networks for portmap and various NFS related programs in /etc/hosts.allow. To find out which NFS programs are invoked when you start the NFS server, you can check the /etc/init.d/nfs service script. Then run the "strings <program> | egrep "hosts.deny | hosts.allow | libwrap"" command I described above.

On Red Hat Advanced Server 3, the /usr/sbin/rpc.rquotad program includes a built-in TCP wrapper. On Red Hat Fedora Core 3, /usr/sbin/rpc.mountd now also includes a built-in TCP wrapper.

 To allow NFS requests from e.g. servers test1pub.linuxhowto.in, test2pub.
linuxhowto.in , test3pub. linuxhowto.in and from the .subnet. linuxhowto.in network, the configuration in /etc/hosts.allow would look like as follows: 
  portmap:     test1pub. linuxhowto.in test2 linuxhowto.in  test3 linuxhowto.in subnet.linuxhowto.in
  rpc.mountd:  test1pub. linuxhowto.in  test2pub. linuxhowto.in  test3pub. linuxhowto.in  subnet.linuxhowto.in
  rpc.rquotad: test1pub. linuxhowto.in test2 linuxhowto.in  test3pub. linuxhowto.in subnet.linuxhowto.in 

For portmapper you can now test access from trusted servers or networks using the rpcinfo command: 
# rpcinfo -p <server>
   program vers proto   port
    100000    2   tcp    111  portmapper
    100000    2   udp   111  portmapper
    100011    1   udp   607  rquotad
    100011    2   udp   607  rquotad
    100011    1   tcp    610  rquotad
    100011    2   tcp    610  rquotad
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    100003    2   tcp    2049  nfs
    100003    3   tcp    2049  nfs
    100005    1   udp     623  mountd
    100005    1   tcp      626  mountd
    100005    2   udp     623  mountd
    100005    2   tcp      626  mountd
    100005    3   udp     623  mountd
    100005    3   tcp      626  mountd
#
If you run it from an "untrusted" server or network, you should get the following output:
# rpcinfo -p <server>
No remote programs registered.
#

Exporting NFS File Systems

To allow a client access to a filesystem or directory, the
/etc/exports serves as the access control list.

To give the network "subnet.example.com" read-only access to /pub, the entries in
/etc/exports would look like as follows:

/pub      *.subnet.linuxhowto.in(ro,sync)

It is very important NOT to give write access to NFS clients if not absolutely needed! Entries in /etc/exports are exported read-only ("ro" option) by default.

 To allow servers test1pub, test2pub and test3pub read-write access to the /data/cloud-data directory, the entries in
/etc/exports would look like as follows: 
/data/cloud-data  test1pub linuxhowto.in (rw,sync) test2pub. linuxhowto.in (rw,sync) test3pub. linuxhowto.in (rw,sync)

Note that options MUST NOT be separated from hostnames or networks with whitespace(s).
And use fully qualified domain names to diminish spoofing attempts.

All entries in
/etc/exports are exported with the root_squash option ('root squashing') by default. This means that a root user on a client machine does not have root privileges (root access) to root-owned files on exported NFS filesystems/directories. It is not recommended to turn 'root squashing" off using the no_root_squash option!

After you've made all your entries in /etc/exports, you can export all filesystems/directories using the following command:
# exportfs -a
To unexport all shared filesystems/directories, run:
# exportfs -ua

To see all shared filesystems/directories, run:
# showmount -e localhost
Export list for localhost:
/pub             *.subnet. linuxhowto.in
/data/cloud-data  test3pub.linuxhowto.in ,test2pub.linuxhowto.in ,test1pub.linuxhowto.in

Using NFS over TCP

If you need NFS, it is recommended to use NFS over TCP since NFS over UDP is not very secure. All 2.4 and 2.6 kernels support NFS over TCP on the client side. Server support for TCP appears in later 2.4 kernels, and in all 2.6 kernels.

To verify whether your server supports NFS over TCP, use the wire-test command (/usr/sbin/wire-test is part of the am-utils package). If your server supports NFS over TCP, the output looks like this:
# wire-test localhost
Network 1: wire="192.168.1.0" (netnumber= 192.168.1 ).
Network 2: wire=" 192.168.1.1" (netnumber= 192.168.1 ).
My IP address is 0rgh100101.
NFS Version and protocol tests to host "localhost"...
        testing vers=2, proto="udp" -> found version 2.
        testing vers=3, proto="udp" -> found version 3.
        testing vers=2, proto="tcp" -> found version 2.
        testing vers=3, proto="tcp" -> found version 3.
#
If the server does not support NFS over TCP, the output will look like this:
# wire-test localhost

Network 1: wire="192.168.1.0" (netnumber= 192.168.1 ).
Network 2: wire=" 192.168.1.1" (netnumber= 192.168.1 ).
My IP address is 0rgh100101.
NFS Version and protocol tests to host "localhost"...
        testing vers=2, proto="udp" -> found version 2.
        testing vers=3, proto="udp" -> found version 3.
        testing vers=2, proto="tcp" -> failed!
        testing vers=3, proto="tcp" -> failed!
#

To mount a shared directory using NFS over TCP, use the "proto=tcp" mount option:
# mount -o proto=tcp <nfs_server_name>:/pub /usr/local/pub
Make sure the target directory, in this example /usr/local/pub, exists on the client.

You can verify the NFS over TCP mount using the mount command:
# mount
...
nfstestserver:/pub on /usr/local/pub type nfs (rw,proto=tcp,addr=192.168.10.8)

To have the shared directory mounted on the client at boot time, use the /etc/fstab file.
For the above example, the /etc/fstab entry could look like this:


nfstestserver:/pub  /usr/local/pub      nfs   rsize=8192,wsize=8192,timeo=14,intr,tcp  0 0



Note that this document comes without warranty of any kind. But every effort has been made to provide the information as accurate as possible. I welcome emails from any readers with comments, suggestions, and corrections at webmaster_at admin@linuxhowto.in

                                               Copyright © 2012 LINUXHOWTO.IN

No comments:

Post a Comment