This post talks you through getting and setting up CoreDNS with a small zone file that it will serve. CoreDNS is a nameserver that is very flexible because it can chain different kinds of middleware. From the README:

CoreDNS aims to be a fast and flexible DNS server. The keyword here is flexible, with CoreDNS you are able to do what you want with your DNS data. And if not: write a middleware!

This post does not detail on how to use CoreDNS as a replacement for SkyDNS.

It assumes that you have installed a newish version of Go (1.5+).

Go get CoreDNS: go get github.com/miekg/coredns and compile and install it:

cd $GOPATH/src/github.com/miekg/coredns
go install

coredns -version should show something like: CoreDNS (untracked dev build).

Now, we are going to work with a little zonefile used for my atoom.net (atom in English) domain, just drop the contents of this in ~/atoom.net

$TTL    30M
$ORIGIN atoom.net.
@  IN      SOA     linode.atoom.net. miek.miek.nl. (
                 1282630061  ; Serial
                  4H         ; Refresh
                  1H         ; Retry
                  7D         ; Expire
                  4H )       ; Negative Cache TTL
   IN      NS      linode
   IN      NS      ns-ext.nlnetlabs.nl.
   IN      A       139.162.196.78
   IN      AAAA    2a01:7e00::f03c:91ff:fef1:6735

   IN      HINFO   "Please stop asking for ANY" "See draft-ietf-dnsop-refuse-any"

linode  IN      A       176.58.119.54
        IN      AAAA    2a01:7e00::f03c:91ff:feae:e74c
www     IN  	CNAME   linode

x64     IN      A       139.162.196.78
        IN      AAAA    2a01:7e00::f03c:91ff:fef1:6735

Create a Corefile with the following contents. We assume this file is also placed in my homedir:

atoom.net:53 {
    file /home/miek/atoom.net
    errors stdout
    log stdout
}

And start coredns: sudo coredns -log stdout -conf ~/Corefile, query it:

% dig @localhost atoom.net A +short
139.162.196.78

Pretty boring, let’s add DNSSEC, because that generates the most interesting outages.

We create a keypair and use it for signing:

% dnssec-keygen -r /dev/urandom \
    -a ECDSAP256SHA256 atoom.net
Generating key pair.
Katoom.net.+013+21905

Amend our Corefile and add the dnssec directive, then restart:

atoom.net:53 {
    file /home/miek/atoom.net
    dnssec {
        key file Katoom.net.+013+21905
    }
    errors stdout
    log stdout
}

Using dig again, we see an RRSIG popping up:

dig @localhost a atoom.net +dnssec +short
139.162.196.78
A 13 2 3600 20160505102551 20160427072551 21905 atoom.net. Xdebr6v7rsV+QO9...xnxaO6QgjVww...

Maybe you know about those pesky ANY queries, that generate large responses?

Testing this I see CoreDNS actually only includes the SOA record when responding to an ANY query. No sure if this is a bug or feature…

Let’s rewrite ANY queries to the more harmless HINFO type:

atoom.net:53 {
    file /home/miek/atoom.net
    dnssec {
        key file Katoom.net.+013+21905
    }
    rewrite ANY HINFO
    errors stdout
    log stdout
}

And checking:

% dig @localhost ANY atoom.net +dnssec +short
"Please stop asking for ANY" "See draft-ietf-dnsop-refuse-any"
HINFO 13 2 3600 20160505104728 20160427074728 21905 atoom.net. 5exk2LXO...OxS0LN7Hqbw==

HINFO in all its glory.

Maybe just using it as an authoritative server isn’t enough? Let’s make CoreDNS a proxy for anything that isn’t atoom.net.

We need to push all queries through our stanza, so instead of listing atoom.net we use the root zone “.”. We are then forced to specify atoom.net for the bits that handle that zone. We end up with:

.:53 {
    file /home/miek/atoom.net atoom.net
    dnssec atoom.net {
        key file Katoom.net.+013+21905
    }
    proxy . 8.8.8.8:53 [2001:4860:4860::8888]:53
    errors stdout
    rewrite ANY HINFO
    log stdout
}

This routes atoom.net to the file backend and everything else gets forwarded to Google. Now this forwarding is slow, so you might want to add a caching layer as well.

.:53 {
    file /home/miek/atoom.net atoom.net
    dnssec atoom.net {
        key file Katoom.net.+013+21905
    }
    proxy . 8.8.8.8:53 [2001:4860:4860::8888]:53
    cache
    errors stdout
    rewrite ANY HINFO
    log stdout
}

This will cache queries for atoom.net as well, which should not be really needed. There is currently no syntax that will allow you to say: “cache everything, except these zones”.