Skip to content

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: 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

  • NORMAL / SECURE256 -- GnuTLS preset cipher suites. SECURE256 only 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).


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 →