Setting up DNS over TLS


You probably already heard of DNS over TLS already. I thought it would be interesting to extend the CoreDNS forwarder example with TLS support.

You will either need to install/download kdig and cfssl, or build a container (here’s my example Dockerfile) Alternatively, install kdig and cfssl locally.

Test with public DNS servers

Before deploying my own, a quick test with public DNS servers. You can query public DNS servers such as Cloudflare or Google DNS

kdig -d @ +tls-ca +tls-hostname=one.one.one.one wikipedia.org
kdig -d @ +tls-ca +tls-hostname=dns.google.com wikipedia.org

Generate TLS certificates

We’ll need some certificates in order to serve traffic over TLS (a bad joke using duh/DoH is very tempting). For this example, I’ll use self signed certificates (cfssl sample config) Root CA

pushd /cfssl && \
  cfssl gencert -initca ca.json | cfssljson -bare ca && \
  cfssl gencert -initca intermediate-ca.json | cfssljson -bare intermediate_ca  && \
  cfssl sign -ca ca.pem -ca-key ca-key.pem -config cfssl.json -profile intermediate_ca intermediate_ca.csr | cfssljson -bare intermediate_ca  && \
  cfssl gencert -ca intermediate_ca.pem -ca-key intermediate_ca-key.pem -config cfssl.json -profile=server dns-host.json | cfssljson -bare dns-server && \

Inspect the certificate

openssl x509 -text -in cfssl/dns-server.pem | more

Deploy to Kubernetes

For the next part, I’ll use a Kubernetes cluster, but this could have been done with docker, or by just downloading the coredns binary.

Create a secret

pushd cfssl && \
  kubectl create secret generic coredns-tls \
  --from-file=dns-server.pem \
  --from-file=dns-server-key.pem \
  --from-file=intermediate_ca.pem && \

Deploy CoreDNS with TLS

helm repo add coredns https://coredns.github.io/helm
helm upgrade -i example coredns/coredns --version 1.14.0 -f values.yaml

In the value file, we’re telling CoreDNS to serve traffic over TLS and configuring the tls plugin with the certificates we generated

  - zone: tls://.
  - name: tls
    parameters: /tls/dns-server.pem /tls/dns-server-key.pem /tls/intermediate_ca.pem

Resolve DNS queries over TLS

kubectl run -it --rm --restart=Never --image=docker.io/alpine:3.12 sandbox -- ash -c "apk add knot-utils;cat"

From another tab let’s query our newly deployed DNS server for wikipedia.org

kubectl cp ./cfssl/intermediate_ca.pem sandbox:/
kubectl exec sandbox -- kdig -d @example-coredns.default.svc.cluster.local -p 5553 +tls-ca=/intermediate_ca.pem +tls-hostname=dns.example.com wikipedia.org