In the last couple of evenings I’ve implemented a caching middleware in CoreDNS. It has a only a few knobs and should be simple to use.

Take a simple Corefile and add caching, via the cache directive.

.:1053 {
    proxy . 8.8.4.4:53
    cache 10 miek.nl
    log stdout
    errors stdout
}

Which defines CoreDNS to be a proxy, and only cache responses for the miek.nl zone. This cache only caches for up to 10 seconds. Lets send some queries and looks at the logs:

::1 - [19/Apr/2016:10:41:08 +0000] "MX IN google.com. udp false 4096" NOERROR 148 14.057126ms
::1 - [19/Apr/2016:10:41:13 +0000] "MX IN google.com. udp false 4096" NOERROR 148 11.705738ms
::1 - [19/Apr/2016:10:41:17 +0000] "MX IN miek.nl. udp false 4096" NOERROR 170 33.744613ms
::1 - [19/Apr/2016:10:41:18 +0000] "MX IN miek.nl. udp false 4096" NOERROR 170 377.881µs

The 33.74ms is the upstream query duration for the first miek.nl query, after that it craters to a low value. This does not happen for google.com as that domain is exempt from caching.

In the response the TTL is lowered as well:

;; ANSWER SECTION:
miek.nl.		9	IN	MX	5 alt2.aspmx.l.google.com.
miek.nl.		9	IN	MX	10 aspmx3.googlemail.com.
miek.nl.		9	IN	MX	10 aspmx2.googlemail.com.
miek.nl.		9	IN	MX	5 alt1.aspmx.l.google.com.
miek.nl.		9	IN	MX	1 aspmx.l.google.com.

With caching the last missing piece of SkyDNS has been implemented (only online DNSSEC signing is remaining). I believe (haven’t run CoreDNS in production yet), that CoreDNS has more features (notable multiple domain support) and is more standard compliant than SkyDNS. Having said that, SkyDNS allows its config to be stored in etcd and it can get config from environment variables. CoreDNS can receive a Corefile via stdin though.

The following Corefile should mimic SkyDNS completely:

.:53 {
    etcd skydns.local {
        stubzones
        path /skydns
        endpoint http://localhost:2379
        upstream 8.8.8.8:53 8.8.4.4:53
    }
    prometheus
    cache 60 skydns.local
    loadbalance
    proxy . 8.8.8.8:53 8.8.4.4:53
}