All the guides I see for using DNS-over-TLS on OpenWRT require unbound, what I found out is that in fact you only need stubby, which does the DNS-over-TLS and acts as a proxy for DN resolution.
Stubby is simple to configure and dnsmasq can point to this proxy instead and continue to do all the things it needs to do such as domain name caching.
Because I have this setup running in a old router (4/32) without much space on the overlay to install stubby and its dependencies I have it setup so it installs stubby on startup to the RAM, because of this I'm presenting 2 tutorials, one for a RAM installation and another for a permanent install. All the instructions are for the console, stubby doesn't have a LUCI module so you must be confortable with configuring your router using SSH and Linux.
These configuration are for running DNS-over-TLS in STRICT mode on Cloudfare 188.8.131.52 service.
Strict mode means that only encrypted requests are allowed from a server with a valid certificate.
Install to RAM
Add the following lines to /etc/rc.local (what to do when the router boots)
opkg update opkg install ca-bundle -d ram opkg install stubby -d ram rm /tmp/opkg-lists/* sleep 5 export PATH="/usr/sbin:/usr/bin:/sbin:/bin:/tmp/usr/bin:/tmp/usr/sbin" && export LD_LIBRARY_PATH="/tmp/lib:/tmp/usr/lib" && /tmp/usr/sbin/stubby -C /etc/myconfig/stubby.yml -g
CA-bundle installs the certificates bundle needed for TLS
The rm command is there to free up some space from the RAM (deletes the OPKG lists as they are no longer needed)
The Export commands are required in order to be able to run applications and libraries installed to the /tmp/ dir (RAM).
Finally it launches stubby, notice the "-C /etc/myconfig/stubby.yml" that is the configuration file (more on that later), you can store permanently as the example in /etc/myconfig (myconfig is an example, just make sure to include the dir in your backup configuration).
You should first run those commands by manually via console on your router before having them run automatically at startup.
First, run the opkg commands to install all that we need.
Secondly copy the default config from /tmp/etc/stubby/stubby.yml to your custom config dir in /etc/
Now we need to edit /etc/myconfig/stubby.yml using vi.
#NOTE: See '/etc/stubby/stubby.yml.default' for original config file and descriptions resolution_type: GETDNS_RESOLUTION_STUB dnssec_return_status: GETDNS_EXTENSION_TRUE appdata_dir: "/tmp/stubby" tls_ca_file: "/tmp/etc/ssl/certs/ca-certificates.crt" dns_transport_list: - GETDNS_TRANSPORT_TLS tls_authentication: GETDNS_AUTHENTICATION_REQUIRED tls_query_padding_blocksize: 128 edns_client_subnet_private : 1 round_robin_upstreams: 0 idle_timeout: 10000 listen_addresses: - 127.0.0.1@5453 - 0::1@5453 upstream_recursive_servers: # IPv6 addresses # # Cloudflare IPv6 - address_data: 2606:4700:4700::1111 tls_port: 853 tls_auth_name: "cloudflare-dns.com" # # Cloudflare IPv6 - address_data: 2606:4700:4700::1001 tls_port: 853 tls_auth_name: "cloudflare-dns.com" # # Quad 9 IPv6 # - address_data: 2620:fe::10 # tls_auth_name: "dns.quad9.net" # IPv4 addresses # # Cloudflare servers - address_data: 184.108.40.206 tls_port: 853 tls_auth_name: "cloudflare-dns.com" # # Cloudflare servers - address_data: 220.127.116.11 tls_port: 853 tls_auth_name: "cloudflare-dns.com" # Quad 9 service # - address_data: 18.104.22.168 # tls_auth_name: "dns.quad9.net"
dnssec_return_status: GETDNS_EXTENSION_TRUE : This line provides DNSSEC validation
appdata_dir: Where the keys for DNSSEC are stored
tls_ca_file is important, this is the name and location of the CA bundle file required for TLS to work.
notice the "listen adresses", 5453 is the port number dnsmasq will have to connect on localhost.
Finally we need to edit dnsmasq.conf in /etc/.
Add the following lines (replace the existing server(s) lines)
no-resolv proxy-dnssec server=127.0.0.1#5453
If the only "server" line present in the dnsmasq.conf is the one above then all requests from clients will go to
To test the settings:
killall dnsmasq /etc/init.d/dnsmasq start export PATH="/usr/sbin:/usr/bin:/sbin:/bin:/tmp/usr/bin:/tmp/usr/sbin" && export LD_LIBRARY_PATH="/tmp/lib:/tmp/usr/lib" && /tmp/usr/sbin/stubby -C /etc/myconfig/stubby.yml -g
It's important to notice, that with this configuration the DNS traffic is only available for clients after stubby is successfully installed and running.
In order for the router to run opkg and set the time after reboot it needs to perform Domain Name resolution even thou Stubby is not running yet, because of that I only have dnsmasq running for the clients, all dn lookups made by the router itself are going to the ISP DN servers that are obtained via DHCP on the WAN side.
If everything is working correctly (you can use http://www.dnsleaktest.com/ to test, note that you will not see the 22.214.171.124 IP but you should see the ISP name as Cloudfare, the IP you will see there is that of the closest cloudflare server and that is a good thing) then you can reboot and have rc.local do the job for you.
The permanent install is simpler
Run the following commands manually:
opkg update opkg install ca-certificates opkg install stubby
Edit /etc/stubby/stubby.yml (see above, but you shouldn't need to set the tls_ca_file), and edit dnsmasq as above.
killall dnsmasq /etc/init.d/dnsmasq start /etc/init.d/stubby start /etc/init.d/stubby enable
Attention: this tutorial is a work in progress and might be incomplete, use at your own risk.