So in a litte while Google Chrome is going to enable DNS over HTTPs, and Firefox has already enabled it, by default!
So I think to myself “myself, do you want cloudflare watching all your DNS queries?” - nope is the the answer!
Right, so I’ll build my own DNS over HTTPs (DoH) server.
This doc assumes you have a working DNS server (I use bind9), and you can sort your own SSL certs for nginx.
It also assumes you know your way around a command line 🤪
Set up nginx
So I’m not going to talk you through how to install nginx, or get it running, that is beyond the scope of this doc.
I’m also not going to tell you how to setup Let’s Encrypt, that is also outside the scope of this doc.
So let’s get straight into the config:
So let me talk you through the config:
I start by creating a config that points to our, not yet installed, doh-server. That server is going to be running on port 8053:
Next I’ve got a server block for port 80 (non-secure / non https).
It has some config for my Let’s Encrypt SSL cert bot (dehydrated), and redirects everthing to the SSL version of the website (return 301):
and lastly, the SSL version config, includng the reverse proxy bit which I will repeat here (because it is the important bit):
So assuming that you have your SSL certs sorted, and your nginx config is all good you should be able to start nginx 🥰
Install doh-server
so you’ll need some build packages, so let’s install some build tools: aptitude install curl software-properties-common build-essential git
Now let’s config the DoH server:
The DoH server has a config in /etc/dns-over-https/doh-server.conf
You want to change the upstream to use 127.0.0.1:53 and that’s about it, here’s what I’ve got:
Once you’ve got that saved you can restart the DoH server with systemctl restart doh-server
Testing the install
So let’s recap:
We have:
Configured nginx and got it running nicely, forwarding DoH requests
Installed a DoH server
We already had a DNS resolver installed and running, right? 🧐
Now let’s do some testing.
The DoH server returns JSON, so you can just test in your browser:
https://ns1.example.com/dns-query?name=example.org&type=A
Or, since you’re already working in a terminal (and this website is called Terminal Addict 😇)
You should get a JSON response like the following:
Configure your browser
Well in Firefox this is pretty easy.
Search your preferences / settings in Firefox for DNS.
In Google Chrome the setting will be released in version 78 I’m told, I guess I’ll keep an eye out 🙃
Conclusion
So, maybe you’re super sentive about people spying on you, maybe you like playing with new gadgets / tech. Who knows.
But, I certainly don’t trust cloudflare enough to be giving them my browser DNS queries!
So we’ve now got DNS over HTTPs to use, and we own all our own history / data 👍
If you are interested as a user in “just using a private DNS server” and not building you own, let me know.
I might build a public facing DoH server for people to use.
Nice article, I have 2 questions. Do clients support authentication? Like, assuming Nginx was set up for HTTP basic auth, could I use a full URL like https://user:password@host/ in the Firefox preferences above? Which brings me to my second question, is there a need for Nginx in this setup? Assuming you aren’t already running a web server on 443 of course, it seems like the DoH server can listen directly for requests.
So after 5 seconds of testing, it looks like Firefox does support HTTP basic auth, so yes, you could configure your DNS server as user:pass@ns1.example.com
The need for Nginx is to server SSL certs (HTTPS); you could use anything (maybe write your own Go web service? or fork the DoH server and add in SSL support), so long as it has the ability to 1) reverse proxy to the DoH server, and 2) server SSL certificates, or 3) write a new DoH server that supports SSL 😀
This DoH server doesn’t have the ability to communicate via SSL.
I assumed from the config entries cert and key that the DNS-over-HTTPS server would serve TLS. The code would appear to back me up but I’ll have to try an installation before I can say for sure.
Paul
You could be right !!!
I might do some testing myself !
I’d also have to figure out how to do Let’s Encrypt without Nginx as well
Hanif
thanks for your help, im doing research for my final exam about DoH
Adib
Hi Paul, thanks for writing this.
Why do you need for a “package” dns-over-https? Because I think that “the dns-query” from nginx can head straight to Bind9. Could you explain this more plase?
Thankyou.
Hi,
you need the doh server to interpret between a DNS conversation, and a http conversation.
The doh server returns JSON to nginx.
So you need nginx for SSL and http conversation (although you may not, as Michael points out above)
you need the DoH server as an interpreter between http and dns.
and you need bind (or some other) dns server.
Scale question
First, thanks for the nice post, well written
To what scale have you been able to test this ?
Paul
Hey Amos, this doesn’t seem to consume a lot of resources. I haven’t tested within an ISP environ yet, only within say 50-100 desktops
Wonyoung Park
Hi Paul, i tried DoH configuration by following your document, but it didn’t work when i tested in firefox, but it worked in curl. do you have any ideas? thanks.
Paul
Hi Wonyoung, how did you confirm it was working in Firefox?
I can see in my nginx logs queries happening, and things working as expected?
14 Comments