How can I configure a system as an NFS server which sits behind a firewall with NFS clients outside of the firewall?

http://kbase.redhat.com/faq/FAQ_85_5928.shtm

Resolution:

Release Found: Red Hat Enterprise Linux 4

Symptom:
NFS relies on portmap to assign the ports on which it will listen. One side effect of this is that the ports are randomly assigned, so each time NFS is restarted the ports will change. This can make it difficult to run an NFS server behind a firewall which only allows access to specific ports on the system.

Solution:
The first step is to assign a permanent port number to each of the NFS services (rquotad, mountd, statd, and lockd). While they can use any unused ports greater than 1024, it is recommended that you first consult the file /etc/services to find a valid unused port range. The following examples use the range 10000-10005.

The majority of the ports are configured through the file /etc/sysconfig/nfs. You will need to create this file if it does not exist. It should look similar to the following example:

# NFS port numbers
STATD_PORT=10002
STATD_OUTGOING_PORT=10003
MOUNTD_PORT=10004
RQUOTAD_PORT=10005

The lockd service is configured differently from the others because it is compiled as a kernel module. To set the port which lockd uses, add these options in the /etc/sysconfig/nfs file:

LOCKD_UDPPORT=30001
LOCKD_TCPPORT=30001

where “30001” can be replaced with any port that is available and can be assigned for use.

After these configuration changes, you can view the port assignments with the command rpcinfo -p <hostname>

# rpcinfo -p localhost
   program vers proto   port
    100000    2   tcp    111  portmapper
    100000    2   udp    111  portmapper
    100021    1   udp  10001  nlockmgr
    100021    3   udp  10001  nlockmgr
    100021    4   udp  10001  nlockmgr
    100021    1   tcp  10000  nlockmgr
    100021    3   tcp  10000  nlockmgr
    100021    4   tcp  10000  nlockmgr
    100024    1   udp  10002  status
    100024    1   tcp  10002  status
    100011    1   udp  10005  rquotad
    100011    2   udp  10005  rquotad
    100011    1   tcp  10005  rquotad
    100011    2   tcp  10005  rquotad
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100003    2   tcp   2049  nfs
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100005    1   udp  10004  mountd
    100005    1   tcp  10004  mountd
    100005    2   udp  10004  mountd
    100005    2   tcp  10004  mountd
    100005    3   udp  10004  mountd
    100005    3   tcp  10004  mountd

At this point, the ports will remain the same when NFS is restarted. The following is a list of ports which need to be opened on the firewall:

  • 111: portmap (tcp/udp)
  • 2049: nfs (tcp/udp)
  • 10000: example lockd (tcp)
  • 10001: example lockd (udp)
  • 10002: example statd/status (tcp/udp)
  • 10003: example statd/status outgoing (tcp/udp)
  • 10004: example mountd (tcp/udp)
  • 10005: example rquotad (tcp/udp)

You can now open these ports on the firewall to allow remote clients to mount a share on the server. If you are using iptables, the following commands can be used to add inbound/outbound rules to allow access to these ports. Note that this is only an example, as your specific firewall rules may differ:

# iptables -A INPUT -p tcp -m tcp --dport 111 -j ACCEPT
# iptables -A INPUT -p udp -m udp --dport 111 -j ACCEPT
# iptables -A INPUT -p tcp -m tcp --dport 2049 -j ACCEPT
# iptables -A INPUT -p udp -m udp --dport 2049 -j ACCEPT
# iptables -A INPUT -p tcp -m tcp --dport 10000 -j ACCEPT
# iptables -A INPUT -p udp -m udp --dport 10001 -j ACCEPT
# iptables -A INPUT -p tcp -m tcp --dport 10002:10005 -j ACCEPT
# iptables -A INPUT -p udp -m udp --dport 10002:10005 -j ACCEPT
# iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -A INPUT -j REJECT --reject-with icmp-port-unreachable
# iptables -A OUTPUT -p tcp -m tcp --dport 111 -j ACCEPT
# iptables -A OUTPUT -p udp -m udp --dport 111 -j ACCEPT
# iptables -A OUTPUT -p tcp -m tcp --dport 2049 -j ACCEPT
# iptables -A OUTPUT -p udp -m udp --dport 2049 -j ACCEPT
# iptables -A OUTPUT -p tcp -m tcp --dport 10000 -j ACCEPT
# iptables -A OUTPUT -p udp -m udp --dport 10001 -j ACCEPT
# iptables -A OUTPUT -p tcp -m tcp --dport 10002:10005 -j ACCEPT
# iptables -A OUTPUT -p udp -m udp --dport 10002:10005 -j ACCEPT
# iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -j REJECT --reject-with icmp-port-unreachable

Note: Mount requests without the specific options for tcp will default to udp.