Skip to content

Instantly share code, notes, and snippets.

@Juul
Last active March 4, 2025 10:52
Show Gist options
  • Save Juul/8771c110c33fa24a2423e5087e6164fd to your computer and use it in GitHub Desktop.
Save Juul/8771c110c33fa24a2423e5087e6164fd to your computer and use it in GitHub Desktop.
DNS over TLS on OpenWRT / Debian using stubby and Quad9 9.9.9.9

This configures dnsmasq to forward queries to a locally running stubby which makes the DNS over TLS requests.

OpenWRT

opkg update
opkg install stubby

Edit /etc/config/dhcp adding the following to the dnsmasq section:

# use stubby
option noresolv '1'
list server '127.0.0.1#5453'

stubby is configured by /etc/config/stubby which is documented here

If you want to use SPKI pinning then you can get the current sha256 certificate hash like so:

echo | openssl s_client -connect '9.9.9.9:853' 2>/dev/null | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

Which should output a certificate hash like this:

i2kObfz0qIKCGNWt7MjBUeSrh0Dyjb0/zWINImZES+I=

Comment out all of the existing config resolver sections in /etc/config/stubby and instead add the following, replacing all instances of <cert_hash> with the certificate hash, or delete the list spki lines entirely if you don't want SPKI pinning. Note that SPKI pinning means that you will manually have to come back and change the has whenever the quad9 certificate is changed.

config resolver
       option address '9.9.9.9'
       option tls_auth_name 'dns.quad9.net'
       list spki 'sha256/<cert_hash>'

config resolver
        option address '149.112.112.112'
        option tls_auth_name 'dns.quad9.net'
        list spki 'sha256/<cert_hash>'

config resolver
        option address '2620:fe::9'
        option tls_auth_name 'dns.quad9.net'
        list spki 'sha256/<cert_hash>'

config resolver
        option address '2620:fe::fe'
        option tls_auth_name 'dns.quad9.net'
        list spki 'sha256/<cert_hash>'

Add the following to the config stubby 'global' section:

       option tls_cipher_list 'EECDH+CHACHA20'
       option tls_ciphersuites 'TLS_CHACHA20_POLY1305_SHA256'
       option tls_min_version '1.2'
       option tls_max_version '1.3'

Enable stubby and restart:

/etc/init.d/stubby enable
/etc/init.d/stubby restart
/etc/init.d/dnsmasq restart

Debian

sudo apt update
sudo apt install dnsmasq stubby

On systems that don't use uci the stubby config file is /etc/stubby/stubby.yml. Change the port in the listen_address to 5353:

listen_addresses:
  - 127.0.0.1@5353

Add the following options:

tls_cipher_list: "EECDH+CHACHA20"
tls_ciphersuites: "TLS_CHACHA20_POLY1305_SHA256"
tls_min_version: GETDNS_TLS1_2
tls_max_version: GETDNS_TLS1_3

Comment out any existing upstream servers and add the following, replacing all instances of <cert_hash> with the certificate hash:

upstream_recursive_servers:
  - address_data: 9.9.9.9
    tls_auth_name: "dns.quad9.net"
    tls_pubkey_pinset:
      - digest: "sha256"
        value: <cert_hash>

  - address_data: 149.112.112.112
    tls_auth_name: "dns.quad9.net"
    tls_pubkey_pinset:
      - digest: "sha256"
        value: <cert_hash>

Restart stubby:

systemctl restart stubby

To configure dnsmasq edit /etc/dnsmasq.conf. You'll probably want to comment out any dhcp-range options if you don't want to also use dnsmas as a DHCP server. You should add at least the following lines:

no-resolv # don't read /etc/resolv.conf
server=127.0.0.1#5353 

You might also want to set the interface that dnsmasq listens on:

interface=eth1

Then restart dnsmasq:

sudo systemctl restart dnsmasq
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment