Skip to content

DNS over TLS

This one has been a long time coming, I’ve been trying to get to this for over a month. It’s small on work but big on ideas.

The Push for Encryption

There incoming tide is pushing hard on everyone to encrypt all traffic on the web. I think it’s great for end user security and a necessary direction. Yes it makes things difficult for administration and troubleshooting, but that goes along with the same old see-saw of security vs inconvenience. Besides, if it’s really a problem that’s what proxy servers and local CA’s are for. Lets-Encrypt has helped the small sites (such as this one) get publicly signed without the financial burden. HTTP is becoming less and less common. I’m not saying that HTTPS is needed for everything. It isn’t going to save the world when you’re not logging into a site and just consuming content, like what you’re doing right now here. But I log in here, and I want encryption for that. That’s why this site is signed. Google has also been pushing hard and downstream changes will cause HTTP sites to display “Not Secure” in the address bar come July.

So for the basic user and the vast majority of web traffic, let’s say all sites on the web switch to HTTPS. There’s still one glaring hole, DNS. DNS interception isn’t going to give up passwords or show a Man In the Middle the content, but they will see what domain names a user is querying against. It’s can be obvious the amount of time spent on facebook, youtube, or any site on the web by monitoring DNS. This information is seen plain as day to the DNS forwarder or root, but also to someone like an ISP who can monitor DNS traffic in the clear and build metrics to sell to other companies.

Encrypted DNS

There’s quite a few DNS encryption projects that are at some stage in their life cycle, and some new, some dying. The site below is a great resource on the subject.

https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+-+The+Solutions

We’ve been lucky that also this year that 2 contenders have invested quite a bit into DNS. Cloudflare and Quad 9. Both groups are respectable and both support DNS over TLS, port 853.

Everything here has made it a good time to put this into practice. There are some desktop apps that can run on individual machines to encrypt DNS traffic. Again see https://dnsprivacy.org for more information. If you already have a private DNS server though, there’s a very easy way to encrypt all external DNS traffic with just a couple steps.

 

Stubby

Stubby is a small deamon that really does one thing, resolve DNS over TLS. Linux being what it is, if an existing DNS server is already up and running it only needs Stubby installed and it’s forwarders can just be adjusted to point to localhost on Stubby’s listening port and it can take over all forwarding requests. Configuration here is pretty simple as the config files are very verbose, but I’ll post the blob below.

On RHEL like systems, install with

yum install getdns

This is going to install unbound as well as stubby, but if the system is already running bind it can continue to just use that.

Then edit

vim /etc/stubby/stubby.yml

Notice YAML. The key bits that are needed are below

resolution_type: GETDNS_RESOLUTION_STUB

dns_transport_list:
 - GETDNS_TRANSPORT_TLS

tls_authentication: GETDNS_AUTHENTICATION_REQUIRED

tls_query_padding_blocksize: 128

edns_client_subnet_private : 1

idle_timeout: 10000

listen_addresses:
 - 127.0.0.1@8053
 - 0::1@8053

round_robin_upstreams: 0 #0 causes forwarders to function as a traditional list rather than the default round robin.

upstream_recursive_servers:
 - address_data: 1.1.1.1
 tls_auth_name: "dns.cloudflare-dns.com"
 tls_pubkey_pinset:
 - digest: "sha256"
 value: yioEpqeR4WtDwE9YxNVnCEkTxIjx6EEIwFSQW+lJsbc=
 - address_data: 9.9.9.9
 tls_auth_name: "dns.quad9.net"
 tls_pubkey_pinset:
 - digest: "sha256"
 value: G+ullr8exb9aHemu3vmI9Jwquuqe0DwnBdFHss8UfVw=

I have both Cloud flare and Cloud 9 configured above. If you need to grab the public key from another TLS capable DNS server, just shoot a

echo | openssl s_client -connect '9.9.9.9:853' 2>/dev/null | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

Changing the IP to the target. And if you need the TLS Authentication Name, use

openssl s_client -connect X.X.X.X:853 -tls1_2

And look for

subject=/CN=

For the correct FQDN.

Once all set there, all that’s left is to adjust the forwarders in named.conf  or unbound conf file and restart all services. It’s also possible to monitor stubby just by typing it, stubby, and see live output of what it’s up to. This causes all DNS traffic leaving my network to be encrypted and private aside from the Quad9 and Cloudflare.

DNSSEC

The last bit I want to mention, DNSSEC, verifies the DNS entry. Similar to CA’s and certs for HTTPS, DNS needs to validated. This prevents a malicious DNS server from returning false answers. Stubby is on top of this and with v1.2, all that’s needed is to add

dnssec_return_status: GETDNS_EXTENSION_TRUE

to the YAML configuration file.