← DNS SoftwareDNS Software / Recursive Resolver

Knot Resolver

A modern recursive resolver with a Lua scripting engine — supporting DoH, DoT, DNSSEC validation, and policy scripting for ISPs and privacy-focused DNS services.

Overview

Scriptable Recursive Resolver

Knot Resolver (kresd) is a recursive resolver developed by CZ.NIC — distinct from Knot DNS (the authoritative server). It is built around a modular architecture with Lua scripting, allowing operators to implement custom resolution policies, blocking rules, logging, and protocol handling without recompiling.

Knot Resolver supports DNS-over-HTTPS, DNS-over-TLS, and DNS-over-QUIC (experimental) for both inbound client connections and upstream forwarders. It performs full DNSSEC validation and supports aggressive NSEC caching for faster negative responses. CZ.NIC operates a public DNS service (1.12.12.12, Cloudflare for Families-style) using Knot Resolver.

  • Lua module system — custom blocking, rewriting, and policy logic
  • DNS-over-HTTPS (DoH), DNS-over-TLS (DoT) inbound and outbound
  • DNS-over-QUIC (DoQ) experimental support
  • Full DNSSEC validation with aggressive NSEC caching
  • RPZ (Response Policy Zones) support via Lua module
  • Prometheus metrics endpoint for monitoring
  • Multi-process scaling: run multiple kresd instances sharing a cache
When to Choose Knot Resolver
  • You need DoH or DoT for client-facing resolver connections
  • You want Lua scripting for custom resolution policies
  • You are building an ISP or public resolver service
  • You need aggressive NSEC caching for fast NXDOMAIN responses
CZ.NIC
Built by .cz TLD operator
Lua
Scriptable module system
Configuration

Key Configuration Examples

kresd.conf — basic resolver

-- /etc/knot-resolver/kresd.conf (Lua) -- Listen on all interfaces net.listen('0.0.0.0', 53, { kind = 'dns' }) net.listen('::', 53, { kind = 'dns' }) -- Enable DNSSEC validation trust_anchors.add_file('/etc/knot-resolver/root.keys') -- Cache size (MB) cache.size = 100 * MB -- Load useful modules modules = { 'hints > iterate', -- /etc/hosts + hints 'stats', -- query statistics 'predict', -- prefetch popular records }

DNS-over-HTTPS and DoT

-- Listen for DoT clients (port 853) net.listen('0.0.0.0', 853, { kind = 'tls', tls_cert = '/etc/ssl/certs/kresd.crt', tls_key = '/etc/ssl/private/kresd.key', }) -- Listen for DoH clients (port 443) net.listen('0.0.0.0', 443, { kind = 'doh2', tls_cert = '/etc/ssl/certs/kresd.crt', tls_key = '/etc/ssl/private/kresd.key', }) -- Forward 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'}, }) ))

Lua policy: blocking

-- Block domains using Lua policy -- Block a specific domain policy.add(policy.suffix( policy.DENY, { todname('badsite.com') } )) -- Block by RPZ zone file policy.add(policy.rpz( policy.DENY, '/etc/knot-resolver/blocklist.rpz' )) -- Block ads for specific clients policy.add(policy.client_subnet( { '192.168.1.0/24' }, policy.rpz(policy.DENY, '/etc/knot-resolver/adblock.rpz') ))

Runtime management

# Knot Resolver is configured via Lua # Changes require reload or runtime eval # Check status systemctl status kresd@1 # Reload config systemctl reload kresd@1 # Run multiple instances (multi-core) systemctl enable --now kresd@1 systemctl enable --now kresd@2 systemctl enable --now kresd@3 # Interactive console (if enabled) socat - /run/knot-resolver/control/1 # Then type Lua commands: # stats.list() # cache.count()