I saw the recent announcements from Mozilla, Cloudflare and Google about running a trial to try and make DNS name resolution more secure.
The basic problem is that most users get their DNS server set via DHCP which is controlled by who ever runs the network (at home this tends to be their ISP, but when using public wifi this could be anybody). The first approach to help with this was Google’s 8.8.8.8 public DNS service (followed by the IBM’s 9.9.9.9 and Cloudflares 1.1.1.1). This helps if people are technically literate enough know how to change their OS’s DNS settings and fix them to one of these providers. Also DNS is UDP based protocol which makes it particularly easy for a bad actor on the network to spoof responses.
The approach the 3 companies are taking is to run DNS over an existing secure protocol, in this case HTTPS. From Firefox version 60 (currently in beta) it is possible to set it up to do name host name resolution via DNS-Over-HTTPS.
There are currently 2 competing specifications for how to actually implement DNS-Over-HTTPS.
DNS Wireformat
This uses exactly the same data structure as existing DNS. Requests can be made via a HTTP GET or POST. For a POST the body is the binary request and the Content-Type is set to application/dns-udpwireformat.
For GET requests the payload is BASE64 encoded and passed as the dns query parameter.
In both cases the response is the same binary payload as would be made by a normal DNS server.
This approach is currently covered by this draft RFC
JSON
For this approach the request are made as a HTTP GET request with the hostname (or IP address) being passed as the name and the query type being passed as the type query parameters.
A response looks like this:
{ "Status": 0, "RA": true, "RD": true, "TC": false, "AD": false, "CD": true, "Additional": [], "Answer": [ { "TTL": 86400, "data": "93.184.216.34", "name": "example.com", "type": 1 } ], "Question": [ { "name": "example.com", "type": 1 } ] }
With a Content-Type of application/dns-json
You can find the spec for this scheme from Google here and Cloudflare here.
Both of these schemes have been implemented by both Google and Cloudflare and either can be used with Firefox 60+.
Privacy Fears
There has already been a bit of a backlash against this idea, mainly around privacy fears. The idea of Google/CloudFlare being able to collect information about all the hosts your browser resolves scared some people. Mozilla has an agreement in place with CloudFlare about data retention for the initial trial.
Given these fears I wondered if people might still want to play with DNS-Over-HTTPS but not want to share data with Google/Cloudflare. With this in mind I thought I’d try and see how easy it would be to implement a DNS-Over-HTTPS server. Also people may want to try this out on closed networks (for things like performance testing or security testing).
It turned out not to be too difficult, I started with a simple ExpressJS based HTTP server and then started to add DNS support. Initially I tried a couple of different DNS NodeJS nodes to get all the require details and in the end settled on dns-packet and actually sending my own UDP packets to the DNS server.
I’ve put my code up on github here if anybody wants a play. The README.md should include details about how to set up Firefox to use an instance.