Questions about installing DNS over HTTPS with Dnsmasq and https-dns-proxy

I noticed this install guide appears to have been updated recently (Last modified: 2019/09/19 01:24 by vgaetera):
https://openwrt.org/docs/guide-user/services/dns/doh_dnsmasq_https-dns-proxy

A couple questions I was hoping could be answered:

The guide says you can change the DoH Provider to another one, but I'm not sure how to do this.

It appears a URL is used in the example (uci set https_dns_proxy.dns.url_prefix="https://cloudflare-dns.com/dns-query?ct=application/dns-json&"). I thought this would be actual IP addresses.

If one is supposed to get a URL, where does one get it from? I do not see the Cloudflare URL that is present in the guide as one appearing on the DoH Provider list.

If I am supposed to use IP addresses, how exactly do I format primary, secondary, IPv4, and IPv6. For example, for Quad9, I would be specifying the following 4 IPs: 9.9.9.9, 149.112.112.112, 2620:fe::fe, 2620:fe::9

Yep, you basically need to change the URL.
The method in the how-to is a bit more complex to clean up all the previously configured providers, so you get exactly the one you want.

There's also the package luci-app-https_dns_proxy which should be available for OpenWrt 19.07 and Snapshot.

Choose a DNS provider that supports DoH, e.g. Quad9, then search Quad9+DoH and here it is:
https://www.quad9.net/doh-quad9-dns-servers/

Major DoH providers support domain names, so you typically do not need to use IP addresses.

Although running multiple instances should be still possible:

while uci -q delete https_dns_proxy.@https_dns_proxy[0]; do :; done
uci set https_dns_proxy.dns1="https_dns_proxy"
uci set https_dns_proxy.dns1.listen_addr="127.0.0.1"
uci set https_dns_proxy.dns1.listen_port="5053"
uci set https_dns_proxy.dns1.user="nobody"
uci set https_dns_proxy.dns1.group="nogroup"
uci set https_dns_proxy.dns1.url_prefix="https://doh1.example.org/?"
uci set https_dns_proxy.dns2="https_dns_proxy"
uci set https_dns_proxy.dns2.listen_addr="127.0.0.1"
uci set https_dns_proxy.dns2.listen_port="5054"
uci set https_dns_proxy.dns2.user="nobody"
uci set https_dns_proxy.dns2.group="nogroup"
uci set https_dns_proxy.dns2.url_prefix="https://doh2.example.org/?"
uci commit https_dns_proxy
/etc/init.d/https_dns_proxy restart

uci -q delete dhcp.@dnsmasq[0].server
while
DOHPROXY_ADDR="$(uci -q get https_dns_proxy.@https_dns_proxy[0].listen_addr)"
DOHPROXY_PORT="$(uci -q get https_dns_proxy.@https_dns_proxy[0].listen_port)"
DOHPROXY_SERV="${DOHPROXY_ADDR//[][]/}#${DOHPROXY_PORT}"
uci -q delete https_dns_proxy.@https_dns_proxy[0]
do
uci add_list dhcp.@dnsmasq[0].server="${DOHPROXY_SERV}"
done
uci revert https_dns_proxy
uci commit dhcp
/etc/init.d/dnsmasq restart

For older OpenWrt/LEDE, that Luci app is available from my repo: https://stangri.github.io/openwrt-repo/

Luci app has simple choices between providers, no need to specify the URL.

Also, the updated init script for https_dns_proxy (version 2018-04-23-1 and later) doesn't require user/group/listen_addr if they are default values. I believe it has been updated for current release as well.

@vgaetera thank you for information on Quad9 DoH, I'll update the Luci app.

1 Like

Since I'm anticipating 19.07 to be released soon, I'm thinking I should just wait and install 'luci-app-https_dns_proxy'.

I am looking forward to finally getting some DNS privacy and security. Thanks for all your work on this, guys/gals! It is greatly appreciated.

1 Like

Speaking of, I just tried a variety of Quad9 DoH servers, with and without explicitly specifying port 5053 in the URL, both with and without type=A in the request and it doesn't seem to work with https_dns_proxy. I get the instance started, but no resolution. If anyone has had positive experience with Quad9 DoH, please let me know.

@okji -- no, the URLs used in the config are NOT examples, they are working configs. Sorry about missing that earlier. :wink:

1 Like

It seems that the default implementation is now based on RFC 8484.
And it is quite different from the one that uses JSON API and hosted on the port 5053.
I'm not sure whether https_dns_proxy supports RFC 8484 or not.

The reply given by the old implementation includes DNSSEC record when available which seems to break the parser:

# nslookup openwrt.org 127.0.0.1#5053
Server:		127.0.0.1
Address:	127.0.0.1#5053

Name:      openwrt.org
Address 1: 139.59.209.225
Address 2: 2a03:b0c0:3:d0::1af1:1

# nslookup example.com 127.0.0.1#5053
Server:		127.0.0.1
Address:	127.0.0.1#5053

*** Can't find example.com: Parse error
*** Can't find example.com: Parse error

# curl "https://dns.quad9.net:5053/dns-query?name=openwrt.org"
{"Status":0,"TC":false,"RD":true,"RA":true,"AD":false,"CD":false,"Question":[{"name":"openwrt.org.","type":1}],"Answer":[{"name":"openwrt.org.","type":1,"TTL":1602,"Expires":"Mon, 30 Sep 2019 20:13:08 UTC","data":"139.59.209.225"}]}

# curl "https://dns.quad9.net:5053/dns-query?name=example.com"
{"Status":0,"TC":false,"RD":true,"RA":true,"AD":true,"CD":false,"Question":[{"name":"example.com.","type":1}],"Answer":[{"name":"example.com.","type":1,"TTL":37987,"Expires":"Tue, 01 Oct 2019 06:19:51 UTC","data":"93.184.216.34"},{"name":"example.com.","type":46,"TTL":81187,"Expires":"Tue, 01 Oct 2019 18:19:51 UTC","data":"A 8 2 86400 20191020120717 20190929102834 56575 example.com. EWZqo0Y+PjoPq4c1Pfqz6nPRuTs/URqwqkFJ9GvPCFJh8M9DyOI8BsyAHbU74wM9QrCQF9e1saWS/jPhBFQCNBMb9LhSeGKmLuXULIJ7aQX4B+oOEIokBsC/1alFhFYbHh6xPVCuo2qr52DAS9+Ia8qxTZrk01g99/P61BHNVNE="}]}

# uci get https_dns_proxy.@https_dns_proxy[0].url_prefix
https://dns.quad9.net:5053/dns-query?

Alas, this looks like not supported by Quad9 or they have their own JSON API implementation. :roll_eyes:

The JSON I get back when hitting port 5053 is pretty similar to what I get from Google DoH server, except that Quad9 adds the Expires tuple.

For https-dns-proxy using Cloudflare I had to add a line in /etc/config/https_dns_proxy :
option use_http_1_1 '1'

@stangri, just installed luci-app-https_dns_proxy from your repo, all looks good, but I have some suggestions if you don't mind.
Will be good to have enabled/disabled button to be able to temporarily disable DNS proxy without deleting everything.
When enabled we need to adjust /etc/config/dhcp - add "option noresolv '1'" and remove "resolvfile" if any. When disabled or completely uninstalled we need to revert all the changes there - set "option noresolv '0'" and restore the previous "resolvfile" value in addition to removal of "list server '127.0.0.1#5053'".

1 Like

Where? If you've added it to /etc/config/https_dns_proxy, unless there were other changes since I've submitted a new init script, that setting is ignored, so it doesn't do anything.

You mean to temporarily restore the previous dhcp.dnsmasq[0].server setting?

I don't have "option noresolv '1'" and I do have a resolvfile referenced from dnsmasq config and https_dns_proxy is working fine here, so I don't understand what do you mean.

Good call, will implement asap. Now that I've had time to reflect on it, not sure about this, what if the luci app is uninstalled, but the actual DoH proxy is still installed? Also, not sure if I can have a pre-rm in the luci app Makefile, I'll investigate.

No need to change resolvfile as it is ignored when noresolv=1.

No. With noresolv=1 only the single file named /etc/resolv.conf is ignored.
If any other file was referenced by resolvfile directive it will be still used. All was tested yesterday.

-R, --no-resolv
Don't read /etc/resolv.conf. 

The wiki documentation is a bit inaccurate - fixed.
Check out the source:

1 Like

Thank you for the information, however during my test yesterday I've noticed that the DNS server from the file referenced in resolvfile was still in use after I added noresolv=1 and reloaded dnsmasq.
I will re-test.

Note that service reload != restart.

1 Like

Noted. Will revise my test script and check.

1 Like

yes, this is the file
It should be added there if 'Cloudflare' is selected as a provider in Luci. Not required for Google.

I was probably wrong about resolvfile and save/restore requirements, however option noresolv '1/0' is required. '1' when entry is added and enabled, '0' - when entry is removed or disabled.

1 Like

No, it shouldn't: https://github.com/openwrt/packages/blob/master/net/https-dns-proxy/files/https_dns_proxy.init

Please test yourself if you can. This is not about https-dns-proxy, its about cloudflare server which works differently comparing to google. During my tests it was like a timeout with cloudflare without this option. It was just a guess that helped.
The option itself is definitely supported by the app, the keyword is here. This is a cli equivalent:

-x         Use HTTP/1.1 instead of HTTP/2. Useful with broken
             or limited builds of libcurl (false).

That's not how it works. The init script translates your /etc/config/https_dns_proxy options to the command line parameters and as I've explained before, the init file does not support that option. Moreover, I believe that the actual binary doesn't support that option either.

1 Like

The luci-app-https_dns_proxy (git-19.290.74883-9c3e931-6) now backs up the previously used servers, restores them on stop button click and also displays the information about running https_dns_proxy instances.

Available from my repo, I don't think it will be accepted to 18.06, but I'll try to send PR to master/19.07 when I solve the prerm issue.