Skip to content

Last updated: 2026-06-25

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 (the configuration below uses the 5.x Lua format; Knot Resolver 6.x is the current stable line and uses a declarative YAML configuration)
  • GnuTLS 3.6 or later
  • SSL certificates (for serving DoT/DoH to clients)

RHEL: 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. In Knot Resolver 5.x the TLS policy is fixed by the daemon (TLS 1.2 and higher with strong GnuTLS defaults) and is not configurable from kresd.conf; the 5.x TLS server bindings expose only certificate, session-ticket, and EDNS padding settings (net.tls, net.tls_sticket_secret, net.tls_padding). There is no net.tls_priority() function in the 5.x configuration.

The current Knot Resolver 6.x line exposes TLS settings declaratively via its YAML configuration; see the 6.x documentation if you need to adjust TLS parameters.

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
-- (in 5.x the TLS protocol/cipher policy is fixed by the daemon and not configurable here)
net.tls('/etc/knot-resolver/ssl/server-cert.pem', '/etc/knot-resolver/ssl/server-key.pem')

-- 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. Knot Resolver 5.x uses a Lua configuration, so validate it by having kresd load the config in non-interactive mode against a scratch run directory; it exits with an error if the config fails to load:

kresd -n -c /etc/knot-resolver/kresd.conf /tmp/kresd-check

Version note: Knot Resolver 6.x replaces the Lua configuration with a declarative YAML config, validated with kresctl validate. The kresctl tool does not apply to the 5.x Lua configuration shown in this guide.

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).


Related Guides

View all DNS guides →

Configured TLS? Now Monitor It.

Generator Labs alerts you before certificates expire, get revoked, or fail chain validation, across HTTPS, SMTPS, IMAPS, LDAPS, and more.

Certificate Monitoring →