AdguardTeam / AdGuardHome

Network-wide ads & trackers blocking DNS server
https://adguard.com/adguard-home.html
GNU General Public License v3.0
25.4k stars 1.83k forks source link

Treat empty responses as invalid during parallel requests #6508

Open POMATu opened 11 months ago

POMATu commented 11 months ago

Prerequisites

The problem

Neither adguard home nor dnsmasq nor other dns proxies that i know support this. Sometimes dns servers return empty response (domain not exists) just because their resolver module gone disconnected from upstream. The issue is actual when you want some freedom and when you are using something like opennic resolvers or blockchain resolvers (or even some meshnet resolvers) which provide you extra domain TLDs. Right now due to this issue i can only use opennic resolvers as upstreams because i want to use those extra tabooed TLDs. I cant use cloudflare/google alongside opennic resolvers because they will respond faster and i will get "domain does not exists" response. But even if i use only opennic resolvers the issue is still there, sometimes they just crack and then once again i get "domain does not exists" response just because some server replied faster than another working server. This DNS technology is too legacy and drives me nuts but i see adguard home as some solution that can potentially solve the issue as some extra feature since it already has more features comparing to dnsmasq.

Proposed solution

Add extra feature to treat empty responses as invalid during parallel requests. Wait for response from each upstream with timeout and only then respond that domain does not exists or ip is empty or whatever. Only if some ip came as response then treat it as job done and stop further waiting for other upstreams. This will make it more stable when upstream is nuts and also will allow to use cloudflare/google alongside any other custom TLD resolver and prevent cache poisoning/empty replies due to cloudflare/google faster responses.

Alternatives considered and additional information

Alternative could be adding a feature for setting resolvers per TLD but its pain in the ass. There are too many of them, sometimes new ones are introduced, its really not possible to track all custom TLDs and write em down like that. Much easier if machine would be able to just execute this simple algorithm and wait for more replies from other upstreams in case of empty response.

ainar-g commented 11 months ago

An empty NOERROR response (aka NODATA) is semantically different from an NXDOMAIN response. Which one of these would this feature treat as invalid? Or are you suggesting that any response that doesn't contain answer records would be considered invalid?

ardel commented 11 months ago

@POMATu have you tried "Fastest IP address" instead of "Parallel requests"? Does it solve your issue?

POMATu commented 11 months ago

@POMATu have you tried "Fastest IP address" instead of "Parallel requests"? Does it solve your issue?

i just run few tests and it works but its utterly unusable if one of dns upstreams is dead. When i remove dead upstreams it also becomes very slow occasionally like every 4 times i probe dns. Why does it waits for all responses? It makes no sense.

An empty NOERROR response (aka NODATA) is semantically different from an NXDOMAIN response. Which one of these would this feature treat as invalid? Or are you suggesting that any response that doesn't contain answer records would be considered invalid?

I have good reference that you can also use because its public opennic dns servers that are malfunctioning.

root@dsl:/#  dig flibusta.lib @137.220.55.93 -p 53

; <<>> DiG 9.11.5-P4-5.1+deb10u5-Debian <<>> flibusta.lib @137.220.55.93 -p 53
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12742
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 4a34474833f7e4a00100000065738dd86efc898f3fd7222e (good)
;; QUESTION SECTION:
;flibusta.lib.          IN  A

;; ANSWER SECTION:
flibusta.lib.       3600    IN  A   179.43.150.83

;; Query time: 238 msec
;; SERVER: 137.220.55.93#53(137.220.55.93)
;; WHEN: Fri Dec 08 21:42:49 UTC 2023
;; MSG SIZE  rcvd: 85

root@dsl:/# dig flibusta.lib @161.97.219.84 -p 53

; <<>> DiG 9.11.5-P4-5.1+deb10u5-Debian <<>> flibusta.lib @161.97.219.84 -p 53
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 26166
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;flibusta.lib.          IN  A

;; Query time: 192 msec
;; SERVER: 161.97.219.84#53(161.97.219.84)
;; WHEN: Fri Dec 08 21:43:01 UTC 2023
;; MSG SIZE  rcvd: 41

root@dsl:/# dig flibusta.lib @116.203.104.203

; <<>> DiG 9.11.5-P4-5.1+deb10u5-Debian <<>> flibusta.lib @116.203.104.203
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53692
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 0831fcb1037fcc730100000065738e04318f5e256feaef89 (good)
;; QUESTION SECTION:
;flibusta.lib.          IN  A

;; AUTHORITY SECTION:
lib.            3600    IN  NS  seed1.emercoin.com.
lib.            3600    IN  NS  seed2.emercoin.com.

;; Query time: 64 msec
;; SERVER: 116.203.104.203#53(116.203.104.203)
;; WHEN: Fri Dec 08 21:43:32 UTC 2023
;; MSG SIZE  rcvd: 121

One gives response, another one gives SERVFAIL third one gives empty response. Yup these alternative TLDs (and overall ancient DNS technology) are like that. If i probe cloudflare it gives NXDOMAIN response so this is also the case when adguard should wait for another reply or else - timeout.

Or are you suggesting that any response that doesn't contain answer records would be considered invalid?

And yes, i think its normal for browser or other client to lag for 2 seconds if site doesnt exists but its not normal to lag on every request (fastest ip address) neither normal to respond that site doesnt exists when it does exists

Parallel requests combined with "taking first non-empty response" method supposed to be both fast and reliable at the same time. And its even possible to take it further. There could be extra feature to not treat some ip addresses as valid response. This way adguard could drop fake landing page responses from DPI. But this problem wont occur if you use encrypted dns so i'd say its not that important.