1
Fork 0
blog/_posts/2018-02-07-d-oh-dns-over-https-in-rust.md

72 lines
2.6 KiB
Markdown

---
permalink: "/{{ year }}/{{ month }}/{{ day }}/d-oh-dns-over-https-in-rust"
title: "D'oh! - DNS over HTTPS in Rust"
published_date: "2018-02-07 09:05:00 +0100"
layout: post.liquid
data:
route: blog
tags:
- rust
---
Last weekend I met [Daniel Stenberg][bagder], author of curl, at FOSDEM and we talked a bit about curl, Firefox and also Rust.
One recent project he was working on was *DNS over HTTPS* [support for Firefox][firefox] and [eventually for curl][curl] as well.
*DNS over HTTPS*, short *DOH*, is a recent idea to do DNS queries over HTTPS for privacy, performance and security reasons. There's an [RFC draft in version 3][draft03][^1] at the IETF describing it in more detail.
The *tl;dr*: Send the DNS protocol in an HTTP POST request or base64-encoded in a GET request,
get back the DNS protocol in the response body and parse it.
Given how simple that sounds, I decided to implement a minimal DOH client in Rust.
I present to you:
<center>
<h3><a href="https://github.com/badboy/dnsoverhttps">dnsoverhttps</a></h3>
</center>
It exports one function to resolve a hostname to its IPv6 and IPv4 addresses:
```rust
extern crate dnsoverhttps;
fn main() {
let name = "example.com";
let addr = dnsoverhttps::resolve_host(name);
for a in addr {
println!("{} has address {}", name, a);
}
}
```
It currently uses `dns.google.com` (or to be exact one of its IPs: `172.217.21.110`) and skips TLS certificate checks (because the underlying HTTP request library has no option to pass in the hostname yet).
It will also always query for both IPv6 and IPv4 addresses (`AAAA` and `A` records respectively).
`CNAME` records will work as well by the mere fact that the server recursively resolves it and `dnsoverhttps` simply takes the found IP address.
Other records are not supported at the moment.
For a quick try you can install the bundled CLI tool to replace the `host` tool to resolve hostnames.
```
cargo install dnsoverhttps
```
And then execute it:
```
$ ~/.cargo/bin/host example.com
example.com has address 2606:2800:220:1:248:1893:25c8:1946
example.com has address 93.184.216.34
```
[Documentation is available online][docs].
[bagder]: https://twitter.com/bagder
[curl]: https://github.com/curl/curl/wiki/DNS-over-HTTPS
[firefox]: https://bugzilla.mozilla.org/show_bug.cgi?id=1434852
[draft03]: https://tools.ietf.org/html/draft-ietf-doh-dns-over-https-02
[dnsoverhttps]: https://github.com/badboy/dnsoverhttps
[docs]: https://docs.rs/dnsoverhttps/0.1.0/dnsoverhttps/
---
[^1]: `dnsoverhttps` currently implements Version 2, because that's what `dns.google.com` supports. Version 3 changes the query parameter from `body` to `dns`.