DNS delivery of Discovery of Network-designated Resolvers (DNR)

,

Thinking about it more, you can do this easily enough now with Pi-hole, using dnsmasq's option dns-rr but you need to encode the option yourself.

To be clear, this does not add dot, doq or doh functionality to Pi-hole. This is for use in cases such as described by @a7md0 to direct clients to installed proxies capable of handling that conversion.

The python code at the end of this post can generate the line for you, and the result would need to be entered into the misc.dnsmasq_lines setting in Pi-Hole. You would also need to make sure that dns.specialDomains.designatedResolver is disabled in the all settings dns tab.

rob@builder:~/git/svcb-encoder$ ./svcbencoder.py 
Domain name : (press enter for pi.hole)
IP address :1.2.3.4
Please select server type:
For each of the following (dot, doh, doq), please enter 'y' or 'n'
DNS over TLS - dot (y/n)y
DNS over QUIC - doq (y/n)n
DNS over HTTPS - doh (y/n)y
DOH path ( press enter for '/dns-query{?dns}' ) :
dnsmasq.conf option:
--dns-rr=_dns.reverse.arpa,64,000102706904686F6C65000001000702683203646F740004000401020304000700102F646E732D71756572797B3F646E737D
Pi-Hole misc.dns.masq_lines value:
Enter into settings, expert, all settings, miscellaneous, misc.dnsmasq_lines
dns-rr=_dns.reverse.arpa,64,000102706904686F6C65000001000702683203646F740004000401020304000700102F646E732D71756572797B3F646E737D

Confirm by running
dig SVCB _dns.resolver.arpa @pi.hole :

rob@builder:~/git/svcb-encoder$dig SVCB _dns.resolve.arpa @pi.hole

; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> SVCB _dns.resolve.arpa @pi.hole
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15648
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;_dns.resolver.arpa.		IN	SVCB

;; ANSWER SECTION:
_dns.resolver.arpa.	0	IN	SVCB	1 pi.hole. alpn="h2,dot" ipv4hint=1.2.3.4 key7="/dns-query{?dns}"

;; Query time: 31 msec
;; SERVER: 192.168.1.228#53(192.168.1.228) (UDP)
;; WHEN: Tue May 06 14:22:56 AEST 2025
;; MSG SIZE  rcvd: 107

Code:

#!/usr/bin/python3
import dns.rdata # pip3 install dnspython
import io

name = str(input("Domain name : (press enter for pi.hole)"))
name = name if name else "pi.hole"
ipaddr = str(input("IP address :"))
print("Please select server type:")
print("For each of the following (dot, doh, doq), please enter 'y' or 'n'")
nalpn = int(0)
dot = str(input("DNS over TLS - dot (y/n)"))
if dot == "y":
  nalpn = nalpn + 1
doq = str(input("DNS over QUIC - doq (y/n)"))
if doq == "y":
  nalpn = nalpn + 2
doh = str(input("DNS over HTTPS - doh (y/n)"))
if doh == "y":
  nalpn = nalpn + 4
match nalpn:
  case 1:
    alpn = "dot"
  case 2:
    alpn = "doq"
  case 3:
    alpn = "doq,dot"
  case 4:
    alpn = "h2"
  case 5:
    alpn = "h2,dot"
  case 6:
    alpn = "h2,doh"
  case 7:
    alpn = "h2,doq,dot"
  case 0:
    print("Nothing entered. Exiting...")
    quit
rclass = dns.rdataclass.IN
rtype = dns.rdatatype.SVCB
rdata = '1 '+name+'. alpn="'+alpn+'" ipv4hint="'+ipaddr+'"'
if nalpn >= 4:
  dohpath = str(input("DOH path ( press enter for '/dns-query{?dns}' ) :"))
  dohpath = dohpath if dohpath else "/dns-query{?dns}"
  rdata = rdata + 'key7="'+dohpath+'"'
rd = dns.rdata.from_text(rclass, rtype, rdata)
f = io.BytesIO()
rd.to_wire(f)
wire_data = f.getvalue()
print ("dnsmasq.conf option:")
print ("--dns-rr=_dns.resolver.arpa," + str(rtype) + "," + wire_data.hex().upper())
print ("Pi-Hole misc.dns.masq_lines value:")
print ("Enter into settings, expert, all settings, miscellaneous, misc.dnsmasq_lines")
print ("dns-rr=_dns.resolver.arpa," + str(rtype) + "," + wire_data.hex().upper())
1 Like

Thank you! This way really worked and it's exactly what I wanted to achieve. I will need to test it further on my setup

Although the test command should be (as per what we override using dns-rr)

dig SVCB _dns.reverse.arpa @pi.hole

Yikes. Thanks.

The script output has been corrected to "_dns.resolver.arpa".