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!

HAProxy

Install HAProxy:

# yum -y install haproxy
# systemctl enable haproxy

I set the following options:

  • BIND-Server listen additionally local (127.0.0.2) on port 8853.
  • IP 127.0.0.2 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.

/etc/haproxy/haproxy.cfg

global
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

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

listen dns
bind 0.0.0.0:853 ssl crt /var/lib/acme/live/certificates/<cert>.pem
mode tcp
server server1 127.0.0.2:8853
Bind

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

I configured the additional local ip 127.0.0.2 (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 127.0.0.1 client and therefore has full access to all zones and recursive queries.

ip addr add 127.0.0.2/8 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 { 127.0.0.2; };
acl "trusted" {
    127.0.0.1;
    !127.0.0.2;
};

In the end:

systemctl restart named-chroot
systemctl restart haproxy
Test

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
./configure
make

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 159.100.252.246 -V
-----DNS Msg: len=367; response; id=19383-----
Que:
www.sandchaschte.ch A   IN
Ans:
www.sandchaschte.ch.    15M IN A    159.100.248.212
...
.           9h6m8s 4096 4096  4096 bytes
-----DNS Msg: len=685; response; id=19384-----
Que:
blog.sandchaschte.ch    A   IN
Ans:
blog.sandchaschte.ch.   15M IN CNAME    sandchaschte.ch.
...
sandchaschte.ch.    15M IN A    159.100.248.212
...

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

dig +tcp @159.100.252.246 -p 853 www.sandchaschte.ch
;; communications error to 159.100.252.246#853: 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!

Next Post Previous Post

Add a comment