Why would `dig` succeed, but `host`, `nslookup`, `curl`, `ping` all fail?
host
and nslookup
make several separate DNS queries – one for each record type. They want to show you both IPv4 and IPv6 addresses, so they need to make an A query and an AAAA query.
If you run host -v api.nordvpn.com
(with the 'verbose' option to show responses in dig-like format), you will see that it is actually equivalent to these 3 commands in a row:
dig api.nordvpn.com A
dig api.nordvpn.com AAAA
dig api.nordvpn.com MX
Running nslookup -debug api.nordvpn.com
will similarly show it querying for both A and AAAA records (although not MX).
If you look carefully at your Docker output, you will notice that the A query actually succeeds, it's the AAAA one which returns a SERVFAIL. So the failure is never visible in 'dig' because you never asked it to make AAAA queries.
There could be several explanations for the partially failing queries:
-
Your resolver has some connectivity issues with the authoritative servers, but it happens to have results for A cached from earlier and is still able to return those.
-
The authoritative servers of nordvpn.com are returning responses for A queries but failing to respond at all for AAAA queries.
-
Your DNS requests are being intercepted and redirected to a different resolver, and that resolver blocks all AAAA queries under the pretense of "not supporting IPv6" or "avoiding IPv6 VPN leaks" or similar.
Indeed your dig +trace
output already shows that it's the 3rd case:
api.nordvpn.com. 299 IN A 104.17.50.74
api.nordvpn.com. 299 IN A 104.17.49.74
;; Received 106 bytes from 199.7.83.42#53(l.root-servers.net) in 43 ms
In trace mode, dig starts by contacting the root servers, where it's supposed to receive a referral response (one that points to the '.com' servers) and follow the chain.
But in your case, dig somehow immediately receives a direct answer with the requested A records. That's not how the root servers work – they are not able to provide such answers. The only time you would see this result is if your packets on port 53 are being redirected to a local resolver and you're not, in fact, talking to the DNS server that you think you're talking to.
Try making a DNS query at 192.0.2.1 or 203.0.113.1 – if you receive a response from this address you'll know it's not legitimate, because this address does not exist anywhere on the Internet.)
dig @192.0.2.1 google.com
Try making these queries to find out the name of the DNS server that you're actually talking to:
dig @9.9.9.9 hostname.bind chaos txt
dig @9.9.9.9 id.server chaos txt
(If talking to the real 9.9.9.9, you should see something like "res600.fra.rrdns.pch.net" as the id.server response.)
It might be worth trying to traceroute --udp --port=53 9.9.9.9
; it will show normal results until it reaches the point where the packets are being redirected, nonsensical results afterwards.