Last updated: 2026-05-15
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
- Knot Resolver 5.5 or later
- GnuTLS 3.6 or later
- SSL certificates (for serving DoT/DoH to clients)
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:
doh2uses 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
- NORMAL / SECURE256 -- GnuTLS preset cipher suites.
SECURE256only allows 256-bit or higher security level ciphers. - -VERS-TLS1.0 / -VERS-TLS1.1 -- Disables TLS 1.0 and 1.1, allowing only TLS 1.2 and TLS 1.3.
- %SERVER_PRECEDENCE -- The server's cipher preference order takes priority over the client's.
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')
See RFC 8446 ยง4.3.2 for the TLS Certificate Request specification, and Wikipedia: Mutual authentication for a general overview.
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
Security Notes
Knot Resolver uses GnuTLS for TLS, which is an independent implementation not based on OpenSSL:
- POODLE (CVE-2014-3566, 2014): SSL 3.0 disabled since GnuTLS 3.3.8 (October 2014). The recommended configuration explicitly excludes older protocol versions.
- BEAST (CVE-2011-3389, 2011): Mitigated by recommending TLS 1.2 as the minimum; AEAD-only ciphers eliminate the CBC padding oracle.
- FREAK (CVE-2015-0204, 2015): EXPORT-grade ciphers removed from GnuTLS 3.4.1 (April 2015).
- LOGJAM (CVE-2015-4000, 2015): Short-key DHE is excluded; only ECDHE key exchange is recommended.
- Sweet32 (CVE-2016-2183, 2016): 3DES is excluded from the recommended cipher configuration.
- TLS_FALLBACK_SCSV: Supported since GnuTLS 3.2.12 (March 2014).
- CVE-2014-0092 (March 2014): Certificate validation bypass in GnuTLS, fixed in GnuTLS 3.1.22 / 3.2.12.
The following are not addressable through TLS configuration alone:
- Heartbleed (CVE-2014-0160, 2014): Not applicable. GnuTLS is an independent TLS implementation not based on OpenSSL and was never affected by Heartbleed.
- BREACH (CVE-2013-3587, 2013): Not applicable. BREACH targets HTTP-level response compression; DNS-over-TLS and DNS-over-HTTPS do not involve compressible HTTP responses in standard usage.
- DROWN (CVE-2016-0800, 2016): Not applicable. GnuTLS does not support SSLv2.
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
Confirm the DoT/DoH certificate and chain externally with the Mr.DNS SSL/TLS Certificate Check (port 853 for DoT, 443 for DoH).