TTR Networks

Intermediate · PowerDNS on Debian: authoritative, secondary, DNSSEC and recursor · section 7 of 10

DNSSEC

✓ Lab-tested 21 October 2026 on Debian 13.7, PowerDNS Authoritative 4.9.17, PowerDNS Recursor 5.2.13, BIND dig 9.20.29

DNSSEC lets a resolver prove that an answer really came from the zone's owner and wasn't changed on the way. Each zone signs its records, and each parent vouches for its child's key, all the way up to the root. PowerDNS makes the signing side almost automatic: it signs answers as it serves them, from keys kept in the backend.

The backend has to allow it

The first secure-zone fails: No backend was able to secure 'example.net'. PowerDNS's SQL backends only store DNSSEC data when told to, with gsqlite3-dnssec=yes. All three authoritative servers need it, the secondary included, because it stores the signed records it receives.

Signing a zone

pdnsutil secure-zone example.net creates a key and starts signing. PowerDNS's default is a single combined signing key (CSK) using ECDSA P-256 (algorithm 13): small, fast signatures, and one key to manage instead of two. rectify-zone then adds the ordering information PowerDNS needs to prove that names don't exist.

show-zone lists the key, its DNSKEY record (the public key, published in the zone) and the DS record: a hash of that key, which the parent zone must publish. The DS is the link in the chain of trust. Until the parent has it, the zone is signed but nobody can validate it.

The chain of trust

The lab builds the full chain:

  1. The DS for example.net goes into the net zone, and net is signed.
  2. The DS for net goes into the root zone, and the root is signed.
  3. The root's own DS becomes the resolver's trust anchor: the one key it trusts without asking anyone, just as real resolvers ship with the real root's key.

In real life, step 1 is done through your domain registrar, who passes the DS to the registry. One more step matters: signing doesn't change the zone's serial, so increase it and notify, or the secondary keeps serving the unsigned copy.

Signing fails at first (real output)
root@ns1:~# pdnsutil secure-zone example.net && pdnsutil rectify-zone example.net
Securing zone with default key size
Adding CSK (257) with algorithm ecdsa256
No backend was able to secure 'example.net', most likely because no DNSSEC
capable backends are loaded, or because the backends have DNSSEC disabled.
For the Generic SQL backends, set the 'gsqlite3-dnssec', 'gmysql-dnssec' or
'gpgsql-dnssec' flag. Also make sure the schema has been updated for DNSSEC!

root@ns1:~# pdnsutil show-zone example.net
No keys for zone 'example.net'.
This is a Master zone
Last SOA serial number we notified: 2026102104 == 2026102104 (serial in the database)
Zone is not actively secured
Metadata items: 
	SOA-EDIT-API	DEFAULT

root@ns1:~# pdnsutil export-zone-ds example.net
Zone is not actively secured
  • Lines 4–7: The backend must be told to store DNSSEC data.
  • Line 13: Nothing was signed.
Signing example.net (real output)
root@ns1:~# grep dnssec /etc/powerdns/pdns.d/ns1.conf && systemctl restart pdns
gsqlite3-dnssec=yes

root@ns1:~# pdnsutil secure-zone example.net && pdnsutil rectify-zone example.net
Securing zone with default key size
Adding CSK (257) with algorithm ecdsa256
Zone example.net secured
Adding NSEC ordering information for zone 'example.net', 8 updates
Adding NSEC ordering information for zone 'example.net', 1 updates

root@ns1:~# pdnsutil show-zone example.net
This is a Master zone
Last SOA serial number we notified: 2026102104 == 2026102104 (serial in the database)
Metadata items: 
	SOA-EDIT-API	DEFAULT
Zone has NSEC semantics
keys: 
ID = 1 (CSK), flags = 257, tag = 18425, algo = 13, bits = 256	  Active	 Published  ( ECDSAP256SHA256 ) 
CSK DNSKEY = example.net. IN DNSKEY 257 3 13 JwbFcWWEpxje9623ndQwMircZ8Mvk709HHNW+wgpADQC8q3QBMOM5jAHLk2JHFQAUJi/M3OgZ9xFh1OXuwQ3mg== ; ( ECDSAP256SHA256 )
DS = example.net. IN DS 18425 13 2 9b98e79540d98caeb43674c9a6530ecbaa8ea151d501fb8c99819c15154bdd92 ; ( SHA256 digest )
DS = example.net. IN DS 18425 13 4 8ae2e2ff3c30eae3775b6922d6942d698c85d8101467aecc9c5236933278bf3f2a09d14de76db2489c537c238b92563d ; ( SHA-384 digest )

root@ns1:~# pdnsutil export-zone-ds example.net
example.net. IN DS 18425 13 2 9b98e79540d98caeb43674c9a6530ecbaa8ea151d501fb8c99819c15154bdd92 ; ( SHA256 digest )
example.net. IN DS 18425 13 4 8ae2e2ff3c30eae3775b6922d6942d698c85d8101467aecc9c5236933278bf3f2a09d14de76db2489c537c238b92563d ; ( SHA-384 digest )
  • Lines 1–2: gsqlite3-dnssec=yes, then a restart.
  • Lines 5–7: One combined signing key (CSK), ECDSA P-256.
  • Lines 8–9: Ordering information, used to prove names don't exist.
  • Line 18: The key: tag 18425, algorithm 13.
  • Line 19: The public key, published in the zone.
  • Lines 20–21: The DS record the parent must publish (SHA-256; SHA-384 as an alternative).
The chain of trust, up to the root (real output)
root@rootns:~# pdnsutil add-record net example DS '18425 13 2 9b98e79540d98caeb43674c9a6530ecbaa8ea151d501fb8c99819c15154bdd92' && pdnsutil secure-zone net && pdnsutil secure-zone . && pdnsutil rectify-all-zones
New rrset:
example.net. 3600 IN DS 18425 13 2 9b98e79540d98caeb43674c9a6530ecbaa8ea151d501fb8c99819c15154bdd92
Securing zone with default key size
Adding CSK (257) with algorithm ecdsa256
Zone net secured
Adding NSEC ordering information for zone 'net', 11 updates
Securing zone with default key size
Adding CSK (257) with algorithm ecdsa256
Zone . secured
Adding NSEC ordering information for zone '.', 9 updates
Rectifying .: Adding NSEC ordering information for zone '.', 6 updates
Rectifying net: Rectified 2 zones.
Adding NSEC ordering information for zone 'net', 11 updates

root@rootns:~# pdnsutil add-record . net DS '53664 13 2 a5e8adbc0be2c16c3f5ec9e93ac1c0355414c57a02938625531d01742dc23670' && pdnsutil rectify-zone . && systemctl restart pdns
New rrset:
net. 3600 IN DS 53664 13 2 a5e8adbc0be2c16c3f5ec9e93ac1c0355414c57a02938625531d01742dc23670
Adding NSEC ordering information for zone '.', 8 updates

root@rootns:~# pdnsutil export-zone-ds . | grep SHA256
. IN DS 49430 13 2 79ec0fb185cf6f5be1df5936655d08fb7dc4e280694535ab8d819da9cccb7757 ; ( SHA256 digest )

root@client:~# dig @203.0.113.1 net DS +dnssec +norecurse | grep -E "IN\s+(DS|RRSIG)"
;net.				IN	DS
net.			3600	IN	RRSIG	DS 13 1 3600 20261029000000 20261008000000 49430 . +pS6XfP+cKLJUeWgookIAa7O9ZSj9dvFrcewzQt9Uh6L+2uFxsRjfNZR 3RfEMzGscllmsoJQduhuaUdO9uUaHA==
net.			3600	IN	DS	53664 13 2 A5E8ADBC0BE2C16C3F5EC9E93AC1C0355414C57A02938625531D0174 2DC23670

root@client:~# dig @203.0.113.1 example.net DS +dnssec +norecurse | grep -E "IN\s+(DS|RRSIG)"
;example.net.			IN	DS
example.net.		3600	IN	DS	18425 13 2 9B98E79540D98CAEB43674C9A6530ECBAA8EA151D501FB8C99819C15 154BDD92
example.net.		3600	IN	RRSIG	DS 13 2 3600 20261029000000 20261008000000 53664 net. GfYaqMVw6dN7eEdz83lw51lIxTbSAj92Pzm4K6k79gZcNcnGjo2ZmDPF M/BrEai8QxIlITP71R424fgYY+KLvQ==
  • Lines 1–3: example.net's DS goes into net…
  • Lines 4–10: …net and the root are signed…
  • Lines 16–18: …net's DS goes into the root…
  • Lines 21–22: …and the root's DS becomes the resolver's trust anchor.
  • Lines 25–27: The root vouches for net (signed by key 49430, the root's).
  • Lines 30–32: net vouches for example.net (signed by key 53664, net's).

Check your understanding

You've just run pdnsutil secure-zone on your zone. What else has to happen before validating resolvers trust its signatures?

  • The DS record has to be published in the parent zone, through your registrar.
  • Every resolver needs your DNSKEY configured by hand.
  • Nothing: signing is enough.
  • The zone has to be converted to NSEC3.