0xERR0R / blocky

Fast and lightweight DNS proxy as ad-blocker for local network with many features
https://0xERR0R.github.io/blocky/
Apache License 2.0
4.77k stars 209 forks source link

When the returned query type is different from the queried one, Block does not cache it #830

Closed alpominth closed 1 year ago

alpominth commented 1 year ago

Easy to reproduce, just enable cache and test it:

$ time dig @127.0.0.1 -p 53 -t PTR t.co

; <<>> DiG 9.18.4-2ubuntu2-Ubuntu <<>> @127.0.0.1 -p 53 -t PTR t.co
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59632
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;t.co.              IN  PTR

;; AUTHORITY SECTION:
t.co.           1   IN  SOA ns1.p26.dynect.net. ops.twitter.com. 2538 3600 600 604800 60

;; Query time: 223 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Sun Jan 15 19:17:35 EST 2023
;; MSG SIZE  rcvd: 102

real    0m0.241s
user    0m0.006s
sys 0m0.003s
$ time dig @127.0.0.1 -p 53 -t PTR t.co

; <<>> DiG 9.18.4-2ubuntu2-Ubuntu <<>> @127.0.0.1 -p 53 -t PTR t.co
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37219
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;t.co.              IN  PTR

;; AUTHORITY SECTION:
t.co.           2936    IN  SOA ns1.p26.dynect.net. ops.twitter.com. 2538 3600 600 604800 60

;; Query time: 223 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Sun Jan 15 19:17:41 EST 2023
;; MSG SIZE  rcvd: 102

real    0m0.242s
user    0m0.009s
sys 0m0.000s

The queried type was PTR and a SOA was returned:

screensh

When using a different DNS client such as dnsproxy and looking at the timings, you can perceive that the different returned query type was cached:

$ time dig @127.0.0.1 -p 1053 -t PTR t.co

; <<>> DiG 9.18.4-2ubuntu2-Ubuntu <<>> @127.0.0.1 -p 1053 -t PTR t.co
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53471
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;t.co.              IN  PTR

;; AUTHORITY SECTION:
t.co.           293 IN  SOA ns1.p26.dynect.net. ops\@twitter.com. 2538 3600 600 604800 60

;; Query time: 223 msec
;; SERVER: 127.0.0.1#1053(127.0.0.1) (UDP)
;; WHEN: Sun Jan 15 19:22:19 EST 2023
;; MSG SIZE  rcvd: 102

real    0m0.243s
user    0m0.004s
sys 0m0.005s
$ time dig @127.0.0.1 -p 1053 -t PTR t.co

; <<>> DiG 9.18.4-2ubuntu2-Ubuntu <<>> @127.0.0.1 -p 1053 -t PTR t.co
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32015
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;t.co.              IN  PTR

;; AUTHORITY SECTION:
t.co.           292 IN  SOA ns1.p26.dynect.net. ops\@twitter.com. 2538 3600 600 604800 60

;; Query time: 0 msec
;; SERVER: 127.0.0.1#1053(127.0.0.1) (UDP)
;; WHEN: Sun Jan 15 19:22:20 EST 2023
;; MSG SIZE  rcvd: 102

real    0m0.019s
user    0m0.004s
sys 0m0.004s

The same problem is showed when querying A type on a AAAA only hostname:

time dig @127.0.0.1 -p 53 -t A v6.testmyipv6.com

===============================================================

I think this behavior should be fixed.

0xERR0R commented 1 year ago

Blocky caches positive responses (response with answer section) and negative responses (only NXDOMAIN). In your case, there is no answer section and status is NOERROR.

alpominth commented 1 year ago

Sorry, I forgot to set the option cacheTimeNegative: and I didn't know that it caches NXDOMAIN, it was my fault.

Thanks for the explanation.

alpominth commented 1 year ago

Results from any DNS server:

$ dig @1.1.1.1 -t ptr g.co

; <<>> DiG 9.18.4-2ubuntu2-Ubuntu <<>> @1.1.1.1 -t ptr g.co
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64255
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;g.co.              IN  PTR

;; AUTHORITY SECTION:
g.co.           60  IN  SOA ns1.google.com. dns-admin.google.com. 502341315 900 900 1800 60

;; Query time: 103 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Tue Jan 17 01:04:32 EST 2023
;; MSG SIZE  rcvd: 93

From cached Blocky:

$ dig @127.0.0.1 -p 53 -t ptr g.co

; <<>> DiG 9.18.4-2ubuntu2-Ubuntu <<>> @127.0.0.1 -p 53 -t ptr g.co
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5075
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;g.co.              IN  PTR

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Tue Jan 17 01:05:48 EST 2023
;; MSG SIZE  rcvd: 22

I know that this behavior is more aesthetic than practical in fact, but it would be a good idea to make Blocky cache queries with type different from the type queried, it would be more like a "normal" caching DNS proxy.