Secure your DNS

Eliminate the weakest link

/ n3rd, Internet, Hosting, Linux

The idea:

When you access a website, for example, then a piece of software between you and your goal translates this address to a set of numbers, an IPv4 or IPv6 address. Somebody controls this service. This somebody might not be your friend.

Such a set of numbers is the house number of your goal on the web. Since there are extremely numerous addresses in the world wide web, such a journey requires many hops until you arrive at the door of your goal. This is very danger lurks.

In almost all settings, the service to turn a typed address into such a number is handled your Internet Service Provider (ISP). These might be nice or naughty, these might log which addresses you access or ignore it, these might send you straight on your way or worse, detour you to an alternative address.

We want to cut this weak link of the web and replace it with something we can control. We want this for all of your devices and wherever we are. At home, at work or on the go. This ensures our privacy, it speeds up our web and it massively reduces the clutter and size of websites.

But best of all, it makes browsing the web safe. We know that we see is really what we see. We secure ourselves against attacks by bad players. This is a very, very real problem on the web.

This "guide" has three chapters:

  1. Why we all need this.
  2. How to setup the server
  3. How to use it on your devices.

For starting out, you can just look at the last chapter and use existing services.

List of contents

The background

Building the solution

Server side

Client side


  1. 13.11.18: Error corrections, like removing # where they needn't be. Thanks, @Dennis.
  2. 15.11.18: Added initial Android info & internal preperations for ipv6 additions

Your provider alters your Internet

Imagine your ISP wants you to use their movie streaming services. Whenever you try to access netflix, you end up on their streaming site. That is because they intercept your attempt to reach netflix and detour you. Is this happening already? Partly: In Germany the Deutsche Telekom offers an opt-in service that touts itself to detach your music and video streaming from your high speed data volume. How do they do that? They inspect the addresses you visit and the packages sent to you. Packages with certain quality and signatures are then marked as exempt. Sounds good? Well, it has two significant downsides: The Telekom looks into your packages and alters them, for example lowering the bitrate of music or resolution of videos when there's load on the network. The second downside: This only works for partners of the Telekom. If you don't partner with the Telekom or vice versa, your streaming services are counted against the high-speed data volume. That is strongly against net neutrality.

Spicy: While you can chose the server who should answer your requests to turn address into numbers, called DNS requests, on Desktop PCs and Macs, neither Android nor iOS allow you to do this for mobile networks. The result? In Germany the Deutsche Telekom hijacks your DNS requests. Every time you call Cloudflare or another DNS provider to translate an address for you, the Telekom jumps in between. Another good reason to make the ISP what it really is: A mere servant to bring you connectivity to the world.

Your government spies on you

Another example: Imagine your ISP reports certain addresses you attempt to visit to the government and logs your moves on the Internet. This is invisible to you, until it becomes very apparent when they powers that be are at your door. Is this happening? Almost definitely is. But be aware: The approach presented here does not protect your from spying state players, almost nothing can. If you want to hide your entire traffic from spying eyes between you and your goal it's almost always recommended to use a VPN and do all Web surfing via https connections. But this is a different topic.

But there is more to that.

Websites you visit are much more than you see

If you visit any average commercial websites, like or, then such pages load tons of resources from other places of the Internet along with themselves.

If you are interested in finding out, there are neat addons like Noscript for which can enlighten you on just how many domains are really loaded when you visit a website.

Websites rely on third-party services to provide all sort of things: From extra content like videos and images to fonts and scripts to create metrics of their usage. There're even services that, kind of, watch your behavior.

Their scripts step in if you are about to leave the website or are missing carrying out an important action. For example: An airline might remind you to finish your booking with a notification because others are about to snatch your seats if you idle too long. Or an online store directs your attention to an offering you are about to miss if you continue scrolling.

Such services can be helpful or annoying - but most of the time they come from other parties than the one you are intending to interact with. This can be a problem, since these service providers also know that you are visiting certain websites. They can track you. This is how google generates a huge part of its revenue, this is how facebook tracks you across the web. Such trackers are something we want to avoid.

You are the product

Companies like google or facebook spent tons of money on technology that can reliably track you on all your steps of your digital life. Not having an account with their services doesn't save you. Only herd immunity could help there. They don't just track you to show you ads, but companies produces something I call personas of you. Digital twins of your online behavior. These personas start as a shadow, trailing your steps but with every acquired data point it moves forward, until your digital shadow walks solidly in front of you. Not only the NSA, but also tech companies want to predict your behavior to design their products to your future needs. Sounds good? Well, don't forget: Your data is what they sell. If they anticipate your behaviors and design their services around such participated patterns, then they predetermine your behavior. Just look at digital echo chambers and their effect on the people of the USA, which become increasingly polarized.

Since you are the product, you should not have free will

I cannot stress that enough: The data companies collect about you can be, will be and is being used to manipulate your behavior and emotions.

If the wrong state-level players gaining access to all the data collections of you on the web and connect the vectors, then a state can have full control of your digital fate. No move would be surprising, until you change your behavior pattern and raise a red flag. Think this is conspiracy bullshit? Look at the social credit score system in China. Mass surveillance and firewalling turned into mass control with the help of WeChat and Social Scoring.

Is this a tech article or where am I?

Enough with the political and privacy motivations to take control of your Internet. It should have become self-evident by now that in order to protect your wallet, sanity and capacity of critical thinking we need to protect the web and to protect us in it. At the end of the article I will point you to some resources where you can learn on how to become an activist for freedom and freedom of the web.

What do we want to protect against?

In order to have a safe web experience, we need to protect us from three things:

  1. Man in the middle attacks (see ISP hijacking your requests)
  2. Tracking (we don't want a digital persona of us walking ahead)
  3. Malware (keeping our data safe is paramount)

Personally, my initial motivation for embarking on this journey was

  1. Protect myself from advertising

Wait, why no advertisements?

This is a murky thing. Some websites rely on advertisements and show ads which are not at all evil. Some websites on the other hand only exist to show you ads. Being shown ads in exchange for a service is a fair deal, or it should be. The arms race between ad-blockers and advertisers, joined by with lowering revenue from ads, has lead to very obstructive and resource intensive ads on websites and in apps. All these self-playing movies, animations, colorful images require work from your hardware and bandwidth with your provider.

I have less of my monthly high-speed data and lowered battery life due to ads. This is unacceptable. Thus I decided for the nuclear option: Ban all advertisement from my Internet experience. Everywhere and on every device.

Secure DNS vs VPN

There is one important to differentiation to make between a VPN and a DNS solution for privacy: A VPN can tunnel your entire traffic securely across the internet from your endpoint to a defined endpoint on the Internet. This way you can pass your data across insecure intermediaries. This can help overcoming firewalls, censorship and avoid tracking. Again, all your packets might be tunneled this way.

Securing your DNS requests in the way described here ONLY secures resolving domain names. The actual traffic of your Internet use goes through your normal network. This means while an ISP doesn't know your opened movie2k or somer other dubious page, they very well can see the traffic.

Why then not always use VPN? Depending on your situation you should always VPN. But for the home user in free country, for example in Europe, it might not be necessary yet to go nuclear like this. For mobile devices, VPN can have battery impact and it can make your Internet slower. So when you are fairly sure about your Internet connection, securing your DNS eliminates the only weak link you're facing.

Build it

Building the solution

This chapter is getting technical. Unfortunately, there's no simple plug-and-play or pay and be happy solution. By the definition as laid out above, there can't be. This is something you need to control in order to be sure. Also, I'll be switching to technical terminology now, because otherwise this will become a book.

Warning: I'm a docker fan. This setup is built around docker and my very poor understanding of it. Docker is not intended to be used on single VPS like I do it, but it's still great for it.

The structure

  1. Client: dnscrypt-proxy - Takes your DNS requests and sends it out via HTTPS to the DoH-Server
  2. Server: DoH-Server - receives DNS requests via HTTPS and sends DNS request on port 54 or via linux sockets to pi-hole
  3. Server: pi-hole - caches requests and filters out all the junk we don't want and requests solutions from unbound via local port 53 or linux sockets
  4. Server: unbound - caches requests as well and asks trusted authoritative DNS servers in a secure way for resolution or alternatively acts as a authoritative DNS server if you're really paranoid

Server side

You need: A server on the web with a domain name

Basically you need a device which you can access from everywhere on the web. This can by a dedicated server like's hardware, or it can be your home router with an alternative firmware. The easiest would most likely be attaching an SoC-board like the Raspberry Pi to your router or installing software on a NAS box.

You need: DoH server

The first piece of software is a DNS-over-HTTPS server. It's a open-source standard co-developed by google (ironic, isn't it) to send DNS requests via a HTTPS connection. Instead of sending a DNS request via port 53 and UDP in the open (in the fucking open!) to a server as recommended by your gateway, you send a DNS request via HTTPS to such a server.

I've opted for a great implementation by coder from Chinese naming himself "Star Brilliant" because it was the only one I could find to do what I wanted. It's widely used and open source. This adds to a feeling of security.

How to install DoH server

  1. Compile it yourself with their instructions
  2. Use my, so far undocumented, docker image which builds upon my alpine linux based webserver image.

How to configure DoH server

You want to make sure that the DoH server can be reached via the domain name of the server and you want to make sure that the server communicates with pi-hole for upstream DNS requests, see here for an example:

# HTTP listen port
listen = [
# TLS certification file
# If left empty, plain-text HTTP will be used.
# You are recommended to leave empty and to use a server load balancer (e.g.
# Caddy, Nginx) and set up TLS there, because this program does not do OCSP
# Stapling, which is necessary for client bootstrapping in a network
# environment with completely no traditional DNS service.
cert = ""
# TLS private key file
key = ""
# HTTP path for resolve application
path = "/dns-query"
# Upstream DNS resolver
# If multiple servers are specified, a random one will be chosen each time.
upstream = [
# Upstream timeout
timeout = 60
# Number of tries if upstream DNS fails
tries = 10
# Only use TCP for DNS query
tcp_only = false
# Enable logging
verbose = false

In the example above the listen port 8053 is tuned to the nginx config. The upstream DNS server points at a pi-hole container running in the same docker network with the hostname "pi-hole" which listens on port 53 for DNS request.

doh-server docker run command

I start all my docker services via systemd on CoreOS.

Description=doh server for grundstil

ExecStartPre=-/usr/bin/docker kill grundstil-doh-server
ExecStartPre=-/usr/bin/docker rm grundstil-doh-server
ExecStartPre=-/usr/bin/docker pull gymnae/docker-dns-over-http2-proxy:latest
ExecStart=/usr/bin/docker run -d --hostname=doh-server --network=<networname> --name=grundstil-doh-server --link=pi-hole -e "VIRTUAL_HOST=subdomain.domain.tld" -e "LETSENCRYPT_HOST=subdomain.domain.tld" -e "[email protected]" gymnae/docker-dns-over-http2-proxy:latest
ExecStop=/usr/bin/docker stop grundstil-doh-server


For this to work you first must create a docker network with a name and then replace <networkane> with its name: docker network create --driver=bridge --subnet= <networkname>

That is all there is. Of course you'd need to adjust the environment variables to your needs

Add webserver

The DoH server alone is not presenting itself to the web. It needs to accompanied by a webserver, which in turn must be reachable by a domain name.

Docker webserver

I'm using my own docker image as a webserver in connection with the great jwilderproxy and it's letsencrypt companion. Following the links will give you great instructions to get started.

If you use my docker image, you get a the webserver as part of the DoH-server and thus have a ready to go solution.

My nginx.conf for the DoH-server docker image can be found here.

Other webserver

If you don't use docker (boooh) there are million ways to install and configure a webserver. This is out of scope for this guide, but you can find in-depth instructions at the very inspiring blog post by Antoine Aflalo.

You need: pi-hole

Pi-hole comes from the world of raspberry pi and is a super nice kit to stop ads, trackers, malware and, if you want, porn on DNS level. Stopping ads before they reach your devices has all the mentioned benefits of reducing load on network and processing power.

Pi-hole also comes as a docker image. Installing it is very easy. Pairing it with jwilderproxy and its letsencrypt companion can have you accessing pi-hole through a sub-domain in very short time. Docker, it's just great. A great pain, but great.

Install pi-hole

  1. Use the official docker image
  2. Install pi-hole on your device without docker: curl -sSL | bash

Configure pi-hole

pi-hole has to point at your unbound server - but since we are still to do this, you can follow the pi-hole manual to set up blocking and other features to your liking. This is where you can dive into ad blocking or block whatever you want. You can also turn sinister at this point: pi-hole can extensively log DNS requests. If you want to be fair and make yourself less of a target for questioning, turn off logging completely.

pi-hole can be configured to block not only ads, but also porn, malware and even fake news pages - real fake news, not what Trump calls fake news. You have to balance your decisions, otherwise well meaning blocking turns to censorship.

You could also stop here and point pi-hole to use the cloudflare DNS servers - but then your pi-hole would do insecure DNS request to the configured DNS servers - which could defeat the purpose if you haven't left the network with the rogue DNS provider yet, for example you installed pi-hole on a raspberry pi in your home network.

After installing unbound all you have to do is pointing pi-hole at the IP (domain name won't work) of your local unbound install.

At least for me, pi-hole forget the DNS set when re-creating the container even when it's saving persistent data to a volume. Thus I have fixed the SetupVars.conf file with the chattr command

pi-hole docker start command

For some reason, here I opted for a docker-compose file instead of a systemd unit file:

    container_name: pi-hole
    image:  pihole/pihole:latest
    restart: unless-stopped
    hostname: pi-hole
#    ports:
#     - "53:53/tcp"
#     - "53:53/udp
      - ServerIP=<yourexternalipv4>
      - ServerIP6=<yourexternalipv6>
      - IPv6=true
      - name=pi-hole
      - network-alias=pi-hole
      - TZ=CEST-2
      - WEBPASSWORD=<averysecurepassword>
      - VIRTUAL_HOST=subdomain.domain.tld
      - LETSENCRYPT_HOST=subdomain.domain.tld
      - [email protected]
      - <docker volume or host folder>/pihole:/etc/pihole/
      - <docker volume or host folder>/pihole/dnsmasq.d/:/etc/dnsmasq.d/

Please note the commended ports: It's not necessary to publish ports when using them only in the internal network. Which is the case. I assign a fixed IP to pi-hole just to be safe. You again need to edit in your domain data and your <yourexternalipv4>. The other parts should be self-explanatory.

You need: unbound

Unbound is a validating, recursive, and caching DNS resolver. With unbound you create your own DNS resolver. This means over time fewer and fewer calls to so-called authoritative DNS servers, like cloudflare, are done. This increases security. If unbound request a resolution from an upstream server, it does it in a secure manner.

To quote

To help increase online privacy, Unbound supports DNS-over-TLS which allows clients to encrypt their communication. In addition, it supports various modern standards that limit the amount of data exchanged with authoritative servers. These standards do not only improve privacy but also help making the DNS more robust. The most important are Query Name Minimization, the Aggressive Use of DNSSEC-Validated Cache and support for authority zones, which can be used to load a copy of the root zone.

Install unbound

Again, you have options. I opted for a docker image made by a fellow docker enthusiast, Matthew vance. His image points at the fast and secure Cloudflare DNS servers and brings a robust base config.

unbound docker run command

Description=unbound server for grundstil

ExecStartPre=-/usr/bin/docker kill grundstil-unbound
ExecStartPre=-/usr/bin/docker rm grundstil-unbound
ExecStartPre=-/usr/bin/docker pull mvance/unbound:latest
ExecStart=/usr/bin/docker run -d --hostname=grundstil-unbound --ip= --name=grundstil-unbound --network=<networkname> mvance/unbound:latest
ExecStop=/usr/bin/docker stop grundstil-unbound


The most important part here is the fixed IP address --ip= For this you need to create a custom docker network with a custom subnet (see above). This IP is where pi-hole must point to for it's upstream DNS resolution. You can chose the IP freely, but note it down for pi-holes usage.

That's it for the server side. If you followed the steps you now have three things running:

  1. An DoH-Server to accept your secure DNS requests
  2. pi-hole to keep you safe from trackers, ads and malware
  3. unbound for upstream DNS requests among other things

Create your DNS stamp

Now that your Server is running, it's time to create your DNS stamp here: Change the Protocol to DNS-over-HTTP/2 and enter the IPv4 of your server (here you might run into problems if the IP of your server changes frequently) and the hostname. The website generates a DNS stamp which you need later on for your clients. Therefore, not it down.


The hardest part is over. Now you can spread joy to all your devices, friends and family.

Activate DoH in Firefox

The easiest and best way to test your setup is in Firefox, since mozilla is testing DoH and enabled it in Firefox. Simply follow these instructions and have your DoH-Server URL ready.

dnscrypt-proxy for all others

dnscrypt-proxy 2 A flexible DNS proxy, with support for modern encrypted DNS protocols such as DNSCrypt v2 and DNS-over-HTTPS.

dnscrypt-proxy is a great piece of software which allows you to secure your DNS request in more way than one. DoH is just one standard currently competing for revolutionizing and securing the biggest flaw in the WWW. If you install dnscrypt-proxy and run ALL your DNS requests through it, you are safe for no matter which technology wins.

Generic installation instructions for many platforms.

One config to rule them all

You can use the same config file for all installs. You should adjust a couple of lines:

  1. Change # server_names = ['scaleway-fr', 'google', 'yandex'] to server_names = ['<yourstampname>'] - remove the # in front of the line
  2. Change # fallback_resolver = '' to fallback_resolver = '' - Also remove any # in front of this line

Add your DNS stamp below [static]. There might already be an entry with # in front, you can add your entry below that one.

     stamp = 'sdns://<yourdnsstamp>'

These changes should be made to any device you use with dnscrypt-proxy.

Install on Synology NAS boxes

Currently, the package is not yet available at, so follow these instructions.
The package installs an app to adjust the config file, you can access this tool via the app menu in the top left when you are accessing your Synology's web interface. The config file is saved and the services restarted when you are done with your edit, giving hints for any errors that might be in your config.

Once you've done this, make sure that the router in your network points to the Synology NAS as DNS server. For testing, you can also have your PC/Mac point at the Synology.

Install on iOS

Install DNSCloak. The configuration should be quite self explanatory. DNSCloak also offers local caching, for even another layer of caching and can run all the time in parallel to a VPN or without. It doesn't take many resources, too.

Apple might throw out DNSCloak if it's becoming to obvious it's being used to block ads on a DNS level. Because neither Google nor Apple allow such apps in their ecosystem. Another way how walled gardens limit your freedom.

Install on Android

This is untested by me, because I left Android for iOS:
Install AdGuard. For installation details, since you cannot download it from the PlayStore, see here.

Because neither Google nor Apple allow such apps in their ecosystem, you have to dowload AdGuard outside of the Google PlayStore ecosystem. This is not a bad thing, you can also install F-Droid for FOSS while you are at it - Contrary to iOS, Android offers paths out of the walled garden.

I couldn't find a detailled configuration manual, but I know there's a dialouge in the app where you can add your DNS stamps. It allows to change to DNS-over-HTTPS and the addition of static DNS entries. You need to find this setting and add your stamp(s).

Potentially the app blokada will support DNScrypt-proxy soon, which will be a better alternative.

Install on Asus routers with Merlin WRT

Use a script provided by "thuantran" instructions.

If you go this route, make sure all the devices in your network use your router as DNS and it doesn't have any other DNS servers active.

Install on OpenWRT

Follow these instructions. If you go this route, make sure all the devices in your network use your router as DNS and it doesn't have any other DNS servers active.

But I don't want to create my own server, can I still be saved?

Depends on your level of trust. There's a list of public resolvers available here: - pick one and use it.
But keep in mind: Do you know who's running these?

If you trust this server, I run the setup above. If you know how to, contact me and I give you my DNS stamp and my DNS URL. It's DNSSEC enabled, it's pi-holed and it's really, really fast.

Comparison with cloudflare's app

In November 2018 cloudflare released a nifty app for iOS and Android. It's a very easy way to secure your DNS on your mobile device. A couple of points to note:

  1. You are using closed-source code in an proprietary app
  2. You are depending on Cloudflare DNS - whereas this solution can use any DNS you desire, you can even be your own DNS without an upstream server
  3. You don't have ad- or tracker-blocking via pi-hole - Your traffic does not reduce
  4. You are directly connecting to cloudflare's servers, which means they know you contact them from your mobile device. With the solution in this article, all clients exits through your unbound server, which is not logging. Therefore it's hard to trace down who is requesting which DNS record

I'm currently using cloudflare as my upstream DNS at the end of the chain DoH-Server -> pi-hole -> unbound - but that might change if something drives to do so. That is the key advantage, freedom of choice. That and ad-blocking

Become active

All this trouble to just make sure you see what you want to see and avoid less desirable content? To keep the noses of your ISPs out of your traffic? This cannot turn into a cat and mouse game! Let's take back the web. Join the EFF. The Electronic Frontier Foundation works hard to protect your freedoms on the Internet. If you are in Germany, you can also join the Chaos Computer Club - A very active and politically accepted community of ethical hackers and computer geeks who campaign to keep your silicon in your control and protect our liberal society in cyber space.

Oh, the irony: tracks me!

I'm completely aware of the irony: If you check NoScript while visiting, you'll see matomo and disqus trying to load a tracker and ads. I also want to know who's coming and I'm also relying on 3rd party services for certain features. Feel free to block these services and know me crying because we cannot discuss and I cannot see where you're coming from :) If your blocker doesn't catch matomo loading, then I encourage you to check the source code of this page. I've hidden matomo quite well.

Next Post

Blog Comments powered by Isso.