Your vulnerability scanner has flagged TCP and UDP port 111 open on a Linux server, and the finding names rpcbind, the service older guides call portmapper. On our Debian 13 test box nobody installed it on purpose, because apt install nfs-common pulled rpcbind in and enabled a socket on every interface. To disable portmapper for good you have to deal with that socket unit as well as the service, since stopping the service alone leaves 111 open.
You will end with one of two setups. Either rpcbind is masked (with the NFS server on NFSv4 only, if you serve shares), or it stays behind an nftables rule that accepts loopback first so it cannot hang your own NFS daemons. RHEL, Rocky and Fedora were not tested. Every command, error and nmap scan below was run on Debian 13 with rpcbind 1.2.7 in October 2026, scanned from a second VM.
Find what opened port 111
On a systemd distro, port 111 is opened by rpcbind.socket, and the rpcbind daemon only takes over the sockets systemd already holds. That is why the socket table shows two owners for each listener. Check what is bound to the port first, so you know you are dealing with rpcbind and not something else.
sudo ss -tulpn | grep -E ":111\b"
Each line lists both rpcbind and systemd with pid 1. That second owner is the socket unit, and it is the part people forget, so keep it in mind when you stop things later. Our server returned four listeners.
udp UNCONN 0 0 0.0.0.0:111 0.0.0.0:* users:(("rpcbind",pid=12350,fd=5),("systemd",pid=1,fd=64))
udp UNCONN 0 0 [::]:111 [::]:* users:(("rpcbind",pid=12350,fd=7),("systemd",pid=1,fd=66))
tcp LISTEN 0 4096 0.0.0.0:111 0.0.0.0:* users:(("rpcbind",pid=12350,fd=4),("systemd",pid=1,fd=63))
tcp LISTEN 0 4096 [::]:111 [::]:* users:(("rpcbind",pid=12350,fd=6),("systemd",pid=1,fd=65))
If grep prints nothing, nothing is listening on 111 and your scanner is looking at a different host or a stale result. When it does match, ask apt which installed package depends on rpcbind. The answer tells you whether anything on the box actually uses it:
apt-cache rdepends --installed rpcbind
On our server the only reverse dependency was the NFS client package. If you see something else here, such as a NIS client, find out who uses it before you remove or mask anything.
rpcbind
Reverse Depends:
nfs-common
That matches what happened when we installed nfs-common on a fresh Debian 13 cloud image, which had nothing on port 111 before. Apt listed rpcbind among the new packages and enabled both of its units without asking:
The following NEW packages will be installed:
keyutils libevent-core-2.1-7t64 libnfsidmap1 nfs-common rpcbind
0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded.
Created symlink '/etc/systemd/system/multi-user.target.wants/rpcbind.service' → '/usr/lib/systemd/system/rpcbind.service'.
Created symlink '/etc/systemd/system/sockets.target.wants/rpcbind.socket' → '/usr/lib/systemd/system/rpcbind.socket'.
So a machine that only mounts NFS shares, or merely had the client tools installed by a provisioning script, listens on 111 just like a file server does. NFS clients are where most stray port 111 findings come from. The socket unit’s status shows exactly which addresses it holds:
systemctl status rpcbind.service rpcbind.socket --no-pager
The Listen: block is the important part. It covers the local Unix socket plus TCP and UDP on all IPv4 and IPv6 addresses:
● rpcbind.socket - RPCbind Server Activation Socket
Loaded: loaded (/usr/lib/systemd/system/rpcbind.socket; enabled; preset: enabled)
Active: active (running) since Tue 2026-10-20 10:16:03 UTC; 12s ago
Triggers: ● rpcbind.service
Listen: /run/rpcbind.sock (Stream)
0.0.0.0:111 (Stream)
0.0.0.0:111 (Datagram)
[::]:111 (Stream)
[::]:111 (Datagram)
For more ways to read listening sockets and their states, our guide to checking TCP connection states with netstat and ss covers the filters in detail.
List registered RPC services with rpcinfo
rpcinfo asks rpcbind which RPC programs are registered and on which ports. Run locally with no host, it queries the local rpcbind. On a box that only has nfs-common, the portmapper itself is the only entry:
rpcinfo -p
Program 100000 is the portmapper itself, registered for versions 2, 3 and 4 over both TCP and UDP. Nothing else is registered, so on this box rpcbind serves no purpose at all.
program vers proto port service
100000 4 tcp 111 portmapper
100000 3 tcp 111 portmapper
100000 2 tcp 111 portmapper
100000 4 udp 111 portmapper
100000 3 udp 111 portmapper
100000 2 udp 111 portmapper
The short form groups versions and transports onto one line per program, which is easier to read once NFS services are registered:
rpcinfo -s
The netid column confirms the portmapper answers on the local socket and on UDP and TCP over IPv4 and IPv6. That matches the four listeners ss showed earlier.
program version(s) netid(s) service owner
100000 2,3,4 local,udp,tcp,udp6,tcp6 portmapper superuser
The real exposure shows up when you query from another machine, which is what an attacker or your scanner does. We used a second Debian 13 VM at 10.0.1.60 and installed nmap and rpcbind on it, the latter being what put the rpcinfo client on that box. That also opens 111 on the scanning machine, so either mask rpcbind there when you finish (the same mask command shown later) or skip it and rely on nmap’s rpcinfo script below. Set the server address once, because the later checks reuse it:
sudo apt-get install -y nmap rpcbind
export HOST_IP="10.0.1.50"
For this test the server ran rpcbind plus an NFS server with NFSv3 enabled, which is the Debian default. List its registrations from the second machine.
rpcinfo -p "${HOST_IP}"
Anyone who can reach 111 gets the whole map: 23 entries from six RPC programs on our server. That includes status (rpc.statd), every mountd version and the lock manager, each on a random high port. Without the portmapper, a scanner would have to sweep the whole high port range to find mountd on 36153 or nlockmgr on 35695, and it would still have to guess what each port is. With it, one unauthenticated request returns the names and the ports together:
program vers proto port service
100000 4 tcp 111 portmapper
100000 3 tcp 111 portmapper
100000 2 tcp 111 portmapper
100000 4 udp 111 portmapper
100000 3 udp 111 portmapper
100000 2 udp 111 portmapper
100024 1 udp 45322 status
100024 1 tcp 52491 status
100005 1 udp 39567 mountd
100005 1 tcp 48249 mountd
100005 2 udp 51797 mountd
100005 2 tcp 48337 mountd
100005 3 udp 35727 mountd
100005 3 tcp 36153 mountd
100003 3 tcp 2049 nfs
100003 4 tcp 2049 nfs
100227 3 tcp 2049 nfs_acl
100021 1 udp 58494 nlockmgr
100021 3 udp 58494 nlockmgr
100021 4 udp 58494 nlockmgr
100021 1 tcp 35695 nlockmgr
100021 3 tcp 35695 nlockmgr
100021 4 tcp 35695 nlockmgr
That listing is the information disclosure scanners complain about. It tells an attacker you run NFSv3, which lock and mount daemons are up, and where to find them. nmap’s rpcinfo script pulls the same data during a service scan, so assume anyone who scans your network already has it.
sudo nmap -sV -p 111 --script rpcinfo "${HOST_IP}"
nmap identifies the service as rpcbind 2-4 and prints the program table, IPv6 registrations included. The IPv4 ports match the rpcinfo -p run exactly. The extra mountd and nlockmgr ports are the tcp6 and udp6 registrations, which rpcinfo -p cannot show because it speaks portmap version 2, an IPv4-only protocol.
PORT STATE SERVICE VERSION
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100003 3,4 2049/tcp nfs
| 100003 3,4 2049/tcp6 nfs
| 100005 2,3 34877/tcp6 mountd
| 100005 2,3 53855/udp6 mountd
| 100005 3 35727/udp mountd
| 100005 3 36153/tcp mountd
| 100021 1,3,4 32875/tcp6 nlockmgr
| 100021 1,3,4 35543/udp6 nlockmgr
| 100021 1,3,4 35695/tcp nlockmgr
| 100021 1,3,4 58494/udp nlockmgr
| 100227 3 2049/tcp nfs_acl
|_ 100227 3 2049/tcp6 nfs_acl
If you want the wider scanning picture, our nmap network scanning guide covers service and script scans beyond this one port.
Choose: mask rpcbind or firewall port 111
rpcbind exists for NFSv3 and older RPC services such as NIS. NFSv4 talks to a fixed port, 2049, and does not need a portmapper at all, so the choice comes down to whether anything on the network still speaks NFSv3. Clients count too: every machine with nfs-common installed listens on 111 unless you act, so a fleet of NFS clients usually produces more scanner findings than the one file server they mount from. Pick your row for each machine:
| Your situation | What to do | Port 111 from outside afterwards |
|---|---|---|
| No NFS use; rpcbind came in with nfs-common | Mask rpcbind | closed |
| NFS client mounting NFSv4 shares | Mask rpcbind, mount with -t nfs4 | closed |
| NFS server, every client speaks NFSv4 | Mask rpcbind, set vers3=n, mask the statd helpers | closed |
| NFS server with NFSv3 clients, or NIS | Keep rpcbind, allow 111 only from client subnets | filtered |
We would mask in every case where the last row does not apply. A masked unit cannot be started by hand or pulled in by another unit, and a closed port answers a connection with a refusal instead of holding it open. Firewalling is the right call only when you cannot drop NFSv3 yet. Even then you are accepting that every trusted host can still read the full RPC map, so treat the firewall as a stopgap and plan the move to NFSv4.
Stop the rpcbind service and socket
You have to stop rpcbind.socket and rpcbind.service together. Stopping the service alone is what most old guides tell you to do, and on a socket-activated system it achieves nothing: systemd keeps the port open and starts the daemon again on the next request. We captured that trap on our server:

Read it top to bottom. systemctl warns that the triggering socket is still active, and ss shows all four listeners now owned by systemd alone. The moment rpcinfo -p connects, systemd hands the connection to a freshly started rpcbind, so is-active reports it as active again. Stop both units in one command instead.
sudo systemctl stop rpcbind.socket rpcbind.service
Then confirm both are inactive and nothing holds the port. Run the three checks together, because each one catches a different half of the problem.
systemctl is-active rpcbind.service rpcbind.socket
sudo ss -tulpn | grep -E ":111\b" || echo "nothing listening on 111"
rpcinfo -p
This time rpcinfo fails with a refused connection. That failure is the result you want, because it means no process and no socket unit is answering on 111.
inactive
inactive
nothing listening on 111
rpcinfo: can't contact portmapper: RPC: Remote system error - Connection refused
If your own run printed a warning instead of this clean result, it is almost always the one below.
Stopping ‘rpcbind.service’, but its triggering units are still active: rpcbind.socket
This warning means you stopped the daemon but left the socket that starts it. Port 111 is still open, held by pid 1, and the next RPC request brings the daemon back. Stop rpcbind.socket too, as shown above. The systemctl commands reference has more on how socket units and the services they trigger relate.
Mask rpcbind so rpc-statd cannot start it
Disabling both units is not enough on a box with the NFS client tools, because another unit can still pull rpcbind back in. Once rpcbind is only disabled, it still has three ways back:
- a manual
systemctl start - a unit that requires the socket, such as rpc-statd
- an NFSv3 mount, which starts rpc-statd
We disabled both units anyway to see what happens, and systemctl is-enabled read disabled for each.
sudo systemctl disable rpcbind.service rpcbind.socket
The culprit is rpc-statd, the NFSv3 lock-recovery helper from nfs-common. Its unit lists the rpcbind socket as a hard requirement, which you can confirm with systemctl.
systemctl show rpc-statd.service -p Requires
A Requires= dependency starts the required unit whether it is enabled or not. Disabling only removes the boot-time links, so it does nothing against this.
Requires=system.slice nss-lookup.target rpcbind.socket
We started rpc-statd with rpcbind disabled, and rpcbind came straight back, socket and service both active and 111 listening again. An NFSv3 mount attempt starts rpc-statd on its own, so a disabled rpcbind reopens the port the first time someone mounts a share without nfs4. Masking points the unit files at /dev/null, which nothing can start. Stop statd and both rpcbind units, then mask rpcbind:
sudo systemctl stop rpc-statd.service rpcbind.socket rpcbind.service
sudo systemctl mask rpcbind.service rpcbind.socket
The capture below shows the mask taking effect and rpc-statd being refused. After a reboot both units were still inactive and nothing listened on 111.

On an NFS client you can do the stop and the mask in one step with --now, which is how we prepared the client VM for the NFSv4 test later:
sudo systemctl mask --now rpcbind.socket rpcbind.service
If something breaks afterwards (an old NFSv3 client, NIS, a backup agent that registers over RPC), the way back is one unmask and one enable. Keep these lines handy before you mask on a server you can’t easily reach:
sudo systemctl unmask rpcbind.service rpcbind.socket rpc-statd.service rpc-statd-notify.service
sudo systemctl enable --now rpcbind.socket rpcbind.service
Unmasking also releases the two statd helpers. On an NFS server you switched to NFSv4 only in the next section, turn version 3 back on and restart the server together with rpc-statd, which is the exact sequence we used to bring NFSv3 back in the lab:
sudo systemctl stop nfs-server
sudo nfsconf --set nfsd vers3 y
sudo systemctl start nfs-server rpc-statd
Check that systemctl is-active rpcbind nfs-server rpc-statd reports active for all three before you point NFSv3 clients back at the server.
We didn’t test RHEL, Rocky or Fedora. rpcbind upstream ships the same rpcbind.service and rpcbind.socket pair, so the commands should carry over, but confirm the unit names with systemctl list-unit-files on your box before masking.
Failed to start rpc-statd.service: Unit rpcbind.socket is masked
This is the mask doing its job. Something tried to start rpc-statd, usually an NFSv3 mount, and systemd refused because the socket it requires is masked. If you meant to drop NFSv3, use NFSv4 mounts and leave it alone. If you still need NFSv3, unmask with the commands above and firewall port 111 instead.
Run the NFS server as NFSv4 only
An NFS server works without rpcbind only once NFSv3 is switched off, because Debian’s default /etc/nfs.conf still enables version 3. We installed nfs-kernel-server with rpcbind already masked, and the server failed to start:
journalctl -u nfs-server -b --no-pager | grep -E "rpc.nfsd|Failed|error"
rpc.nfsd tried to register NFSv3 with the portmapper and got a refusal. It then gave up on every socket, so the server did not even listen on 2049.
Oct 20 10:18:43 deb01 sh[938]: rpc.nfsd: writing fd to kernel failed: errno 111 (Connection refused)
Oct 20 10:18:43 deb01 sh[938]: rpc.nfsd: unable to set any sockets for nfsd
Oct 20 10:18:43 deb01 systemd[1]: nfs-server.service: Failed with result 'exit-code'.
Turn NFSv3 off and NFSv4 on with nfsconf, which edits the [nfsd] section of /etc/nfs.conf for you. It lives in /usr/sbin, so run it with sudo:
sudo nfsconf --set nfsd vers3 n
sudo nfsconf --set nfsd vers4 y
sudo nfsconf --set nfsd vers4.2 y
The statd helpers only matter for NFSv3 locking, and rpc-statd would keep asking for the masked socket, so mask both of them too:
sudo systemctl mask rpc-statd.service rpc-statd-notify.service
Restart the server, then check both the config file and what the kernel actually accepts. The second check matters more, because it reflects the running nfsd and not just the file.
sudo systemctl restart nfs-server
sudo nfsconf --dump | sed -n "/\[nfsd\]/,/^\$/p"
sudo cat /proc/fs/nfsd/versions
A healthy NFSv4-only server prints -3 followed by the v4 versions. Note that reading /proc/fs/nfsd/versions without sudo returns Permission denied, which isn’t a fault:
[nfsd]
vers3 = n
vers4 = y
vers4.2 = y
-3 +4 +4.1 +4.2
Check the listening sockets once more, for both the portmapper and the NFS port.
sudo ss -tulpn | grep -E ":(111|2049)\b"
Only the NFS port answers, over TCP on IPv4 and IPv6. Port 111 is gone, so the server now runs with:
vers3 = nin the[nfsd]section of/etc/nfs.conf- rpcbind, rpc-statd and rpc-statd-notify masked
- TCP 2049 as the only NFS listener
Those three changes are the whole NFSv4-only setup. Nothing else in the NFS config needed to change on our server.
tcp LISTEN 0 4096 0.0.0.0:2049 0.0.0.0:*
tcp LISTEN 0 4096 [::]:2049 [::]:*
To prove clients still work, we created a throwaway test export for the lab subnet and mounted it from the second VM. Use tee -a so existing lines in /etc/exports survive, because exportfs -ra unexports anything that is not in the file. Remove the test line when you are done, with the cleanup commands after the mount test:
sudo mkdir -p /srv/nfs/share
echo hello-from-deb01 | sudo tee /srv/nfs/share/hello.txt
echo "/srv/nfs/share 10.0.1.0/24(rw,sync,no_subtree_check)" | sudo tee -a /etc/exports
sudo exportfs -ra
On the client, install the NFS tools, then mask the rpcbind they bring along so the client does not open 111 either. Mount with the nfs4 type so it never tries the v3 path, because a v3 attempt fails on a masked client.
sudo apt-get install -y nfs-common
sudo systemctl mask --now rpcbind.socket rpcbind.service
sudo mkdir -p /mnt/share
sudo mount -t nfs4 "${HOST_IP}":/srv/nfs/share /mnt/share
cat /mnt/share/hello.txt
findmnt /mnt/share -o SOURCE,FSTYPE,OPTIONS
The test file reads back and findmnt reports vers=4.2. Neither end ran a portmapper, so NFSv4 needs nothing on port 111.
hello-from-deb01
SOURCE FSTYPE OPTIONS
10.0.1.50:/srv/nfs/share nfs4 rw,relatime,vers=4.2,rsize=1048576,wsize=1048576
When you finish testing, delete the test export from the server and reload the export table. These cleanup commands were not part of the lab run:
sudo sed -i '\|^/srv/nfs/share 10.0.1.0/24|d' /etc/exports
sudo exportfs -ra
Your own exports stay in place, because the sed expression only matches the test line.
For a full server build with exports and client options, follow the NFS server setup on Debian, or the Ubuntu 26.04 NFS server guide if your file server runs Ubuntu. Every nfsd option nfsconf can set is listed in the nfs.conf man page.
rpc.nfsd: writing fd to kernel failed: errno 111 (Connection refused)
Errno 111 here is ECONNREFUSED from the portmapper, not port 111. nfsd is still configured for NFSv3 and can’t register with a masked or stopped rpcbind. Set vers3 n with nfsconf as above and restart nfs-server, or unmask rpcbind if you need v3.
mount.nfs: rpc.statd is not running but is required for remote locking
An NFSv3 mount against the NFSv4-only server failed with exit code 32. The client had rpcbind masked, so the message starts with the same refusal you saw earlier.
Failed to start rpc-statd.service: Unit rpcbind.socket is masked.
mount.nfs: rpc.statd is not running but is required for remote locking.
mount.nfs: Either use '-o nolock' to keep locks local, or start statd.
The client asked for vers=3, which needs rpc-statd, which needs rpcbind. Mount with -t nfs4 instead. The -o nolock hint keeps locks local to one client, which is unsafe when two machines write the same files, so we wouldn’t use it on shared data.
nfsconf: command not found
You ran nfsconf as a normal user. It lives in /usr/sbin, which may not be in a regular user’s PATH, so the shell cannot find it. Prefix it with sudo, including for --dump.
Keep rpcbind and firewall port 111 with nftables
If NFSv3 clients have to keep working, leave rpcbind running and let only their subnet reach port 111. Debian 13 ships nftables, but its service is disabled by default, so rules you add by hand vanish at reboot until you enable it. Install it if it’s missing and check its state.
sudo apt-get install -y nftables
systemctl is-enabled nftables
It reports disabled. Create a separate table so these rules don’t touch anything else. In this example the NFSv3 clients live on 10.0.2.0/24, and the scanning VM at 10.0.1.60 sits outside that range, so it sees what an untrusted host sees. Replace the subnet with your own client range.
sudo nft add table inet rpcguard
sudo nft add chain inet rpcguard input "{ type filter hook input priority -10; policy accept; }"
sudo nft add rule inet rpcguard input ip saddr 10.0.2.0/24 tcp dport 111 accept
sudo nft add rule inet rpcguard input ip saddr 10.0.2.0/24 udp dport 111 accept
sudo nft add rule inet rpcguard input tcp dport 111 drop
sudo nft add rule inet rpcguard input udp dport 111 drop
Now add the rule we learned the hard way. The drops above also match loopback traffic, so local NFS daemons that talk to rpcbind over [::1]:111 get their packets silently dropped and hang (we saw this once rpcbind was masked and nothing listened on 111). insert puts the loopback accept at the top of the chain:
sudo nft insert rule inet rpcguard input iif lo accept
sudo nft list chain inet rpcguard input
nftables checks a chain from top to bottom and stops at the first match, so the order of the finished chain is the whole design:
- accept anything arriving on loopback
- accept TCP and UDP 111 from the trusted subnet
- drop TCP and UDP 111 from everyone else
The listing shows the rules in that order.
table inet rpcguard {
chain input {
type filter hook input priority filter - 10; policy accept;
iif "lo" accept
ip saddr 10.0.2.0/24 tcp dport 111 accept
ip saddr 10.0.2.0/24 udp dport 111 accept
tcp dport 111 drop
udp dport 111 drop
}
}
The accepts match IPv4 sources only, while the drops apply to IPv4 and IPv6 because the table is inet. An NFSv3 client that reaches the server over IPv6 is dropped, so add an ip6 saddr pair if you have one. To make the table survive a reboot, append it to /etc/nftables.conf, check the file, and enable the service:
sudo nft list table inet rpcguard | sudo tee -a /etc/nftables.conf >/dev/null
sudo nft -c -f /etc/nftables.conf && echo syntax-ok
sudo systemctl enable nftables
The check prints syntax-ok, and after a reboot nft list tables still showed rpcguard. Debian’s stock /etc/nftables.conf opens with flush ruleset, which means the file expects to own the whole ruleset. Our lab host also carried libvirt’s runtime ip nat and filter tables, and any later restart or reload of nftables.service flushes tables like those (Docker’s too) until their owner recreates them. If ufw or firewalld already manages this server, put the same allow-and-deny logic into that tool instead; we didn’t test either here. The common ufw commands and the firewalld setup on Debian show the syntax.
nfs-mountd.service: start operation timed out. Terminating.
We hit this one while running the firewall and the mask together, before the loopback rule existed. With rpcbind masked and the drop rules loaded, nfs-server failed with “A dependency job for nfs-server.service failed”, and the mountd journal showed systemd giving up:
sudo journalctl -b --no-pager -u nfs-mountd | grep -E "timed out|Failed"
mountd never finished starting, and systemd killed it after the start timeout. Retrying the start only repeated the wait.
Oct 20 11:24:11 deb01 systemd[1]: nfs-mountd.service: start operation timed out. Terminating.
Oct 20 11:25:41 deb01 systemd[1]: nfs-mountd.service: State 'stop-sigterm' timed out. Killing.
Oct 20 11:25:41 deb01 systemd[1]: nfs-mountd.service: Failed with result 'timeout'.
We only saw the hang once nothing listened on 111. While rpcbind was still running behind the same rules, local rpcinfo -p kept working. Deleting the stale /run/rpcbind.sock made no difference. An strace of rpc.mountd showed it stuck in connect() to [::1] port 111. With nothing listening, the kernel would normally refuse that connection at once and mountd would carry on, but the drop rule swallowed the packet, so mountd waited until systemd timed it out. After nft insert rule inet rpcguard input iif lo accept, systemctl start nfs-server finished in 0.2 seconds. Two lessons follow. Any rule that drops 111 should carry the loopback accept first, since it is cheap insurance, and once rpcbind is masked the drop rule is pointless anyway, because a closed port already refuses connections. We deleted the table after that test. The sed range deletes from the table inet rpcguard line to the end of the file, so it is only safe while that table is the last thing in the file. Back the file up first:
sudo cp /etc/nftables.conf /etc/nftables.conf.bak
sudo nft delete table inet rpcguard
sudo sed -i "/table inet rpcguard/,\$d" /etc/nftables.conf
The sed line removes the appended table from /etc/nftables.conf, so it doesn’t come back at the next boot. Skip it and the drop rules return with the next reboot, loopback rule or not.
Verify port 111 from another machine
The only check that counts is the one your scanner makes, so run nmap from a different host against both TCP and UDP. Include 2049 so you can see NFS separately from the portmapper:
sudo nmap -sU -sT -p 111,2049 "${HOST_IP}"
Before any change, with rpcbind and NFSv3 running, port 111 is open on both protocols. This is the state your scanner reported.
Nmap scan report for deb01 (10.0.1.50)
Host is up (0.00031s latency).
PORT STATE SERVICE
111/tcp open rpcbind
2049/tcp open nfs
111/udp open rpcbind
2049/udp closed nfs
With the nftables rules loaded and rpcbind still running, the same scan from outside the trusted subnet returns filtered. nmap can’t tell a dropped UDP probe from a silent service, hence open|filtered. A remote rpcinfo hangs instead of answering, so wrap it in timeout. Scan port 111 and query rpcbind in one go:
sudo nmap -sU -sT -p 111 "${HOST_IP}"
timeout 10 rpcinfo -p "${HOST_IP}"; echo rc=$?
Exit code 124 means timeout killed it. The nmap lines above it show the filtered state on both protocols.
PORT STATE SERVICE
111/tcp filtered rpcbind
111/udp open|filtered rpcbind
rc=124
Some scanners still report open|filtered UDP as a finding, so expect to explain it to whoever reads the report. With rpcbind masked, the server on NFSv4 only and no firewall table, both protocols on 111 report closed while NFS stays reachable on 2049:
PORT STATE SERVICE
111/tcp closed rpcbind
2049/tcp open nfs
111/udp closed rpcbind
2049/udp closed nfs
A remote rpcinfo -p "${HOST_IP}" now fails straight away with RPC: Remote system error - Connection refused. That is the result to aim for. Closed beats filtered because there is no daemon left to misconfigure, and the NFSv4 mount above proves your shares do not need it. Keep the nftables route for servers with NFSv3 clients you can’t move yet, and plan the move.