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

NFS clients outside of the firewall

Environment

  • Red Hat Enterprise Linux 7 and 8
  • NFS version 3

Issue

  • Cannot connect to my NFS server which sits behind a firewall.
  • How to assign permanent ports to NFS services?
  • How to bind RPC services, which are related to NFS, to a static port?

Resolution

  • NFSv3 and below rely 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.

  • The first step is to assign a permanent port number to each of the NFS services (rquotadmountdstatd, and lockd). You may use your own custom port numbers, although there are SELinux rules which prevent some of these services from starting on non-default ports. We strongly recommend using the default ports. The following examples use the default port numbers.

  • The port numbers for these services 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:

# Port rquotad should listen on.
RQUOTAD_PORT=875

# TCP port rpc.lockd should listen on.
LOCKD_TCPPORT=32803
# UDP port rpc.lockd should listen on.
LOCKD_UDPPORT=32769

# Port rpc.mountd should listen on.
MOUNTD_PORT=892

# Port rpc.statd should listen on.
STATD_PORT=662
# Outgoing port statd should used. The default is port
# is random
#STATD_OUTGOING_PORT=2020
  • NOTE - RHEL 8: /etc/sysconfig/nfs has been deprecated and replaced by /etc/nfs.conf in RHEL8. In this example, the following ports would have to be configured at minimum:
[lockd]
port=32803
udp-port=32769

[mountd]
port=892

[statd]
port=662
  • NOTE - statd: STATD_OUTGOING_PORT can usually be left commented out and defaulting to a random outgoing port, as it's most common to only restrict incoming traffic with a firewall. STATD_OUTGOING_PORT is only required to be set if the firewall also restricts outgoing traffic.

  • NOTE - RHEL 7 and RHEL 8: After changing anything in /etc/sysconfig/nfs (or in /etc/nfs.conf in RHEL 8) you must run systemctl restart nfs-server for the changes to take effect. In RHEL 7, STATD_OUTGOING_PORT is no longer valid and is replaced by STATDARG="-o 2020".

# systemctl restart nfs-server
  • NOTE - lockd: If the ports for the lockd service can not be changed despite the above setting, you might need to update your nfs-utils package. This package has a relevant bug in the earlier versions. For more information, please visit our Bugzilla entries Bug 461043.

  • NOTE - protocols: Mount requests without the specific options for tcp will default to udp.

  • 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
    100024    1   udp    662  status
    100024    1   tcp    662  status
    100011    1   udp    875  rquotad
    100011    2   udp    875  rquotad
    100011    1   tcp    875  rquotad
    100011    2   tcp    875  rquotad
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100021    1   udp  32769  nlockmgr
    100021    3   udp  32769  nlockmgr
    100021    4   udp  32769  nlockmgr
    100021    1   tcp  32803  nlockmgr
    100021    3   tcp  32803  nlockmgr
    100021    4   tcp  32803  nlockmgr
    100003    2   tcp   2049  nfs
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100005    1   udp    892  mountd
    100005    1   tcp    892  mountd
    100005    2   udp    892  mountd
    100005    2   tcp    892  mountd
    100005    3   udp    892  mountd
    100005    3   tcp    892  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)
    • 875: example rquotad (tcp/udp)
    • 32803: lockd (tcp)
    • 32769: lockd (udp)
    • 892: mountd (tcp/udp)
    • 662: statd/status (tcp/udp)
    • 2020: statd/status outgoing (tcp/udp) - optional as per note above
  • 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 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -m comment --comment "sshd" -j ACCEPT
iptables -A INPUT -p tcp --dport 111 -m comment --comment "portmap" -j ACCEPT
iptables -A INPUT -p udp --dport 111 -m comment --comment "portmap" -j ACCEPT
iptables -A INPUT -p tcp --dport 2049 -m comment --comment "nfs" -j ACCEPT  
iptables -A INPUT -p udp --dport 2049 -m comment --comment "nfs" -j ACCEPT  
iptables -A INPUT -p tcp --dport 875 -m comment --comment "rquotad" -j ACCEPT
iptables -A INPUT -p udp --dport 875 -m comment --comment "rquotad" -j ACCEPT
iptables -A INPUT -p tcp --dport 32803 -m comment --comment "lockd" -j ACCEPT
iptables -A INPUT -p udp --dport 32769 -m comment --comment "lockd" -j ACCEPT
iptables -A INPUT -p tcp --dport 892 -m comment --comment "mountd" -j ACCEPT
iptables -A INPUT -p udp --dport 892 -m comment --comment "mountd" -j ACCEPT
iptables -A INPUT -p tcp --dport 662 -m comment --comment "statd" -j ACCEPT
iptables -A INPUT -p udp --dport 662 -m comment --comment "statd" -j ACCEPT
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
  • If your firewall restricts outgoing traffic:
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -p tcp -m state --state NEW -m tcp --dport 22 -m comment --comment "ssh-client" -j ACCEPT
iptables -A OUTPUT -p tcp --sport 111 -m comment --comment "portmap" -j ACCEPT
iptables -A OUTPUT -p udp --sport 111 -m comment --comment "portmap" -j ACCEPT
iptables -A OUTPUT -p tcp --sport 2049 -m comment --comment "nfs" -j ACCEPT
iptables -A OUTPUT -p udp --sport 2049 -m comment --comment "nfs" -j ACCEPT
iptables -A OUTPUT -p tcp --sport 875 -m comment --comment "rquotad" -j ACCEPT
iptables -A OUTPUT -p udp --sport 875 -m comment --comment "rquotad" -j ACCEPT
iptables -A OUTPUT -p tcp --sport 32803 -m comment --comment "lockd" -j ACCEPT
iptables -A OUTPUT -p udp --sport 32769 -m comment --comment "lockd" -j ACCEPT
iptables -A OUTPUT -p tcp --sport 892 -m comment --comment "mountd" -j ACCEPT
iptables -A OUTPUT -p udp --sport 892 -m comment --comment "mountd" -j ACCEPT
iptables -A OUTPUT -p tcp --sport 662 -m comment --comment "statd" -j ACCEPT
iptables -A OUTPUT -p udp --sport 662 -m comment --comment "statd" -j ACCEPT
iptables -A OUTPUT -p tcp --sport 2020 -m comment --comment "statd" -j ACCEPT
iptables -A OUTPUT -p udp --sport 2020 -m comment --comment "statd" -j ACCEPT
iptables -A OUTPUT -j REJECT --reject-with icmp-port-unreachable
  • OR if you are using firewalld in RHEL 7.x/RHEL 8.x, you would use the following example commands:
# firewall-cmd --permanent --add-port=111/tcp
# firewall-cmd --permanent --add-port=111/udp
# firewall-cmd --permanent --add-port=2049/tcp
# firewall-cmd --permanent --add-port=2049/udp
# firewall-cmd --permanent --add-port=875/udp
# firewall-cmd --permanent --add-port=875/tcp
# firewall-cmd --permanent --add-port=32803/tcp
# firewall-cmd --permanent --add-port=32769/udp
# firewall-cmd --permanent --add-port=892/tcp
# firewall-cmd --permanent --add-port=892/udp
# firewall-cmd --permanent --add-port=662/tcp
# firewall-cmd --permanent --add-port=662/udp
# firewall-cmd --reload

Post a Comment

© LinuxFault. All rights reserved. Developed by Jago Desain