Skip to content

Last updated: 2026-06-25

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

  • PowerDNS Authoritative Server 4.9 or later (earlier 4.x releases are end-of-life; 5.x is current)
  • PowerDNS Recursor 5.x recommended (outgoing DoT was introduced in 4.6, but the 4.x line is end-of-life)
  • A backend that supports DNSSEC (e.g., gmysql, gpgsql, lmdb, bind)
  • A valid TLS certificate and private key (for DoT via dnsdist)

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:

  • 1 - NSEC3 algorithm (SHA-1, the only defined algorithm)
  • 0 - Flags (0 = no opt-out)
  • 0 - Iterations (0 is recommended per RFC 9276)
  • - - Empty salt (no salt, recommended per RFC 9276)

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

# 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.6+ 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+.

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

Security Notes

The cipher suite and protocol configuration in this guide addresses the following known TLS vulnerabilities:

  • POODLE (CVE-2014-3566, 2014): SSL 3.0 is disabled. TLS_FALLBACK_SCSV was added in OpenSSL 1.0.1j / 1.0.2 (October 2014); SSL 3.0 disabled by default in OpenSSL 1.1.0 (August 2016).
  • BEAST (CVE-2011-3389, 2011): Mitigated by recommending TLS 1.2 as the minimum; AEAD-only ciphers eliminate the CBC padding oracle.
  • CRIME (CVE-2012-4929, 2012): TLS compression is off by default in OpenSSL 1.1.0+; do not enable it.
  • Lucky13 (2013): AEAD-only cipher list eliminates CBC padding timing side-channels entirely.
  • FREAK (CVE-2015-0204, 2015): EXPORT-grade ciphers are excluded. Removed from OpenSSL 1.1.0 (August 2016).
  • 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 cipher string.
  • ROBOT (2017): Static RSA key exchange is excluded; only ECDHE is recommended.
  • Downgrade attacks: TLS_FALLBACK_SCSV prevents protocol version rollback.

The following are not addressable through TLS configuration alone:

  • Heartbleed (CVE-2014-0160, 2014): A memory disclosure bug in OpenSSL 1.0.1 through 1.0.1f. Fixed in OpenSSL 1.0.1g (April 7, 2014). Addressed by patching OpenSSL, not by TLS configuration.
  • BREACH (CVE-2013-3587, 2013): Not applicable. BREACH targets HTTP-level response compression; DNS-over-TLS does not involve HTTP. DNS-over-HTTPS uses HTTP but typically without compressible secret data.
  • DROWN (CVE-2016-0800, 2016): Requires SSLv2 to be enabled on any server sharing the same private key. Ensure SSLv2 is disabled on all services that use the same certificate and key pair.

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

Verify the full DNSSEC chain of trust externally with the Mr.DNS DNSSEC Validation Check.


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 →