DNS over TLS

Anyone who has already dealt with the security of the DNS protocol had to realize that it can be easily manipulated, monitored and censored without much effort. These censors are not only theory, but are already implemented by various countries. To cover these topics in the DNS protocol, several extensions were specified, such as DNSSEC with DANE/TLSA to detect man-in-the-middle attacks. The newest approaches in this area go a step further and encrypt the whole DNS traffic.

DNSCrypt and DNS-over-TLS are 2 implementations, which should replace the already existing and not particularly established DNSSEC standard. For DNS-over-TLS, there is now a adopted standard in the RFC7858, which I would like to setup here with the available resources. This gives users the advantage that even the Internet service provider (ISP) does not receive any more detailed information about the request, but merely sees that the user requests a specific DNS server. There is no complete anonymisation at all.

What and who can DNS-over-TLS

Short summary of what DNS-over-TLS is capable of:

  • TLS-encrypted TCP communication, default port: 853
  • The whole DNS traffic can be encrypted.
  • Verification of server certificates via CA

Since the standard was released by the IETF in May 2016, there are still few functional implementations of this RFC.
At DNSPrivacy.org there is a current overview of the current implementation progress:

(Date: 29.10.2017)

DNS Server with DNS-over-TLS Support:

  • Knot
  • Idns
  • Unbound

DNS Resolver (Client) with DNS-over-TLS Support:

  • knot
  • stubby
  • digit

BIND with TLS-Proxy

A very simple way to make an existing DNS server dns-over-tls capable is to use a TLS proxy such as with HAProxy. I have setup the following on my DNS server running CentOS 7.

Attention! The clients think they are talking a dns-over-tls server and keep the idle connections open when no EDNS0 keepalive is used (RFC7858). Possibly, the server is not robust enough for long-live connections and therefore not suitable for production use!


Install HAProxy:

# yum -y install haproxy
# systemctl enable haproxy

I set the following options:

  • BIND-Server listen additionally local ( on port 8853.
  • IP on external Interface
  • HAProxy is the encrypted endpoint, which according to the RFC is on port 853.
  • A SSL certificate from Letsencrypt

HAProxy requires to have the TLS certificate and the private key in a PEM file.


log /dev/log local0
chroot /var/lib/haproxy
user haproxy
group haproxy
maxconn 1024
pidfile /var/run/haproxy.pid
tune.ssl.default-dh-param 2048
ssl-default-bind-ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-options force-tlsv12

balance roundrobin
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout check 10s

listen dns
bind ssl crt /var/lib/acme/live/certificates/<cert>.pem
mode tcp
server server1


! With the additional BIND configuration, it must be ensured that the DNS servers do not allow recursive queries because the client is now localhost (

I configured the additional local ip (with scope host) on the interface eth1. Thus, only requests on the host are answered, although it is a routed interface. The IP address configured on the loopback device did not work with me, because in bind this adress is recognized as a client and therefore has full access to all zones and recursive queries.

ip addr add dev eth1 scope host

Now I add the new listen port to bind, and mark the new IP address as “not trusted” in my bind acl, so that it can’t access internal zones.

listen-on port 8853 {; };
acl "trusted" {;

In the end:

systemctl restart named-chroot
systemctl restart haproxy


Since there are not yet many integrations, a DNS resolver such as Unbound or Stubby can be installed locally. However, I would like to test only if quierying work, so I take the DNS client Digit for the tests.
Since this is not in the source repositories of fedora, I briefly compiled it by myself.

sudo dnf install compat-openssl10-devel.x86_64
tar xvfz digit-1.4.3.tar.gz
aclocal && automake --add-missing && autoconf

Now I can test with digit the dns-over-tls setup by specifying a file of the sites to query. For this test I have listed my 2 domains, blog.sandchaschte.ch and www.sandchaschte.ch:

$ ./digit -f /tmp/names -r -V
blog.sandchaschte.ch	A	IN
blog.sandchaschte.ch.	15M IN CNAME	sandchaschte.ch.
sandchaschte.ch.	15M IN A

The attempt with dig failes, since a TLS connection must first be established.

dig +tcp @ -p 853 www.sandchaschte.ch
;; communications error to end of file

Until the implementations of dns-over-tls are mature or supported in BIND, this is a working example, but not the best solution yet.

Nevertheless It works!