Troubleshooting DNS over TLS

I have been using DNSCrypt and DNS over HTTPS for a bit of time, but decided to give a try to the new DNS over TLS protocol today. The first problem I faced was the lack of software support and documentation on how DNS over TLS works and how to troubleshoot it.

I will try to fill this gap and talk a bit about DNS over TLS this article.

unEncrypted DNS

DNS is one of the most critical protocols for the Internet. Almost everything you do online starts first with a DNS request. The problem with DNS is that it is a clear-text protocol and everyone that is watching the traffic between you and your DNS provider, can see (and some times modify) the requests you are doing. It is actually common for ISPs and Hotels to hijack DNS requests to their own servers.

DNS over TLS

We all have learned (I hope) that we should not enter our passwords or personal information on sites without the padlock (known as HTTP:// sites). Google, Lets Encrypt, Mozilla and others are pushing the web to go to HTTPS:// only — encrypt everything. Google is even ranking HTTPS sites higher than the ones that are non-encrypted.

TLS (aka SSL) is the protocol we use on HTTPS. It wraps our HTTP requests into an encrypted form, so nobody can see our data. And the same TLS protocol can be used to wrap and encrypt our DNS requests.

I am over summarizing TLS here, but you can read about how it can be implemented with DNS on the RFC 7858.

DNS Server Support

DNS over TLS does not have a wide range of server support yet, but DNSDist , from the PowerDNS team, added support for it in their latest version. That's a great start for anyone looking to implement it themselves.

Also, 3 public DNS providers support DNS over TLS on port 853, allowing pretty much anyone to use it today:

  • Quad9 9.9.9.9: Anycast DNS — filters malicious domains.
  • CloudFlare 1.1.1.1: Anycast DNS — unfiltered
  • CleanBrowsing 185.228.168.168 — Anycast DNS — filters malicious and adult/porn domains.

Troubleshooting DNS over TLS

The beauty of DNS over TLS is that it is the same DNS protocol, just wrapped around the TLS layer. That makes it very easy to debug and troubleshoot.

1- Using OpenSSL

Using the OpenSSL command line tool, we can easily check if a server has DNS over TLS support and see if the server is responding (this is specially important for 1.1.1.1 that is blocked in some location). In this example, I am using the s_client option to connect to port 853 on the CleanBrowsing IP:

$ echo | openssl s_client -connect ‘185.228.168.168:853’ |grep -B 2 -A 5 “Certificate chain”
depth=1 C = US, O = Let’s Encrypt, CN = Let’s Encrypt Authority X3
CONNECTED(00000003)
 — -
Certificate chain
 0 s:/CN=cleanbrowsing.org
 i:/C=US/O=Let’s Encrypt/CN=Let’s Encrypt Authority X3
 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

As you can see, they use Lets Encrypt and the server is replying properly. I can do the same thing for CloudFlare to verify my connectivity:

$ echo | openssl s_client -connect ‘1.1.1.1:853’
 0 s:/C=US/ST=CA/L=San Francisco/O=Cloudflare, Inc./CN=*.cloudflare-dns.com
 i:/C=US/O=DigiCert Inc/CN=DigiCert ECC Secure Server CA

2- Using the DNS over TLS PHP client

OpenSSL is a great tool to test, but doesn't allow you to send and receive responses easily. DNS is a binary protocol, and we will use the lightweight PHP over TLS client to simplify it for us.

To start we need to clone the repository:

$ git clone https://github.com/dcid/dns-over-tls-php-client
Cloning into ‘dns-over-tls-php-client’…
remote: Counting objects: 13, done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 13 (delta 2), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (13/13), done.

Once that is cloned, you will see the dns-over-tls-php-client directory with the PHP file dnstls.php. That's the one we will use to test and send our queries.

To do a DNS request, you can run the command as:

$ php dnstls.php google.com cloudflare
google.com has address 74.125.24.100
google.com has address 74.125.24.101

If DNS over TLS is not supported (or you have the CloudFlare IP blocked), you will get this error:

Warning: stream_socket_client(): unable to connect to ssl://1.1.1.1:853 (Operation timed out) in /Users/nyk/dns-over-tls-php-client/dnstls.php on line 234

The tool supports CloudFlare, Quad9 and CleanBrowsing by default, but you can specify any IP address you wish. If you do not have the proper certificates installed on your server , you might get the following error:

Warning: stream_socket_client(): Peer certificate CN=`*.cloudflare-dns.com’ did not match expected CN=`1.1.1.1' in /Users/nyk/dns-over-tls-php-client/dnstls.php on line 234

That can be solved by upgrading OpenSSL locally on your server (or desktop). Note that if you are trying it against CleanBrowsing, it will return "domain not found" (NX) for domains that it blocks:

$ php dnstls.php pornhub[.]com cleanbrowsing
Host pornhub[.]com not found: 3(NXDOMAIN)

If you are using a custom resolver for DNS over TLS, you need to verify that its certificate is valid or you may get one of the errors I mentioned before.

DNS Privacy

And that's pretty much it for troubleshooting. DNS privacy is as important as HTTP privacy (HTTPS), so I recommend that everyone try DNS over TLS out and see if that works for you. You can also use DNSCrypt as it has more client support as this point.