Local DNS DoT “upgrade”

First of all: This seems to be my first blogpost since 2014. Partially because of time constraints and also because what to tell ๐Ÿ˜‰ Let’s see if the frequency stays at one post per 7 years.

Just a quick overview of my local DNS setup at home as it was for some years until yesterday:

  • I’m running a Synology Diskstation as network storage as well as a kind of infrastructure server for my home network because I bought it already for that purpose because of its ability to run Docker containers in addition to the normal DSM software and services. A network storage was a basic requirement (I had one for many years before) and because this has to run anyway 24×7 I was looking for a possibility to run as many things as possible on it to not require yet another power consuming device. Others run one or more Raspis but when it comes to disk usage and activity that one is not the best choice I think.
  • On the Synology I already had running a pi-hole docker container for quite some time to provide a network wide malware (and yes, also tracking and advertisement) filter. That one is running on a macvlan Docker network because otherwise pi-hole would not recognize the different devices/IPs. As the Synology Docker implementation is rather limited in the UI but provides also docker-compose via shell access this setup is done via docker-compose.
    My DHCP server (built into my central Mikrotik router) provides the pi-hole IP as DNS server to all clients. (And BTW my outgoing firewall does filter all outgoing access to and the other Google DNS IP. Actually I’m doing a DNAT to the pi-hole for those requests. Some clients accept it and some don’t but hey, that’s how it is.)
  • I still use my ISPs DNS resolvers as recursors for pi-hole because I more or less trust my ISP, would hope that those are closest to my Internet connection with small(est) latency and because I believe in the Internet’s decentralized architecture and want to avoid concentration of vital services into a few big players like Google and Cloudflare. Even if their policies look nice I’m not sure how much those really can be trusted. Not to forget they are US companies.

Having said this: Those services in general have a point. Probably even more in networks/countries not under the European GDPR where collecting data from DNS requests (without consent) would be QUITE illegal.
What is certainly true though is that the still common style of DNS resolution is quite behind my normal privacy expectations.

So at least as a start to address this in my own little silo I decided to go for encryption of DNS traffic. For this different possibilities exist like DoT (DNS over TLS) and DoH (DNS over HTTPS) and probably also others. As I do not see why I would need to use DoH for my home network I decided to go for DoT for now. (NB: I think DoH can be a very good technology especially when being a roadwarrior connecting to arbitrary networks with mobile devices.) (A good summary why I’m not a real DoH fan for general purpose can be found here.)

So with that idea and the fact that pi-hole itself does not support any of that and also does not have real plans to do so I went on and searched for possibilities. What you the find are some references to stubby, unbound and cloudflared. You find even some references how to integrate those with pi-hole but all informations I found are about pi-hole on a Raspi where you can easily install an additional service but very few hints about how to do it in a Docker setup.


I decided to go for stubby as I heard good things about it and I didn’t need a full recursor like unbound and as I already indicated cloudflared was already out even when it was just from its name and origins.

So it was clear that I need a second container to run stubby while it might have been possible to load stubby into the pi-hole docker container with some effort I wanted to be sure that the DoT proxy is available within the whole network and not only to pi-hole. (Just because w/o a real usecase right now.)
In any case I was searching for a usable stubby container or Dockerfile to create one and ended up using https://github.com/MatthewVance/stubby-docker.git. That one looked quite ok for my usecase, I just changed the Dockerfile to the latest openssl version and the stubby configuration to the DoT servers I would like to connect to. In my case I used one provided by my ISP (which is only semi-official right now but hopefully becomes fully official at some point) and also Quad9’s. This is also some sort of central but at least somewhat more trustable than the other big guys.

Then I quickly learned that connecting a Docker container running on a macvlan network is not able to reach its Docker host network which was a blocking issue until I found a solution. There was some sort of workaround mentioned somewhere in the wide Internet which was something around creating another macvlan bridge on the host to be able to communicate but I was afraid of doing that on the Synology. No idea how flexible DSM would be around such a manual thing.

So what I tried next to solve the Docker host connectivity issue was to add a second network to the pi-hole container (I’ve chosen the default bridge in the beginning) to be able to communicate with the stubby container on the same network. Now, what to say. I wasn’t able to find any reliable way to make sure that pi-hole would set up eth0 on the macvlan and ethX on the other network. Whatever I tried (docker-compose network priority) ended up with macvlan NOT on eth0. For whatever reason I do not yet understand. Still pi-hole can be configured to listen on all interfaces which is not exactly what I wanted but as a workaround that turned out be good enough finally.

After I got both containers connected to the same Docker network, I was facing the next issue: pi-hole expects an IP address as upstream resolver but in the Docker world you don’t care about IP addresses in most cases. Everything is automatic by default.
To solve that issue I ended up with a new specific network instead of the default bridge and a direct IP assignment for the stubby container:

    container_name: stubby
    image: wrosenauer/stubby:latest
    hostname: dns
      - "53:8053/udp"
    restart: unless-stopped

    driver: bridge
        - subnet:

This setup now seems to work quite alright (as much as I can tell after a day) for me.

And I finally decided to write something up here because I do not have a huge Docker background and was searching the net for hints how a setup with pi-hole and stubby could look like (on a Docker host which is not totally flexible) and had a hard time to find good pointers. I’m not sure if someone will find this in future searching for a similar solution but at least there is a slighty better chance now ๐Ÿ˜‰