TL;DR: Having a domain that is served from Cloudflare DNS in linux resolver search domains breaks resolver. This seems to be due to cloudflare not returning NXDOMAIN
for queries.
This stumped me for a while. I discovered this because my linux resolver stopped resolving names outside of my local network. After a long rabbithole this turns out to be because the resolver gets confused by not receiving NXDOMAIN
from the authoritative DNS.
While I discovered this with my own domain home.ressukka.net
, it seems that this is reproduceable with any domain hosted on cloudflare.
To demonstrate:
ressu@denial ~> dig cloudflare.com @1.1.1.1 +domain=google.com +ndots=3 +short
104.16.133.229
104.16.132.229
ressu@denial ~> dig cloudflare.com @1.1.1.1 +domain=plex.tv +ndots=3 +short
ressu@denial ~> dig cloudflare.com @1.1.1.1 +domain=cloudflare.com +ndots=3 +short
ressu@denial ~> dig cloudflare.com @1.1.1.1 +domain=microsoft.com +ndots=3 +short
104.16.133.229
104.16.132.229
What is happening here is that dig is simulating the linux resolver and trying to look up cloudflare.com
with the given search domain. So effectively it’s looking for cloudflare.com.google.com
(in the first example), which naturally doesn’t exist. Since the resolver receives a NXDOMAIN
status from the DNS it moves on to search for cloudflare.com
which then succeeds. But if we use a domain hosted on Cloudflare DNS, the resolver stops resolving as it instead received a NOERROR
response. There is no data, but also there is no reason to move forward either.
This is a new(ish) behaviour on Cloudflare DNS and I’ve first observed this about a month ago when some of my services in my home network stopped working. They are using home.ressukka.net
as part of their search domain, which is hosted on cloudflare. Since the domain will now always return NOERROR for any query, all workloads will fail.
To make matters worse, this seems to mostly impact recursive queries. If I manually query the authoritative nameserver the correct response is returned:
ressu@denial ~> dig nosuchdomain.cloudflare.com @1.1.1.1
; <<>> DiG 9.18.12-1ubuntu1.1-Ubuntu <<>> nosuchdomain.cloudflare.com @1.1.1.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54049
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;nosuchdomain.cloudflare.com. IN A
;; AUTHORITY SECTION:
cloudflare.com. 300 IN SOA ns3.cloudflare.com. dns.cloudflare.com. 2318959390 10000 2400 604800 300
;; Query time: 36 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Sun Sep 03 19:01:55 IST 2023
;; MSG SIZE rcvd: 100
ressu@denial ~> dig nosuchdomain.cloudflare.com @ns3.cloudflare.com
; <<>> DiG 9.18.12-1ubuntu1.1-Ubuntu <<>> nosuchdomain.cloudflare.com @ns3.cloudflare.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 21644
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;nosuchdomain.cloudflare.com. IN A
;; AUTHORITY SECTION:
cloudflare.com. 300 IN SOA ns3.cloudflare.com. dns.cloudflare.com. 2318959390 10000 2400 604800 300
;; Query time: 28 msec
;; SERVER: 162.159.0.33#53(ns3.cloudflare.com) (UDP)
;; WHEN: Sun Sep 03 19:02:05 IST 2023
;; MSG SIZE rcvd: 100
Note that the response from 1.1.1.1
is NOERROR, while response from ns3.cloudflare.com
is NXDOMAIN
. Both responses are authoritative answers, so they should be both also responding NXDOMAIN
.