2

I simply refuse to believe this is somehow not a feature, I need to get NFS to stop listening on the IPv6 addresses of a server, and also restrict which of it's IPv4 addresses it listens on as well.

I've been researching for hours but I just keep landing on the same four or five answers across different sites that provide no relevant solution.

When I run lsof -i -P on the server I can see NFS has opened more then just a few ports:

rpc.mount 7609 root    8u  IPv4 124179      0t0  UDP *:34231
rpc.mount 7609 root    9u  IPv4 124181      0t0  TCP *:55443 (LISTEN)
rpc.mount 7609 root   10u  IPv6 124183      0t0  UDP *:46874
rpc.mount 7609 root   11u  IPv6 124185      0t0  TCP *:55829 (LISTEN)
rpc.mount 7609 root   12u  IPv4 124187      0t0  UDP *:52359
rpc.mount 7609 root   13u  IPv4 124189      0t0  TCP *:37975 (LISTEN)
rpc.mount 7609 root   14u  IPv6 124191      0t0  UDP *:41861
rpc.mount 7609 root   15u  IPv6 124193      0t0  TCP *:33973 (LISTEN)
rpc.mount 7609 root   16u  IPv4 124195      0t0  UDP *:40059
rpc.mount 7609 root   17u  IPv4 124197      0t0  TCP *:50589 (LISTEN)
rpc.mount 7609 root   18u  IPv6 124199      0t0  UDP *:40265
rpc.mount 7609 root   19u  IPv6 124201      0t0  TCP *:35625 (LISTEN)
rpcbind   8103 _rpc    4u  IPv4  13941      0t0  TCP *:111 (LISTEN)
rpcbind   8103 _rpc    5u  IPv4  71849      0t0  UDP *:111
rpcbind   8103 _rpc    6u  IPv6  13945      0t0  TCP *:111 (LISTEN)
rpcbind   8103 _rpc    7u  IPv6  23221      0t0  UDP *:111

I need all the IPv6 ones to go away and change the IPv4 ones from listening on * to listen on 172.24.24.21, 172.24.24.22, and 172.24.24.23

Ineffective Method #1:

According to https://wiki.debian.org/NFSServerSetup, I could achieve this by modifying /etc/default/nfs-kernel-server to contain this line:

RPCMOUNTDOPTS="-H 172.24.24.21 -H 172.24.24.22 -H 172.24.24.23"

Apon restarting both rpcbind and nfs-kernel-server the output of lsof -i -P remains unchanged, it displays the same information as shown in the sample above

Ineffective Method #2:

To at least fix rpcbind, the file /etc/default/rpcbind states the following:

# Uncomment the following line to restrict rpcbind to localhost only for UDP requests
#OPTIONS="${OPTIONS} -h 127.0.0.1 -h ::1"

I tried uncommenting that line and replacing it with this:

OPTIONS="${OPTIONS} -h 172.24.24.21"

Not only did the output of lsof -i -P remain the same after restarting both services, but htop also showed that the physical command executed by systemd to start the service was, quite literally:

/sbin/rpcbind -f ${OPTIONS} -h 172.24.24.21

I tried manually substituting ${OPTIONS} with the correct value in the file, like this:

OPTIONS="-w -h 127.0.0.1"

Which correctly set the command run by systemd to this, as seen in htop:

/sbin/rpcbind -f -w -h 172.24.24.21

But still, the output lsof -i -P remains exactly the same as it was at the top of this post, all ports are still open on all IPv4 and IPv6 as both TCP and UDP, giving me a lot of paranoia knowing the machine can be accessed globally over it's IPv6 addresses

Ineffective Method #3:

I'm supposed to edit /etc/nfs.conf and define host=, but this appears to only be the method for all the more prestigious linux distros out there. I've always preferred headless debian for servers and I'm not looking to just uproot my entire infrastructure and install an entire different distro on my main file storage server to solve this because that would take a week of downtime and messing around which I just do not have

Ineffective Method #4:

Make a script to auto-config iptables to block the specific ports opened each time the service is restarted.

No, I'm not doing that, that's ridiculous. I refuse to believe there isn't a way to just correctly change the bind address like any other network enabled service allows you to do in 2022.

Other Issues:

Systemd already listens on the four :111 addresses with it's own 'rpc' service as well. From what I understand rpcbind should not be able to start when systemd's service already has the ports bound, yet it clearly does. Assuming this is a bug, which process receives any connections to port 111 in this broken state? How do I disable systemd from opening these ports? I don't need systemd's rpc stuff sitting around waiting for someone to hack either.

Someone please tell me what's going on here, I wasted half a day on this

3 Answers3

2

Although the manpage doesn't say, attempting to change the rpc.mountd listen address on Debian seems to only have an effect if the NFSv2 and NFSv3 disable flags are passed in the service's config.

I am, shamefully, using NFSv3, and on closer inspection the Debian wiki has these -N 2 and -N 3 flags in the example and says that part of the command is to change it for NFSv4. This issue with this is though at if we check manpages.debian.org and also man rpc.mountd there is actually no mention of an -H or -N argument being available.

It directly sates that the -H and --ha-callout prog option is in fact meant to:

Specify a high availability callout program. This program receives callouts for all MOUNT and UNMOUNT requests. This allows rpc.mountd to be used in a High Availability NFS (HA-NFS) environment.

In fact all versions of the manpage state this is the only function of -H

So I don't know what's going on here for sure, but I guess the Debian wiki was correct and I just didn't understand that this wouldn't work unless NFSv2 and NFSv3 are disabled. It's real strange though for the Debian wiki to contain information that has never been a part of the manpage for any version I've been able to dig up. The manpage basically threw me off completely to not trust the Debian wiki even though it turns out the information on it was actually 'correct'.

0

I had success on Debian 11 making nfsd listen only to the interface I wanted by setting RPCNFSDOPTS="-H 10.x.y.z -N 2 -N 3" on /etc/default/nfs-kernel-server.

/etc/default/nfs-kernel-server is sourced from /usr/lib/systemd/scripts/nfs-utils_env.sh and RPCNFSDARGS is set with whatever is in RPCNFSDOPTS and then some, specifically:

echo RPCNFSDARGS=\"$RPCNFSDOPTS ${RPCNFSDCOUNT:-8}\"

nfs-utils_env.sh is invoked and spits out its variables to /run/sysconfig/nfs-utils, and from there, the unit file that starts nfsd, /lib/systemd/system/nfs-server.service reads them and honors RPCNFSDARGS:

ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS

So the neatest way I found to do what you describe (which incidentally, I, too, didn't want to believe was not possible in the times we live) is to set RPCNFSDOPTS as described above, even though it is not mentioned there.

Alfredo
  • 16
0

You cannot.

NFS's rpc.mountd has hardcoded listening on the wildcard address 0.0.0.0.

It's only 30 years old so it seems nobody has had the time to add a listen config option yet :|

(I asked the linux-nfs mailing list if there's a reason for it.)

Code:

struct addrinfo hint = {
        .ai_flags       = AI_PASSIVE | AI_NUMERICSERV,
};

(void)snprintf(buf, sizeof(buf), "%u", port); error = getaddrinfo(NULL, buf, &hint, &ai);

It calls getaddrinfo(NULL, ... {.ai_flags = AI_PASSIVE}). man 3 getaddrinfo says:

If the AI_PASSIVE flag is specified in hints.ai_flags, and node is NULL, then the returned socket addresses will be suitable for bind(2)ing a socket that will accept(2) connections. The returned socket address will contain the "wildcard address" (INADDR_ANY for IPv4 addresses, IN6ADDR_ANY_INIT for IPv6 address). The wildcard address is used by applications (typically servers) that intend to accept connections on any of the host's network addresses.

Call graph:

nh2
  • 958