What is a Domain Name System?

A Domain Name System (DNS) acts like the the phone book of the internet. When we enter a URL in our browser, it sends the URL to a DNS server to look up the actual IP address. Many times a DNS server will not know the IP address of the URL and it will have to forward it on to additional DNS servers. The next server to ask is determined by reading the URL from right to left. Each section of the URL is referred to as a zone and the remainder of the URL is forwarded on to the next zone.

DNS works by making a query to the DNS servers. This query contains a header and a question which is used to determine what type of information is being asked for. The DNS servers will send a response that contains the original request and a resource record which includes the route to get to the final IP. This record also has one of many types which generally break down into a redirect to another server or the type of the final hosting server.

Why setup your own DNS?

There are many DNS servers available already. Your internet service provider is probably already hosting a DNS server that your network uses by default. There are many large companies that also offer a DNS server such as Google or Cloudfare. Why go through the trouble of hosting your own DNS server?

There are many reasons that someone might want to host their own DNS server but some of the more common ones tend to be

  • Assign URLs to local devices. Homes today will typically have many devices on their network. By running a local DNS server, they can have human readable URLs assigned to them which makes them easier to remember or identify.
  • Faster lookup times. A DNS server can cache common queries and make them faster to look up the next time around.
  • Filter allowed websites. DNS servers will typically have the ability to create a block list so that certain webpages cannot be reached.

There are ways to achieve this on an individual system but by creating a DNS server for the entire network, any device connected to the network will be able to resolve URLs without needing to be configured.

What is CoreDNS

CoreDNS is a popular DNS server that is written in Go. It works by being a very simple framework that can be configured to call plugins depending on the desired functionality. Each of these plugins will run a server that listens for queries and performs an action or passes the query on to the next plugin. Plugins currently have one of four ways of handling a request

  • Do nothing and pass it to the next plugin
  • Process the query and return a response
  • Process the query, add a hint, and then pass it to the next plugin
  • Process the request but decide to forward it on halfway through. fallthrough

A small number of plugins don’t handle queries but provide other functionality

Configuring CoreDNS

Configuration for CoreDNS is done using a Corefile. Corefiles support environment variable substitution and snippets of reusable sections. The basic syntax of a Corefile looks like the following.

1
2
3
4
5
<url>:<port> {
  <plugin> {
    <plugin configuration>
  }
}

. can be used for the URL and will handle all queries. For this initial setup the DNS server will forward requests for select URLs to a server on the networking, otherwise it will use Google’s DNS to handle any other requests. This configuration uses a hosts plugin that allows URLs to be created similarly to how they are created in an /etc/hosts file. Changing this part to hosts . /etc/hosts will actually allow the host system’s host file to be used.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
. {
    forward . 8.8.8.8 9.9.9.9
    log
    errors
}

example.com {
    hosts {
    	192.168.1.69	example.com
    }
    log
    errors
}

Running CoreDNS is easy with a docker compose setup. The default docker setup doesn’t require much configuration other than passing the Corefile on the host system to a specific path within the container.

1
2
3
4
5
6
7
8
9
version: "3.9"
services:
  coredns:
    container_name: coredns
    image: "coredns/coredns:latest"
    restart: unless-stopped
    network_mode: "host"
    volumes:
      - ${PWD}/Corefile:/Corefile

Sharing with the entire network

Running CoreDNS on one system will allow it to look up local devices but the whole point of a dedicated DNS server is to allow the whole network to use it. This is done by entering your router’s configuration and assigning the IP address of the device running CoreDNS to the DNS server section. The location of this section can very from router to router so it will take some digging around to find the section for your specific model.

Checking configuration

You should now have a DNS server up and running for your local network. It make take some time for the changes to propagate to all of the devices on your network. Once has happened, you can run a dig command to see that a URL from the configuration resolves to the correct IP address.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ dig example.com

; <<>> DiG 9.16.1-Ubuntu <<>> example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34438
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 1336a3a35d8ea2ee (echoed)
;; QUESTION SECTION:
;example.com.			IN	A

;; ANSWER SECTION:
example.com.		3600	IN	A	192.168.1.69

;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Fri Feb 18 04:43:17 UTC 2022
;; MSG SIZE  rcvd: 79