Skip to content

Last updated: 2026-02-11

PowerDNS DNSSEC & DNS over TLS Configuration Guide

This guide provides recommended DNSSEC and DNS over TLS (DoT) settings for PowerDNS Authoritative Server and PowerDNS Recursor. PowerDNS provides built-in DNSSEC support with straightforward key management through the pdnsutil command-line tool. For DoT, dnsdist (covered in a separate guide) serves as the TLS frontend for the Authoritative Server, while the Recursor supports outgoing DoT natively.

Prerequisites

Authoritative Server DNSSEC

Securing a Zone

Enable DNSSEC for an existing zone with a single command:

pdnsutil secure-zone example.com

This generates a KSK and ZSK using the default algorithm (ECDSAP256SHA256) and activates them immediately.

Algorithm Selection

Specify the algorithm when securing a zone:

pdnsutil secure-zone example.com ecdsap256sha256
Algorithm Recommendation
rsasha256 Acceptable (2048-bit minimum)
rsasha512 Acceptable
ecdsap256sha256 Recommended
ecdsap384sha384 Acceptable
ed25519 Good (limited resolver support)

Rectifying the Zone

After securing a zone, rectify it to generate NSEC/NSEC3 records and calculate ordername hashes:

pdnsutil rectify-zone example.com

Key Management

List all keys for a zone:

pdnsutil show-zone example.com

Add a new key:

# Add a new ZSK
pdnsutil add-zone-key example.com zsk active ecdsap256sha256

# Add a new KSK
pdnsutil add-zone-key example.com ksk active ecdsap256sha256

Rotate a ZSK:

# Add a new ZSK (active)
pdnsutil add-zone-key example.com zsk active ecdsap256sha256

# Deactivate the old ZSK (by key ID)
pdnsutil deactivate-zone-key example.com OLD_KEY_ID

# After TTL expiry, remove the old key
pdnsutil remove-zone-key example.com OLD_KEY_ID

DS Record Publication

Extract the DS record for publication at the parent zone:

pdnsutil show-zone example.com

This shows DS records in multiple digest formats. Publish the SHA-256 digest (type 2) with your registrar:

pdnsutil export-zone-ds example.com

You can also extract specific formats:

pdnsutil hash-zone-record example.com example.com

NSEC vs NSEC3

By default, PowerDNS uses NSEC. To switch to NSEC3 for authenticated denial of existence without zone enumeration:

pdnsutil set-nsec3 example.com '1 0 0 -'
pdnsutil rectify-zone example.com

The parameters '1 0 0 -' mean:

To revert to NSEC:

pdnsutil unset-nsec3 example.com
pdnsutil rectify-zone example.com

Authoritative Server Configuration

Enable DNSSEC in pdns.conf:

# /etc/pdns/pdns.conf

# Backend (example: PostgreSQL)
launch=gpgsql
gpgsql-host=127.0.0.1
gpgsql-dbname=pdns
gpgsql-user=pdns
gpgsql-password=secret
gpgsql-dnssec=yes

# Enable DNSSEC
# (Key storage is handled by the backend)

# Bind to all interfaces
local-address=0.0.0.0, ::
local-port=53

# Authoritative only (recursion is disabled by default in 4.5+)

# AXFR restrictions
disable-axfr=yes
allow-axfr-ips=192.0.2.1/32,198.51.100.1/32

# Logging
loglevel=4
log-dns-queries=no

Recursor DNSSEC Validation

PowerDNS Recursor validates DNSSEC-signed responses automatically when configured:

# /etc/pdns-recursor/recursor.conf

# Enable DNSSEC validation
dnssec=validate

# Log DNSSEC validation failures
dnssec-log-bogus=yes

# Local address
local-address=127.0.0.1, ::1

# Allow queries from local networks
allow-from=127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, ::1/128, fe80::/10

# Forward to authoritative servers (optional)
# forward-zones=example.com=192.0.2.1

# Root hints
hint-file=/usr/share/dns/root.hints   # RHEL: /var/named/named.ca; or omit (built-in hints used by default)

DNSSEC validation modes:

Mode Description
off No DNSSEC processing
process-no-validate Set DO bit, pass records through, no validation
process Set DO bit, set AD flag where applicable
log-fail Validate, log failures, but serve bogus answers
validate Full validation, return SERVFAIL for bogus answers

Complete Configuration

Authoritative Server

# /etc/pdns/pdns.conf

# Backend
launch=gpgsql
gpgsql-host=127.0.0.1
gpgsql-dbname=pdns
gpgsql-user=pdns
gpgsql-password=secret
gpgsql-dnssec=yes

# Network
local-address=0.0.0.0, ::
local-port=53

# Security (recursion is disabled by default in 4.5+)
disable-axfr=yes
allow-axfr-ips=192.0.2.1/32,198.51.100.1/32
version-string=anonymous

# Performance
cache-ttl=60
negquery-cache-ttl=60
query-cache-ttl=20       # Renamed to zone-cache-refresh-interval in Auth 4.8+

# Logging
loglevel=4
log-dns-queries=no

After starting the server, secure your zones:

pdnsutil secure-zone example.com
pdnsutil set-nsec3 example.com '1 0 0 -'
pdnsutil rectify-zone example.com
pdnsutil export-zone-ds example.com

Validating Recursor

# /etc/pdns-recursor/recursor.conf

# Network
local-address=127.0.0.1, ::1
local-port=53

# Access control
allow-from=127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, ::1/128, fe80::/10

# DNSSEC
dnssec=validate
dnssec-log-bogus=yes

# Root hints
hint-file=/usr/share/dns/root.hints   # RHEL: /var/named/named.ca; or omit (built-in hints used by default)

# Performance
threads=4
max-cache-entries=1000000
max-packetcache-entries=500000

# Security
version-string=anonymous

DNS over TLS (DoT)

Authoritative Server with dnsdist

PowerDNS Authoritative Server does not natively support DNS over TLS. Use dnsdist as a TLS-terminating frontend (see the dnsdist guide for full configuration):

-- /etc/dnsdist/dnsdist.conf

-- DNS over TLS frontend
addTLSLocal('0.0.0.0:853', '/etc/dnsdist/ssl/fullchain.pem', '/etc/dnsdist/ssl/privkey.pem', {
  minTLSVersion='tls1.2'
})

-- Forward to local PowerDNS Authoritative Server
newServer({address='127.0.0.1:53', name='pdns-auth'})

Recursor Outgoing DoT

PowerDNS Recursor 4.7+ supports forwarding queries to upstream resolvers over TLS. Specify the TLS port and server name for certificate verification:

# /etc/pdns-recursor/recursor.conf

# Forward to upstream over DoT
forward-zones-recurse=.=9.9.9.9:853#dns.quad9.net;149.112.112.112:853#dns.quad9.net

The #hostname suffix after the address enables TLS and verifies the server certificate against the specified hostname.

Version note: The #hostname syntax for outgoing DoT requires PowerDNS Recursor 4.6+. On Debian 11 (Recursor 4.5), this syntax is not available and outgoing DoT is not supported natively.

Recursor DoT Configuration

# /etc/pdns-recursor/recursor.conf

# Network
local-address=127.0.0.1, ::1
local-port=53

# Access control
allow-from=127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, ::1/128, fe80::/10

# DNSSEC
dnssec=validate
dnssec-log-bogus=yes

# Forward all queries over DoT
forward-zones-recurse=.=9.9.9.9:853#dns.quad9.net;149.112.112.112:853#dns.quad9.net;1.1.1.1:853#cloudflare-dns.com;1.0.0.1:853#cloudflare-dns.com

# Performance
threads=4
max-cache-entries=1000000
max-packetcache-entries=500000

# Security
version-string=anonymous

Verification

Check that a zone is properly signed:

pdnsutil check-zone example.com

Verify DNSSEC keys and DS records:

pdnsutil show-zone example.com

Test with dig:

dig @localhost example.com DNSKEY +dnssec +multiline
dig @localhost example.com A +dnssec

Verify the ad (Authenticated Data) flag is set when querying through the recursor:

dig @127.0.0.1 example.com A +dnssec

Check NSEC3 records:

dig @localhost example.com NSEC3PARAM

Use delv for detailed validation:

delv @localhost example.com A +rtrace

Test the full chain of trust from an external resolver:

dig example.com A +dnssec +trace