Skip to content

Last updated: 2026-02-13

Knot Resolver DNS over TLS/HTTPS Configuration Guide

This guide provides recommended DNS over TLS (DoT) and DNS over HTTPS (DoH) settings for Knot Resolver (kresd). Knot Resolver is a modern, caching recursive DNS resolver with built-in support for encrypted DNS protocols and DNSSEC validation.

Prerequisites

RHEL/CentOS: Install with dnf install knot-resolver.

Debian/Ubuntu: Install with apt install knot-resolver.

Certificate Setup

Place your certificates in a dedicated directory:

mkdir -p /etc/knot-resolver/ssl
chmod 750 /etc/knot-resolver/ssl
chown knot-resolver:knot-resolver /etc/knot-resolver/ssl

cp server.crt /etc/knot-resolver/ssl/server-cert.pem
cp server.key /etc/knot-resolver/ssl/server-key.pem

chmod 640 /etc/knot-resolver/ssl/*.pem
chown knot-resolver:knot-resolver /etc/knot-resolver/ssl/*.pem

Serving DNS over TLS (DoT)

Configure Knot Resolver to accept DoT connections from clients on port 853.

Add to kresd.conf (or the configuration file at /etc/knot-resolver/kresd.conf):

-- Listen on standard DNS port
net.listen('0.0.0.0', 53, { kind = 'dns' })
net.listen('::', 53, { kind = 'dns' })

-- Listen on DNS over TLS port
net.listen('0.0.0.0', 853, { kind = 'tls' })
net.listen('::', 853, { kind = 'tls' })

-- TLS certificate and key
net.tls('/etc/knot-resolver/ssl/server-cert.pem', '/etc/knot-resolver/ssl/server-key.pem')

Serving DNS over HTTPS (DoH)

Configure Knot Resolver to accept DoH connections:

-- Listen on DNS over HTTPS port
net.listen('0.0.0.0', 443, { kind = 'doh2' })
net.listen('::', 443, { kind = 'doh2' })

-- Uses the same TLS certificates configured with net.tls()

Note: doh2 uses HTTP/2 for DNS over HTTPS. Knot Resolver handles TLS termination natively.

TLS Configuration

Protocol Versions and Cipher Suites

Knot Resolver uses GnuTLS. Configure TLS settings using GnuTLS priority strings:

net.tls_priority('NORMAL:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS1.0:-VERS-DTLS1.2:%SERVER_PRECEDENCE')

For a more restrictive configuration with only strong ciphers:

net.tls_priority('SECURE256:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS1.0:-VERS-DTLS1.2:+AES-256-GCM:+AES-128-GCM:+CHACHA20-POLY1305:%SERVER_PRECEDENCE')

Configuration Explained

Forwarding over TLS (Upstream DoT)

Configure Knot Resolver to forward queries to upstream resolvers over TLS using the policy module:

-- Load the policy module
modules.load('policy')

-- Forward all queries upstream over TLS
policy.add(policy.all(policy.TLS_FORWARD({
    {'1.1.1.1', hostname='cloudflare-dns.com'},
    {'1.0.0.1', hostname='cloudflare-dns.com'},
    {'8.8.8.8', hostname='dns.google'},
    {'8.8.4.4', hostname='dns.google'},
})))

The hostname parameter enables certificate verification against the upstream server's TLS certificate.

TLS Client Authentication (Upstream)

When forwarding to an upstream resolver that requires client certificates:

net.tls_client('/etc/knot-resolver/ssl/client-cert.pem', '/etc/knot-resolver/ssl/client-key.pem')

DNSSEC Validation

Knot Resolver validates DNSSEC by default. Ensure it remains enabled:

-- DNSSEC trust anchors (auto-managed)
trust_anchors.add_file('/var/lib/knot-resolver/root.keys', true)

Complete Configuration

-- Network listeners
net.listen('0.0.0.0', 53, { kind = 'dns' })
net.listen('::', 53, { kind = 'dns' })
net.listen('0.0.0.0', 853, { kind = 'tls' })
net.listen('::', 853, { kind = 'tls' })
net.listen('0.0.0.0', 443, { kind = 'doh2' })
net.listen('::', 443, { kind = 'doh2' })

-- TLS certificate
net.tls('/etc/knot-resolver/ssl/server-cert.pem', '/etc/knot-resolver/ssl/server-key.pem')

-- TLS protocol settings (GnuTLS priority string)
net.tls_priority('NORMAL:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS1.0:-VERS-DTLS1.2:%SERVER_PRECEDENCE')

-- Modules
modules.load('policy')

-- Forward all queries upstream over TLS
policy.add(policy.all(policy.TLS_FORWARD({
    {'1.1.1.1', hostname='cloudflare-dns.com'},
    {'1.0.0.1', hostname='cloudflare-dns.com'},
    {'8.8.8.8', hostname='dns.google'},
    {'8.8.4.4', hostname='dns.google'},
})))

-- DNSSEC trust anchors
trust_anchors.add_file('/var/lib/knot-resolver/root.keys', true)

-- Cache size (100 MB)
cache.size = 100 * MB

Client Configuration

systemd-resolved

Configure systemd-resolved to use your Knot Resolver over DoT:

[Resolve]
DNS=192.168.1.1
DNSOverTLS=yes

Browser DoH

Modern browsers can use DoH directly. Configure the custom DoH endpoint:

https://dns.example.com/dns-query

Verification

Check the configuration for errors:

kresctl validate

Test the DoT listener:

openssl s_client -connect dns.example.com:853

Test DNS resolution over TLS using kdig:

kdig @dns.example.com +tls example.com A

Test DNS resolution over HTTPS:

curl -s -H 'accept: application/dns-json' 'https://dns.example.com/dns-query?name=example.com&type=A'

Check Knot Resolver logs:

journalctl -u kresd@1 | grep -i tls