Cadey is coffee
<Cadey> Hello! Thank you for visiting my website. You seem to be using an ad-blocker. I understand why you do this, but I'd really appreciate if it you would turn it off for my website. These ads help pay for running the website and are done by Ethical Ads. I do not receive detailed analytics on the ads and from what I understand neither does Ethical Ads. If you don't want to disable your ad blocker, please consider donating on Patreon or sending some extra cash to xeiaso.eth or 0xeA223Ca8968Ca59e0Bc79Ba331c2F6f636A3fB82. It helps fund the website's hosting bills and pay for the expensive technical editor that I use for my longer articles. Thanks and be well!

Site to Site WireGuard: Part 2 - DNS

Read time in minutes: 14

This is the second in my Site to Site WireGuard VPN series. You can read the other articles here:

What is DNS and How Does it Work?

DNS, or the Domain Name Service is one of the core protocols of the internet. Its main job is to turn names like into IP addresses for the lower layers of the networking stack to communicate. Semantically, clients ask questions to the DNS server (such as "what is the IP address for") and get answers back ("the IP address for is"). This is a very simple protocol that predates the internet, and is tied into the core of how nearly every single program accesses the internet. DNS allows users to not have to memorize IP addresses of services in order to connect to and use them. If anything on the internet is truly considered "infrastructure", it is DNS.

A common tool in Linux and macOS to query DNS is dig. You can install it in Ubuntu with the following command:

$ sudo apt install -y dnsutils

A side note for Alpine Linux users: for some reason the dig tool is packaged in bind-tools there. You can install it like this:

$ sudo apk add bind-tools

As an example of it in action, let's look up with the dig tool (edited for clarity):

$ dig
;; Got answer:
;                    IN      A

;; ANSWER SECTION:             299     IN      A


A DNS answer or record has several parts to it:

  • The name (with a terminating .)
  • The time-to-live, which tells DNS caches how long they can wait before looking up the domain again
  • The kind of address being served (DNS supports multiple network kinds, though only INternet records are used nowadays)
  • The kind of record this is
  • Any additional data for that record

Interpreting the question and answer from above: this means that the client asked for the IPv4 address (DNS calls this an A record) for and got back as an answer from the dns server at

DNS supports many other kinds of records, such as PTR or "reverse" records that map an IP address back to a name (again, edited for clarity):

$ dig -x
;; Got answer:
;    IN      PTR

;; ANSWER SECTION: 20787 IN    PTR 20787 IN    PTR


As seen above, DNS supports having multiple answers to a single name. This is useful when doing load balancing between services (so-called "round robin" load balancing over DNS works like this) as well as redundancy in general.

Why Should I Create a Custom DNS Server?

There are two main benefits to creating a custom DNS server like this: ad blocking in DNS and custom DNS routes. The main benefit is having seamless AdBlock DNS, kind of like a Pi-hole built into your VPN for free. The benefits of the AdBlock DNS cannot be understated. It literally makes it impossible to see ads for a large number of websites, without triggering the adblock protection scripts news sites like to use. This will be covered in more detail below. Custom DNS routes sound like they would be overkill for keeping things private, but people can't easily get information on names that literally only exist in your domain.

However, there are reasons why you would NOT want to create a custom DNS server. By creating a custom DNS server, you effectively put yourself in charge of an internet infrastrcture component that is usually handled by people who are dedicated to keeping it working 24/7. You may not be able to provide the same uptime guarantees as your current DNS provider. You are not CloudFlare, Comcast or Google. It's perfectly okay to not want to go through with this.

I think the benefits are worth the risks though.

How Do I Create a Custom DNS Server?

There are many DNS servers out there, each with their benefits and shortcomings. In order to make this tutorial simpler, I'm going to be using a self-created DNS server named dnsd. This server is extremely simple and reloads its zone files every minute over HTTP, to make updating records easier. There are going to be a few steps to setting this up:

  • Creating a DNS zonefile
  • Hosting the zonefile over HTTP/HTTPS
  • Adding ad-blocking DNS rules
  • Installing dnsd with Docker
  • Using the DNS server with the iOS WireGuard app

Creating a DNS Zonefile

dnsd requires an RFC 1035 compliant DNS zone file. In short, it's a file that looks something like this:

; anything after a semicolon is a comment

;; The default time for this DNS record to live in caches
$TTL 60

;; If a domain `foo` is not ended with `.`, assume it's `foo.pele.`
$ORIGIN pele.

; servers

;; Map the name oho.pele. to
oho.pele. IN A

;; Map the IP address to the name oho.pele. IN PTR oho.pele.

; clients

;; Map the name sitelen-sona.pele. to
sitelen-sona.pele. IN A

;; Map the IP address to sitelen-sona.pele. IN PTR sitelen-sona.pele.

;;; How to make Custom DNS Locations:

;; Map the name prometheus.pele. to the name oho.pele., which indirectly maps it to
prometheus.pele. IN CNAME oho.pele.

;; Map the name grafana.pele. to the name oho.pele., which indirectly maps it to
grafana.pele. IN CNAME oho.pele.

Save this file somewhere and get it ready to host somewhere.

If you would like to have some of this generated for you, fill out with the following information:

  • Base data
  • DNS Server
    • Primary host name: ns.pele
    • Primary IP-Addr:
    • Primary comment: The volcano
    • Clear all other boxes in this section
  • Mail Server
    • Clear all boxes in this section
  • Click Create
  • Save this as

Note that this will include a Start of Authority or SOA record, which is not strictly required, but may be nice to include too. If you want to include this in your manually made zonefile, it should look something like this:

@       IN      SOA     oho.pele.       some@email.address. (
                        2019040602      ; serial number YYYYMMDDNN
                        28800           ; Refresh
                        7200            ; Retry
                        864000          ; Expire
                        60              ; Min TTL

; Also not required but some weird clients may want this.
@       IN      NS      oho.pele.

Hosting the Zonefile Over HTTP/HTTPS

This is the "draw the rest of the owl" part of this article, worst case something like GitHub Gists works. Once you have the URL of your zonefiles and a reliable way to update them, you can move to the next step: installing dnsd.

Adding Ad-Blocking DNS Rules

A friend of mine adapted her dnsmasq scripts to generate RFC 1035 DNS zonefiles. In order to generate do the following:

$ cd ~/tmp
$ git clone faithanalog-x
$ cd faithanalog-x/dns-adblock
$ sh ./

This should produce in the current working directory. Put this file in the same place you put your custom zone.

If you are unable to run this script for whatever reason, I update my file weekly (please download this file instead of configuring your copy of dnsd to use this URL).

Installing dnsd with Docker

The easy way:

$ export DNSD_VERSION=v1.0.3
$ docker run --name dnsd -p 53:53/udp -dit --restart always xena/dnsd:$DNSD_VERSION \
  dnsd -zone-url https://domain.hostname.tld/path/to/ \
       -zone-url https://domain.hostname.tld/path/to/ \

This will create a new container named dnsd running the Docker Image xena/dnsd:1.0.2-6-g1a2bc63 (the docker image is created by this script and this dockerfile), exposing the DNS server on the host's UDP port 53. To test it:

$ dig @ oho.pele
;oho.pele.                      IN      A

oho.pele.               60      IN      A


$ dig @ -x
;                IN      PTR

;; ANSWER SECTION: 60      IN      PTR     oho.pele.


Using With the iOS WireGuard App

In order to configure iOS WireGuard clients to use this DNS server, open the WireGuard app and tap the name of the configuration we created in the last post. Hit "Edit" in the upper right hand corner and select the "DNS Servers" box. Put in it and hit "Save". Be sure to confirm the VPN is active, then open LibTerm and enter in the following:

$ dig oho.pele

And make sure it works.

Once this is done, you should be good to go! Updates to the zone files will be picked up by dnsd within a minute or two of the files being changed on the remote servers. Please be sure the server you are using tags the files appropriately with the ETag header, as dnsd uses that to determine if the zonefile has changed or not.

Please give me feedback on my approach to this. I also have a Patreon and a Ko-Fi in case you want to support this series. I hope this is useful to you all in some way. Stay tuned for the future parts of this series as I build up the network infrastructure from scratch. If you would like to give feedback on the posts as they are written, please watch this page for new pull requests.

Be well.

This article was posted on M04 07 2019. Facts and circumstances may have changed since publication. Please contact me before jumping to conclusions if something seems wrong or unclear.

Series: site-to-site-wireguard

This post was not WebMentioned yet. You could be the first!

The art for Mara was drawn by Selicre.

The art for Cadey was drawn by ArtZora Studios.

Some of the art for Aoi was drawn by @Sandra_Thomas01.