-
Notifications
You must be signed in to change notification settings - Fork 0
DNS over TLS
Wikipedia describes DNS over TLS like this:
DNS over TLS (DoT) is a security protocol for encrypting and wrapping Domain Name System (DNS) queries and answers via the Transport Layer Security (TLS) protocol. The goal of the method is to increase user privacy and security by preventing eavesdropping and manipulation of DNS data via man-in-the-middle attacks.
Normally DNS queries and answers are not encrypted which makes it possible for ISP, goverments or other people that want to spy to do man-in-the middle attacks, for instance replace or block answers from DNS servers. By using protocols with encryption it becomes much harder to do this. DNS over TLS is one way to do it. DNS over HTTPS is another way.
Stubby is an application that acts as a local DNS Privacy stub resolver (using DNS-over-TLS). Stubby encrypts DNS queries sent from a client machine (desktop or laptop) to a DNS Privacy resolver increasing end user privacy.
Unbound is a validating, recursive, caching DNS resolver. It is designed to be fast and lean and incorporates modern features based on open standards.
We are going to use Stubby in combination with Unbound - Unbound provides a local cache and Stubby manages the upstream TLS connections (since Unbound cannot yet re-use TCP/TLS connections). You can get the same result by combining Stubby with dnsmasq as described here.
Installing Stubby on debian involves compiling from source code and may be a bit complicated for normal users. Combining it with Unbound also involves some configuration. A much easier way to do it is to use precompiled docker images. Matthew Vance has developed a docker solution that sets this configuration up. You can find them on dockerhub too - Stubby and Unbound.
This allows you to run a Stubby for better DNS over TLS support than Unbound provides without losing the performance benefits of having a local caching DNS resolver.
You need docker and docker-compose to follow this guide. If you have not already installed it you can take a look at our Docker and Docker Compose guide.
First we create the directory structure. I make a hidden directory .docker-compose with sub-directory dns and then switch to this directory:
$ mkdir -p .docker-compose/dns
$ cd .docker-compose/dns
If you don't already have git installed you must install it:
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install git
Now we clone the github repository for stubby-docker. It will download the files from github.
$ git clone https://github.com/MatthewVance/stubby-docker.git
It should have created a sub-directory stubby-docker. So whe change to this directory and take a look.
$ cd stubby-docker
$ ls
docker-compose.yml LICENSE README.md stubby unbound
So the files are there. Let's look at README It say:
Run these containers with the following command:
docker-compose up -d
Next, point your DNS to the IP of your Docker host running the Unbound container.
So we try it:
$ docker-compose up -d
Creating network "stubby-docker_dns" with the default driver
Pulling stubby (mvance/stubby:latest)...
latest: Pulling from mvance/stubby
54f7e8ac135a: Pull complete
66170bcb01a5: Pull complete
5881139a0be6: Pull complete
a03aecab42b3: Pull complete
55c847a40f60: Pull complete
Digest: sha256:e93b3268e8a07b7cce38d22e8b4edfe6cd54b0087edd21692419005e601262c8
Status: Downloaded newer image for mvance/stubby:latest
Pulling unbound (mvance/unbound:1.9.1-stubby)...
1.9.1-stubby: Pulling from mvance/unbound
54f7e8ac135a: Already exists
3eccb92b6ccd: Pull complete
a70020235b32: Pull complete
87c7b21b9491: Pull complete
f8d023a3f8fb: Pull complete
4cdd69e842f9: Pull complete
7fe28bf832ab: Pull complete
Digest: sha256:31154ca953ed07cfd0b1c411f5fe745aae3f29f496691cb6f89c21ec5a408db4
Status: Downloaded newer image for mvance/unbound:1.9.1-stubby
Creating stubby-docker_stubby_1 ... done
Creating stubby-docker_unbound_1 ... error
ERROR: for stubby-docker_unbound_1 Cannot start service unbound: driver failed programming external connectivity on endpoint stubby-docker_unbound_1 (fd86825918aa736aa63edf8392b2c7f745b32ae8e95b621a1d1d1b3c57a8d9ad): Error starting userland proxy: listen udp 0.0.0.0:53: bind: address already in use
ERROR: for unbound Cannot start service unbound: driver failed programming external connectivity on endpoint stubby-docker_unbound_1 (fd86825918aa736aa63edf8392b2c7f745b32ae8e95b621a1d1d1b3c57a8d9ad): Error starting userland proxy: listen udp 0.0.0.0:53: bind: address already in use
ERROR: Encountered errors while bringing up the project.
It downloads docker images from docker-hub and tried to start the containers. I got an error when starting unbound container because I already have unbound running on this machine. Docker is forwarding the container to localhost and it conflicts with local unbound. I could stop unbound.service but I don't want it to forward to localhost so I edit docker-compose.yml and remove ports section. First make sure container is stopped:
$ docker-compose down
Then edit docker-compose.yml file
$ nano docker-compose.yml
Made it look like this:
version: '3'
services:
stubby:
image: "mvance/stubby:latest"
networks:
- dns
restart: unless-stopped
unbound:
image: "mvance/unbound:1.9.1-stubby"
depends_on:
- "stubby"
networks:
- dns
volumes:
- ./unbound/a-records.conf:/opt/unbound/etc/unbound/a-records.conf:ro
restart: unless-stopped
networks:
dns:
The difference between original is that i removed this:
ports:
- "53:53/udp"
These lines tells docker to forward port 53 to localhost and it cause the conflict with my unbound.service
So we try to start it again (this time it does not need to download containers, already done):
$ docker-compose up -d
Creating network "stubby-docker_dns" with the default driver
Creating stubby-docker_stubby_1 ... done
Creating stubby-docker_unbound_1 ... done
It looks like it started successfully! OK then how to use it? According to the README
Next, point your DNS to the IP of your Docker host running the Unbound container.
How do I know "the IP of your Docker host running the Unbound container"? It is possible to look it up but I want to set a specific known IP-address and to be sure it is used every time. I fiddlered around quite a bit to make this work and ended up creating a dedicated network bridge in docker for DNS servers and set fixed ip addresses for each container. All this is controlled by editing the docker-compose.yml file.
So first stop the containers docker-compose down
and edit the docker-compose.yml file until it looks like this: