Quad9 is a public DNS resolver, with promises of better privacy, and a DNS-over-TLS access.
Last week, the new DNS resolver Quad9 has been announced. It is a public DNS resolver with the additional benefit that it is accessible in a secure way over TLS (RFC 7858).
There are plenty of public DNS resolvers. The best known one is Google Public DNS, but there are many others, each of them with different policies and technical features. The fact that so many users blindly use Google Public DNS, despite the huge amount of data that Google already collects about us, is worrisome. But there is also a technical problem, common to most public resolvers: the link to them is not secure. This allows hijackings, as seen in Turkey, as well as third-party monitoring.
The new Quad9 service on the other hand is operated by the not-for-profit Packet Clearing House (PCH), which manages large parts of the DNS infrastructure, and it allows access to the DNS over TLS. This makes it very difficult for third parties to listen in. And it makes it possible to authenticate the resolver (I have not yet tested this yet, Quad9 does not seem to distribute its public keys in an authenticated way, but they plan to do so).
Note that Quad9 claims not to store your IP address. Also note that their resolver is sometimes lying: it does not (deliberately) provide an answer for domain names that are considered to be related to harmful activities like malware distribution. You can have a non-lying resolver by using other addresses, but then you lose DNSSEC. In that case Quad9 uses an indication of the client's network (see RFC 7871), a bad privacy practice. Hopefully we will soon have an address for non-false responses, with DNSSEC and without indication of the customer's network.
Now, let's move on to practice on a Unix machine. The IPv4 address of Quad9, as the name implies, is 9.9.9.9
. Its IPv6 address is 2620:fe::fe
(see the FAQ). First, let's start with classic UDP access:
% dig +nodnssec @9.9.9.9 AAAA irtf.org ; <<>> DiG 9.10.3-P4-Ubuntu <<>> +nodnssec @9.9.9.9 AAAA irtf.org ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11544 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;irtf.org. IN AAAA ;; ANSWER SECTION: irtf.org. 1325 IN AAAA 2001:1900:3001:11::2c ;; Query time: 4 msec ;; SERVER: 9.9.9.9#53(9.9.9.9) ;; WHEN: Thu Nov 16 09:49:41 +08 2017 ;; MSG SIZE rcvd: 65
This shows that Quad9 validates with DNSSEC (the answer contains the AD - Authentic Data - bit).
If the domain is on the blacklist of Quad9 (thanks to Xavier Claude for having found such a name to test), the resolver answers with NXDOMAIN (No Such Domain - this domain does not exist):
% dig @9.9.9.9 www.hjaoopoa.top ; <<>> DiG 9.10.3-P4-Debian <<>> @9.9.9.9 www.hjaoopoa.top ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 1143 ;; flags: qr rd ad; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;www.hjaoopoa.top. IN A ;; Query time: 17 msec ;; SERVER: 9.9.9.9#53(9.9.9.9) ;; WHEN: Sat Nov 18 20:30:41 CET 2017 ;; MSG SIZE rcvd: 45
(With a non-lying resolver, we would have gotten the NOERROR return code and the IP address 54.213.138.248
.)
Now let's test the important benefit of this service, DNS over TLS. It's TLS so we can go with openssl:
% openssl s_client -connect \[2620:fe::fe\]:853 -showcerts depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3 verify return:1 depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3 verify return:1 depth=0 CN = dns.quad9.net verify return:1 --- Certificate chain 0 s:/CN=dns.quad9.net i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 -----BEGIN CERTIFICATE----- ... 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 i:/O=Digital Signature Trust Co./CN=DST Root CA X3 ... Server certificate subject=/CN=dns.quad9.net issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3 --- Peer signing digest: SHA512 Server Temp Key: ECDH, P-256, 256 bits ... New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported ... SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 ...
We see that Quad9 responds well in TLS, and that it has a Let's Encrypt certificate.
Next, let's test the getdns_query programme distributed with getdns:
% getdns_query @9.9.9.9 -s -l L www.afnic.fr AAAA { "answer_type": GETDNS_NAMETYPE_DNS, "canonical_name": <bindata for lb01-1.nic.fr.>, "just_address_answers": [ { "address_data": <bindata for 2001:67c:2218:30::24>, "address_type": <bindata of "IPv6"> } ...
Yes, getdns_query is very talkative. The -l L option tells it to use DNS over TLS.
I've also used tshark to check that we are actually using TLS:
% tshark -n -i wlp2s0 -d tcp.port==853,ssl host 9.9.9.9 Capturing on 'wlp2s0' 1 0.000000000 31.133.136.116 → 9.9.9.9 TCP 74 37874 → 853 [SYN] Seq=0 Win=29200 Len=0 MSS=1460 SACK_PERM=1 TSval=233018174 TSecr=0 WS=128 2 0.002518390 9.9.9.9 → 31.133.136.116 TCP 74 853 → 37874 [SYN, ACK] Seq=0 Ack=1 Win=28960 Len=0 MSS=1460 SACK_PERM=1 TSval=873811762 TSecr=233018174 WS=256 3 0.002551638 31.133.136.116 → 9.9.9.9 TCP 66 37874 → 853 [ACK] Seq=1 Ack=1 Win=29312 Len=0 TSval=233018175 TSecr=873811762 4 0.002642065 31.133.136.116 → 9.9.9.9 SSL 371 Client Hello 5 0.022008585 9.9.9.9 → 31.133.136.116 TLSv1.2 1514 Server Hello 6 0.022042645 31.133.136.116 → 9.9.9.9 TCP 66 37874 → 853 [ACK] Seq=306 Ack=1449 Win=32128 Len=0 TSval=233018180 TSecr=873811781 7 0.022050371 9.9.9.9 → 31.133.136.116 TLSv1.2 108 [TCP Previous segment not captured] , Ignored Unknown Record 8 0.022054712 31.133.136.116 → 9.9.9.9 TCP 78 [TCP Window Update] 37874 → 853 [ACK] Seq=306 Ack=1449 Win=35072 Len=0 TSval=233018180 TSecr=873811781 SLE=2897 SRE=2939 9 0.022667110 9.9.9.9 → 31.133.136.116 TCP 1514 [TCP Out-Of-Order] 853 → 37874 [ACK] Seq=1449 Ack=306 Win=30208 Len=1448 TSval=873811781 TSecr=233018175 10 0.022679278 31.133.136.116 → 9.9.9.9 TCP 66 37874 → 853 [ACK] Seq=306 Ack=2939 Win=37888 Len=0 TSval=233018180 TSecr=873811781 11 0.023537602 31.133.136.116 → 9.9.9.9 TLSv1.2 192 Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message 12 0.037713598 9.9.9.9 → 31.133.136.116 TLSv1.2 117 Change Cipher Spec, Encrypted Handshake Message 13 0.037888417 31.133.136.116 → 9.9.9.9 TLSv1.2 225 Application Data 14 0.093441153 9.9.9.9 → 31.133.136.116 TCP 66 853 → 37874 [ACK] Seq=2990 Ack=591 Win=31232 Len=0 TSval=873811853 TSecr=233018184 15 0.742375719 9.9.9.9 → 31.133.136.116 TLSv1.2 178 Application Data ...
The -d tcp.port == 853, ssl is there to tell tshark to interpret everything that goes through port 853 (DNS-over-TLS) as TLS. We can see the TLS dialogue, but obviously not the DNS queries and answers since everything is encrypted.
Now that these tests have been going well, let's use Quad9 for true name resolution. We will use Stubby to talk to Quad9. The Stubby configuration file looks like this:
listen_addresses: - 0::1@8053 dns_transport_list: - GETDNS_TRANSPORT_TLS upstream_recursive_servers: # Quad9 - address_data: 9.9.9.9 tls_auth_name: "dns.quad9.net" - address_data: 2620:fe::fe tls_auth_name: "dns.quad9.net"
Stubby is told to listen to the local address ::1
on port 8053, and to forward DNS queries over TLS to 9.9.9.9
or to 2620:fe::fe
. Then we launch Stubby:
% stubby [12:28:10.942595] STUBBY: Read config from file /usr/local/etc/stubby/stubby.yml [12:28:10.942842] STUBBY: Starting DAEMON....
And we can test it, using dig to query the specified address and port:
% dig @::1 -p 8053 A www.catstuff.com ; <<>> DiG 9.10.3-P4-Ubuntu <<>> @::1 -p 8053 A www.catstuff.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20910 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 65535 ;; QUESTION SECTION: ;www.catstuff.com. IN A ;; ANSWER SECTION: www.catstuff.com. 600 IN A 216.157.88.24 ;; Query time: 974 msec ;; SERVER: ::1#8053(::1) ;; WHEN: Thu Nov 16 20:29:26 +08 2017 ;; MSG SIZE rcvd: 77
We can then check with tshark or tcpdump that Stubby does speak with Quad9, and that it is using TLS.
Stubby has the advantage of managing TCP well, especially by reusing connections (it would be very expensive to establish a TCP connection for each DNS query, especially over TLS). But it does not cache the answers, which can be annoying if you're far away from the Quad9 server. In that case, it's best to add a real resolver, for instance Unbound. It is configured as follows:
server: interface: 127.0.0.1 do-not-query-localhost: no forward-zone: name: "." forward-addr: ::1@8053
With this configuration, Unbound will listen on 127.0.0.1
(on the default port, 53, the DNS port) and relay the queries for which it does not already have an answer in its cache to Stubby (::1
, port 8053). So, let's ask Unbound:
% dig @127.0.0.1 A mastodon.gougere.fr ; <<>> DiG 9.10.3-P4-Ubuntu <<>> @127.0.0.1 A mastodon.gougere.fr ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40668 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;mastodon.gougere.fr. IN A ;; ANSWER SECTION: mastodon.gougere.fr. 600 IN A 185.167.17.10 ;; Query time: 2662 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Thu Nov 16 20:36:09 +08 2017 ;; MSG SIZE rcvd: 64
Unbound has a memory (the cache) so if we send the query again, the answer will arrive much faster and we will see the TTL (here 600 seconds) decreased.
If you find that all this is very complicated to install or configure, you can use a Docker image, contributed by Juzam (also available on GitHub).
Note that it is not easy to find an IPv4 address that is so easy to remember as 9.9.9.9
. DNSDB shows that this address has been used a lot before arriving at PCH, and partially for activities that some may find questionable. This IP address is blacklisted in several places. If that does not work for you, talk to your provider, or try Quad9 over IPv6. We can see this imperfect connectivity by testing with RIPE Atlas and the atlas-resolve programme, comparing Quad9 and Google Public DNS:
% atlas-resolve -r 200 -e 9.9.9.9 --nsid -t AAAA irtf.org Nameserver 9.9.9.9 [ERROR: SERVFAIL] : 1 occurrences [TIMEOUT] : 9 occurrences [2001:1900:3001:11::2c] : 177 occurrences Test #10205081 done at 2017-11-16T01:41:40Z % atlas-resolve -r 200 -e 8.8.8.8 -g 10205081 --nsid -t AAAA irtf.org Nameserver 8.8.8.8 [TIMEOUT] : 1 occurrences [2001:1900:3001:11::2c] : 186 occurrences Test #10205089 done at 2017-11-16T01:46:38Z
The situation is better with IPv6, this time on par with Google (the second IPv6 test):
% atlas-resolve -6 -r 200 -e 2620:fe::fe -t AAAA irtf.org
Nameserver 2620:fe::fe
[NETWORK PROBLEM WITH RESOLVER] : 2 occurrences
[TIMEOUT(S)] : 5 occurrences
[2001:1900:3001:11::2c] : 191 occurrences
Test #10268718 done at 2017-11-20T15:15:32Z
% atlas-resolve -6 -r 200 -e 2001:4860:4860::8888 -t AAAA irtf.org
Nameserver 2001:4860:4860::8888
[TIMEOUT(S)] : 6 occurrences
[2001:1900:3001:11::2c] : 190 occurrences
Test #10268732 done at 2017-11-20T15:19:27Z
Many thanks to Sara Dickinson for her technical help.
This article was first published in French on my personal blog.
Comments 7
Comments are disabled on articles published more than a year ago. If you'd like to inform us of any issues, please reach out to us via the contact form here.
GAURAV KANSAL •
DNSDB link mentioned is only for account holders. Can we get the information about previous usage of 9.9.9.9 from any other source, which don't need an account ?
Hide replies
Stéphane Bortzmeyer •
DNSDB is subscription-only. But there are some gratis "passive DNS" databases such as https://passivedns.cn/ or https://www.circl.lu/services/passive-dns/
Robert Edmonds •
Re: > DNSDB shows that this address has been used a lot before arriving at PCH, and partially for activities that some may find questionable. Of course, address records in the DNS do not require any authorization from the number resource holder, so for "round number" IP addresses like 8.8.8.8, 9.9.9.9, etc. a lot of weird A-records pointing to those IP addresses would be expected. For instance, there are quite a few "questionable" records in DNSDB pointing at the resolver that I use, 10.10.10.10 :-)
OLF •
With the stubby config above I only receive a FORMERR $ dig @::1 -p 8053 A www.catstuff.com ; <<>> DiG 9.8.3-P1 <<>> @::1 -p 8053 A www.catstuff.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: FORMERR, id: 39788 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;www.catstuff.com. IN A ;; Query time: 115 msec ;; SERVER: ::1#8053(::1) ;; WHEN: Tue Nov 28 07:06:35 2017 ;; MSG SIZE rcvd: 45
Hide replies
Stéphane Bortzmeyer •
This is apparently because a known ECS bug https://github.com/getdnsapi/getdns/issues/357 already fixed in the code repository.
OLF •
Thank you. The version available via brew is too old. After building the latest version it is working fine.
Tom •
I really think there is still a question mark over Quad9 Quote: When you use Quad9 DNS Services, here is the full list of items that are included in our logs: Request domain name, e.g. example.net Record type of requested domain, e.g. A, AAAA, NS, MX, TXT, etc. Transport protocol on which the request arrived, i.e. TCP, UDP, and encryption status of the protocol Origin IP general geolocation information: i.e. geocode, region ID, city ID, and metro code Protocol version IP address – IPv4, or IPv6 Response code sent, e.g. SUCCESS, SERVFAIL, NXDOMAIN, etc. Absolute arrival time Name of the Quad9-operated machine that processed this request Quad9 target IP to which this request was addressed (no relation to the user’s IP address) We may keep the following data as summary information, including all the above EXCEPT for data about the DNS record requested: Currently-advertised BGP-summarized IP prefix/netmask of apparent client origin Autonomous system number (BGP ASN) of apparent client origin All the above data may be kept in full or partial form in permanent archives." If they are privacy conscious why are they logging the above? Also their partners may be seen as questionable too. Thanks Tom