You close DNS on a server, check from your Mac that port 53 is no longer reachable, and nc reports it open anyway. You check the firewall again. You check that the resolver is stopped — named, unbound, dnsmasq, systemd-resolved, whichever you run. It is stopped. The port still reads as open, and you start doubting the firewall change that was, in fact, perfectly correct.
Before anything else, rule out the thing you may already half-know: this is a TCP check. nc -vz without -u completes a real three-way handshake, so this is not the familiar "UDP scans always look open" quirk, where a connectionless probe reports success simply because no ICMP unreachable came back. Something is genuinely completing a TCP connection that has no business succeeding.
The server is not the problem. Some networks — corporate, hotel, ISP, captive portal — transparently terminate outbound DNS connections themselves, so any address appears to have port 53 open. Your probe never reaches the host you are testing.
The one-line proof
Probe an address that cannot possibly answer:
nc -vz 192.0.2.1 53
Connection to 192.0.2.1 port 53 [tcp/domain] succeeded!
192.0.2.1 is TEST-NET-1 from RFC 5737 — a range reserved for documentation, not routed on the internet, and by definition without a host behind it. Nothing can succeed there. When it does, the connection was terminated by something between you and the internet, and every other result you have collected on that port is worthless.
Run a control on the same port, every time:
nc -vz 192.0.2.1 53 # succeeded! <- impossible: the control
nc -vz 198.51.100.1 53 # succeeded! <- so this means nothing either
nc -vz 192.168.50.55 53 # succeeded! <- nor does the box under test
nc -vz 192.168.50.55 9999 # timed out <- a port that is NOT intercepted
That last line is what makes this so easy to miss. The interception is specific to 53. Ports 21, 80, 443, 8181 and 9999 all report truthfully, so the tool looks trustworthy right up until you use it on the one port you care about.
On port 53, the tools disagree – and neither is right
In the same minute, against the same target, on the same port:
nc -vz 192.168.50.55 53
Connection to 192.168.50.55 port 53 [tcp/domain] succeeded!
# bash's built-in TCP pseudo-device
timeout 3 bash -c 'echo > /dev/tcp/192.168.50.55/53' && echo open || echo "no connect"
no connect
When two tools disagree like this, the instinct is to decide which one is right. Neither is. They are being answered by different things, or at different points, and the honest conclusion is that no client-side probe of port 53 from this network can be trusted at all — including the one that agrees with what you were hoping for.
Check from the server instead
Once you know the client side is unreliable, stop asking it. The server can tell you the truth about itself:
# is anything actually listening on 53?
ss -ltnup | grep ':53 '
# is the service running, and will it come back on boot?
systemctl is-active named ; systemctl is-enabled named
# and what does the firewall actually say?
iptables -S | grep 'dport 53'
Three independent pieces of evidence — nothing bound to the port, the service inactive and disabled, and no accept rule for it — settle the question in a way no external probe can.
You can go one level deeper than the handshake and ask the suspect path an actual question:
dig +short @192.168.50.55 example.com
If an answer comes back from a host where the daemon is confirmed stopped — or an answer that differs from what the real resolver would return — then something else is terminating the query, not merely the connection. That is stronger evidence than any succeeded! line. If you need the outside view as well, run it from somewhere else: a different network, a phone on mobile data, or any online port checker.
Where this comes from
You do not need to identify the exact box doing it, but it helps to know the usual suspects, because it tells you whether to expect the same on other ports:
- Captive portals and guest networks intercept DNS to force their own resolver until you authenticate.
- ISPs redirect DNS to their own servers, historically for advertising on NXDOMAIN.
- Corporate networks transparently redirect DNS to an internal resolver for filtering and logging.
- Software on the laptop itself — an MDM-managed security agent, a VPN client, or a local DNS app — hooks into the network stack and intercepts port 53 on every network the machine joins.
That last one is a different problem with a different fix, so it is worth telling apart. Run the same control probe from a completely different network: home Wi-Fi, then a mobile hotspot. If 192.0.2.1 still answers on 53 everywhere you go, the interception is travelling with the laptop, not sitting on the network.
On macOS, two commands say what the machine itself thinks the resolver is:
scutil --dns | grep -A2 'resolver #1'
networksetup -getdnsservers Wi-Fi
If those show a loopback address such as 127.0.0.1 while you never configured one, something local is in the path and that is your answer.
Most of these target UDP 53 first; the router recipes people copy usually redirect UDP and treat TCP 53 as a separate rule somebody has to remember to add. Plenty of setups do both. Either way, TCP interception is the half that is easy to overlook, because it is the one that makes a connect test lie.
The habit worth forming
This is not really about DNS. It is about the shape of the mistake: a check with no control is not a check. Without one, a closed port reads as open and you conclude a firewall change failed when it worked — or, far worse, that a port is exposed when it is not, and you go make a change to fix a problem that never existed.
So: probe an address that cannot answer, on the same port, in the same run. If the impossible address answers, throw the whole result away and go look from the server.
The same instinct pays off elsewhere: when CSF silently blocks Tailscale's UDP, everything looks healthy from the outside and only a measurement taken from the right side shows the damage. And if you are on a Mac, the other macOS post here is about a similarly counter-intuitive networking detail — adding a second IP address to an interface needs a non-conflicting netmask, for reasons the man page states and nothing else explains.