Local DNS - override v6 addresses, don't forward a v6 request if a v4 entry exists

I've set up local DNS to return 10.0.0.10 for deb.debian.org

I would expect AAAA queries to my PiHole server to return NXDOMAIN, however, I'm getting the original DNS back as you can see.

Yes my PiHole is configured correctly on v4 and v6, as is this client.

voltagex@debian:~$ dig deb.debian.org @10.0.0.232

; <<>> DiG 9.20.1-1-Debian <<>> deb.debian.org @10.0.0.232
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41839
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;deb.debian.org.                        IN      A

;; ANSWER SECTION:
deb.debian.org.         0       IN      A       10.0.0.10

;; Query time: 4 msec
;; SERVER: 10.0.0.232#53(10.0.0.232) (UDP)
;; WHEN: Sat Aug 24 22:02:12 AEST 2024
;; MSG SIZE  rcvd: 59

voltagex@debian:~$ dig aaaa deb.debian.org @10.0.0.232

; <<>> DiG 9.20.1-1-Debian <<>> aaaa deb.debian.org @10.0.0.232
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4702
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;deb.debian.org.                        IN      AAAA

;; ANSWER SECTION:
deb.debian.org.         1161    IN      CNAME   debian.map.fastlydns.net.
debian.map.fastlydns.net. 25    IN      AAAA    2a04:4e42:7::644

I think the way local DNS works for queries like these should at least be configurable, but should default to the "least surprising" option.

Where's the surprise then?

If you request an AAAA record, of course Pi-hole would return it if it exists.
It'd not only be a surprise, but an outright bug if it would return a A record instead.

It would also be expected that IPv6 capable clients would often prefer to communicate via IPv6.

Note that you are shadowing a specific public DNS record (A) here.
If you'd want to exercise control over IPv6 addresses returned for your shadowed deb.debian.org, you simply could supply an IPv6 address via Local DNS records, or you could opt to regex block AAAA replies for it, see Pi-hole extensions - Pi-hole documentation .

I get you, but I've added an A record, most clients will ask for both kinds of records so the behaviour I was seeing was

  • Add a local DNS record
  • Receive the non-PiHole entry instead

Which is where the surprise was coming from.

1 Like

Aye, that's because you are shadowing a public domain. :wink:

If that would domain have been yours, you may have been in for other surprises for other record types as well (e.g. MX).

1 Like

Perhaps some tickboxes on the local DNS page would make this clearer - "only answer for set record types" or something like that.

You are not looking for NXDOMAIN (meaning the entire domain does not exist) but a no-AAAA-record situation (NOERROR without any answer records).

As @Bucking_Horn already explained, the behavior is as expected: You overwrote a specific query type (A) for a given domain and any other record which is not locally defined is queried upstream. This is both desired and also desirable default behavior.

What you are looking for can be achieved by adding the custom dnsmasq line

local=/deb.debian.org/

specifying that this domain should be treated local-only and unknown records are considered non-existent.

With Pi-hole v6.0 (currently still in beta), this can easily be added in the config option:
image

With the current stable release, please create a file like /etc/dnsmasq.d/99-my-locals.conf and add the line there. Issue a pihole restartdns thereafter.

If I'm reading the docs correctly, deb.debian.org;reply=10.0.0.10 should do what I want

;; ANSWER SECTION:
deb.debian.org.         2       IN      AAAA    ::

;; Query time: 3 msec
;; SERVER: 10.0.0.232#53(10.0.0.232) (UDP)
;; WHEN: Sat Aug 24 22:32:45 AEST 2024
;; MSG SIZE  rcvd: 71

voltagex@debian:~$ docker run -it debian
root@27d8e5c95412:/# apt update
0% [Connecting to deb.debian.org (::)]

But the client tries to connect to localhost (?) breaking things more than NOERROR would.

Right yes, I'd definitely mixed those up.

Well, only partially, :: is an invalid address, the client will not be able to connect to it. IPv6 localhost would be ::1.

If you want to do it via regex, you should probably do it separately for A and AAAA:

deb.debian.org;querytype=A;reply=10.0.0.10
deb.debian.org;querytype=AAAA;reply=nodata

but note that this still leaves any other type (which may be irrelevant for you) unspecified so they'd be forwarded if queried.

1 Like

I appreciate the detailed response from both of you. I'm on version 6 at the moment so will use the misc.dnsmasq_lines option.

1 Like

My recommendation was to regex block AAAA, e.g.

deb.debian.org;querytype=AAAA;reply=NODATA

But DL6ER's local approach is broader, so also worth considering.

Did you read what it says on the page:

The server deb.debian.org does not have packages itself, but the name has SRV records in DNS that lets apt in stretch and later find places.

http://deb.debian.org/

APT for Debian or Ubuntu etc will connect to those SRV records, if they exist, instead of A or AAAA DNS record(s):

Another example for the us.archive.ubuntu.com repo:

$ dig +short _http._tcp.us.archive.ubuntu.com srv
2 0 80 ubuntu-mirror-1.ps5.canonical.com.
2 0 80 ubuntu-mirror-2.ps5.canonical.com.
0 0 80 ubuntu-mirror-2.ps6.canonical.com.
0 0 80 ubuntu-mirror-1.ps6.canonical.com.
1 Like

yes, I remembered the srv records afterwards. AFAICT it should fall back to AA / AAAA lookups if the srv records don't exist.