Expert coverage of the PowerDNS suite (Authoritative Server 5.0, Recursor 5.4, and DNSdist 2.0): pluggable backends (MySQL/PostgreSQL/LDAP), DNSSEC auto-signing, REST API, Lua scripting, views, RPZ threat blocking, YAML configuration, DoH/DoT termination, and DNS load balancing. Use for \"PowerDNS\", \"pdns\", \"pdnsutil\", \"Recursor\", \"DNSdist\", \"PowerDNS API\", \"PowerDNS backend\", \"PowerDNS DNSSEC\". Do NOT use for cross-vendor comparison, platform selection, or category-wide archit...
Pro scans all 2 files and shows the line behind each finding
Scanned 9/24/2026
npx -y skills add chrishuffman5/domain-expert --skill powerdns --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Powerdns?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/chrishuffman5-powerdns)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: powerdns
description: "Expert coverage of the PowerDNS suite (Authoritative Server 5.0, Recursor 5.4, and DNSdist 2.0): pluggable backends (MySQL/PostgreSQL/LDAP), DNSSEC auto-signing, REST API, Lua scripting, views, RPZ threat blocking, YAML configuration, DoH/DoT termination, and DNS load balancing. Use for \"PowerDNS\", \"pdns\", \"pdnsutil\", \"Recursor\", \"DNSdist\", \"PowerDNS API\", \"PowerDNS backend\", \"PowerDNS DNSSEC\". Do NOT use for cross-vendor comparison, platform selection, or category-wide architecture -- use the `dns` skill."
license: MIT
---
# PowerDNS
This skill covers the PowerDNS suite -- three distinct products with separate roles. Areas of expertise include:
- **Authoritative Server 5.0**: pluggable backends (gmysql, gpgsql, gsqlite3, gldap, bind, pipe, remote), DNSSEC auto-signing with `pdnsutil`, REST API for zone/record CRUD, Lua scripting hooks, views for split-horizon DNS
- **Recursor 5.4**: high-performance recursive resolver, YAML configuration, DNSSEC validation, RPZ (Response Policy Zones) for threat blocking, Lua scripting, serve-stale/serve-expired resilience, conditional forwarding
- **DNSdist 2.0**: DNS load balancer and protocol frontend, YAML configuration (2.0), DoH/DoT/DoQ termination, rate limiting, DDoS protection, query routing rules, DNSdist Defender for advanced threat mitigation
## How to Approach Tasks
1. **Classify** the request:
- **Authoritative DNS** -- Backend selection, zone management, DNSSEC, API, Lua hooks, views
- **Recursive resolution** -- Recursor configuration, DNSSEC validation, RPZ, forwarding
- **Load balancing / Security** -- DNSdist deployment, DoH/DoT, rate limiting, DDoS protection
- **Architecture** -- Load `references/architecture.md` for component relationships and deployment patterns
2. **Identify component** -- Authoritative, Recursor, or DNSdist. These are separate binaries with separate configurations. Never combine authoritative and recursive in the same PowerDNS instance.
3. **Identify version** -- Auth 5.0 introduces views and enhanced Lua hooks. Recursor 5.2+ uses YAML as recommended config format. DNSdist 2.0 introduces YAML configuration alternative to Lua.
4. **Recommend** -- Provide specific configuration (YAML for Recursor/DNSdist, pdnsutil commands for Auth, API calls for automation).
## Authoritative Server 5.0
### Backend Architecture
PowerDNS Auth does NOT perform recursive lookups. It answers queries for zones it is authoritative for, using pluggable backends:
| Backend | Database | Use Case |
|---|---|---|
| gmysql | MySQL/MariaDB | Most common; production |
| gpgsql | PostgreSQL | Production; advanced SQL |
| gsqlite3 | SQLite3 | Dev/small deployments |
| gldap | LDAP | ISP/hosting with directory |
| bind | Zone files | Legacy compatibility |
| pipe | External process | Custom backends |
| remote | JSON/REST/Unix | Custom resolver integration |
### DNSSEC
Built-in with automated key management:
```bash
pdnsutil secure-zone example.com # enable DNSSEC
pdnsutil set-nsec3 example.com # enable NSEC3
pdnsutil show-zone example.com # view DNSKEY + DS hashes
```
Supported algorithms: ED25519, ED448, ECDSA P-256/P-384, RSA. Online signing with key material stored in database. Auto ZSK rollover; manual KSK rollover with DS publication at parent.
### REST API
Full CRUD for zone and record management:
```bash
# Create zone
curl -X POST http://localhost:8081/api/v1/servers/localhost/zones \
-H "X-API-Key: secret" \
-d '{"name":"example.com.","kind":"Native","nameservers":["ns1.example.com."]}'
# Add/replace record
curl -X PATCH http://localhost:8081/api/v1/servers/localhost/zones/example.com. \
-H "X-API-Key: secret" \
-d '{"rrsets":[{"name":"www.example.com.","type":"A","ttl":300,
"changetype":"REPLACE","records":[{"content":"10.1.1.1","disabled":false}]}]}'
```
### Lua Scripting
Dynamic query/response handling via hooks: `preresolve`, `postresolve`, `preaxfr`, `nodata`, `nxdomain`. Use cases: geo-based responses, A/B testing, real-time block lists.
### Views (5.0)
Split-horizon DNS -- different responses based on client source:
```yaml
views:
internal:
networks: [10.0.0.0/8, 192.168.0.0/16]
zones:
- name: example.com
backend: gmysql
database: internal_db
external:
networks: [0.0.0.0/0]
zones:
- name: example.com
backend: gmysql
database: external_db
```
## Recursor 5.4
### YAML Configuration (Recommended)
```yaml
dnssec:
validate: validate # validate | log-fail | off
incoming:
listen: ["0.0.0.0:53", "[::]:53"]
allow_from: ["127.0.0.0/8", "192.168.0.0/16"]
forwarding:
zones:
- zone: internal.corp
recurse: false
forwarders: ["10.0.0.53"]
rpz:
- name: security-policy
url: https://rpz.example.com/feed.zone
defpol: Policy.Drop
refresh: 300
```
### DNSSEC Validation
Modes: `off`, `process` (log failures), `log-fail` (log + continue), `validate` (strict -- BOGUS = SERVFAIL). Built-in root zone trust anchors with automatic updates.
### RPZ (Response Policy Zones)
DNS-based threat blocking with feed support:
- Actions: NXDOMAIN, DROP, PASSTHRU, NODATA, REDIRECT to walled garden
- Multiple feeds with priority ordering
- Providers: Spamhaus, SURBL, self-managed
- 5.4 feature: `includeSoA` for RPZ zone SOA propagation
### Serve-Stale / Serve-Expired
Return expired cache entries when upstream unreachable. Configurable max-stale age. Essential for DNS resilience during outages.
## DNSdist 2.0
### Architecture
Sits in front of DNS servers providing: load balancing, DoH/DoT/DoQ frontend termination, rate limiting, DDoS protection, query routing.
### YAML Configuration (2.0)
```yaml
listen_addresses:
- "0.0.0.0:53"
- "0.0.0.0:853" # DoT
- "0.0.0.0:443" # DoH
backends:
- address: "192.168.1.10:53"
name: "recursor1"
- address: "192.168.1.11:53"
name: "recursor2"
policy: "leastOutstanding"
tls:
certificates:
- cert: "/etc/ssl/dns.pem"
key: "/etc/ssl/dns.key"
doh:
paths: ["/dns-query"]
http_version: "h2"
```
### Rules Engine (Lua)
```lua
addAction(MaxQPSIPRule(100), DropAction()) # rate limit per IP
addAction(QTypeRule(dnsdist.ANY), RCodeAction(dnsdist.REFUSED)) # block ANY queries
addAction(SuffixMatchNodeRule(newSuffixMatchNode({"internal.corp."})),
PoolAction("internal")) # route internal queries
```
### DNSdist Defender
Advanced threat mitigation: DNS tunneling detection, PRSD (pseudo-random subdomain) attack mitigation, amplification/reflection prevention, CEF/syslog threat intelligence export.
### Health Checks and Monitoring
```yaml
backends:
- address: "192.168.1.10:53"
name: "recursor1"
healthcheck: true
check_interval: 5
```
Built-in web dashboard, Prometheus metrics endpoint, Carbon/Graphite export. Per-backend query statistics, latency percentiles, error rates.
## Deployment Patterns
### Authoritative + Recursor Behind DNSdist
```
Internet ──► DNSdist (port 53, DoH, DoT)
│
┌────────┴────────┐
│ │
Auth Server Recursor
(zones you own) (recursive for clients)
```
DNSdist routes based on zone ownership. Queries for hosted zones go to Auth; everything else goes to Recursor.
### Authoritative with Database Backend
```
DNSdist ──► Auth Server 1 ──► MySQL Primary
│ │
Auth Server 2 ──► MySQL Replica (read)
```
Multiple Auth instances load-balanced by DNSdist. MySQL replication for zone data redundancy. Native zone replication via AXFR/IXFR also supported.
### Recursor with RPZ Threat Blocking
```
Internal clients ──► Recursor
├── RPZ Feed 1 (Spamhaus)
├── RPZ Feed 2 (SURBL)
└── RPZ Feed 3 (Custom blocklist)
```
Multiple RPZ feeds loaded with priority ordering. Blocked domains return NXDOMAIN, NODATA, or redirect to walled garden.
### High Availability with DNSdist
```
Anycast VIP ──► DNSdist Active
│
DNSdist Standby (keepalived)
│
┌───────┴───────┐
│ │
Recursor 1 Recursor 2
```
DNSdist HA via keepalived with shared anycast VIP. Backend health checks with automatic failover.
## Authoritative Server Configuration
### pdns.conf Core Settings
```ini
# Backend
launch=gmysql
gmysql-host=127.0.0.1
gmysql-dbname=pdns
gmysql-user=pdns
gmysql-password=secret
# API
api=yes
api-key=changeme
webserver=yes
webserver-address=0.0.0.0
webserver-port=8081
webserver-allow-from=10.0.0.0/8
# Performance
receiver-threads=4
distributor-threads=4
cache-ttl=60
query-cache-ttl=60
negquery-cache-ttl=60
# DNSSEC
default-soa-content=ns1.example.com hostmaster.@ 0 10800 3600 604800 300
# Security
allow-axfr-ips=10.0.0.0/8
disable-axfr=no
only-notify=10.0.0.100,10.0.0.101
```
### Zone Management via pdnsutil
```bash
# Create zone
pdnsutil create-zone example.com ns1.example.com
# Add records
pdnsutil add-record example.com www A 300 10.1.1.1
pdnsutil add-record example.com @ MX 300 "10 mail.example.com"
pdnsutil add-record example.com @ TXT 300 "v=spf1 ip4:10.1.1.0/24 -all"
# List zone contents
pdnsutil list-zone example.com
# DNSSEC operations
pdnsutil secure-zone example.com
pdnsutil show-zone example.com
pdnsutil set-nsec3 example.com '1 0 1 -' optout
pdnsutil rectify-zone example.com
# Zone transfer management
pdnsutil increase-serial example.com
```
## Recursor Lua Scripting
### Request Filtering
```lua
function preresolve(dq)
-- Block specific domain
if dq.qname:equal(newDN("malware.example.com")) then
dq.rcode = pdns.NXDOMAIN
return true
end
-- Log all queries from specific subnet
if dq.remoteaddr:isPartOf(newNMG({"10.100.0.0/16"})) then
pdnslog("Query from monitored subnet: " .. dq.qname:toString())
end
return false
end
```
### Response Modification
```lua
function postresolve(dq)
-- Add response header for debugging
if dq.qtype == pdns.A then
for i, rec in ipairs(dq:getRecords()) do
pdnslog("Response: " .. rec:getContent())
end
end
return false
end
```
### Geo-Based Responses (Auth Lua)
```lua
function preresolve(dq)
if dq.qname:equal(newDN("geo.example.com")) then
local src = dq.remoteaddr:toString()
-- Route based on source network
if dq.remoteaddr:isPartOf(newNMG({"10.0.0.0/8"})) then
dq:addAnswer(pdns.A, "10.1.1.1", 60)
else
dq:addAnswer(pdns.A, "203.0.113.1", 60)
end
return true
end
return false
end
```
## Common Pitfalls
1. **Mixing authoritative and recursive** -- PowerDNS Auth and Recursor are separate products. Never configure recursion on Auth or authoritative zones on Recursor. Use DNSdist to combine them behind a single IP.
2. **DNSSEC without DS at parent** -- Securing a zone with `pdnsutil secure-zone` only signs locally. The DS record must be published at the parent registrar, or DNSSEC validation will fail for resolvers.
3. **RPZ startup race** -- Recursor may serve unprotected queries before RPZ zones finish loading. Enable `servfail-until-ready` for strict RPZ enforcement.
4. **gmysql schema version** -- Auth 5.0 requires updated database schema. Run schema migration scripts before upgrading from 4.x.
5. **DNSdist YAML vs Lua confusion** -- DNSdist 2.0 supports both YAML and Lua configuration. Do not mix them in the same deployment. Choose one format and use consistently.
6. **Recursor YAML migration** -- Recursor 5.2+ recommends YAML but still supports legacy config format. Plan migration to YAML for future compatibility.
## Reference Files
- `references/architecture.md` -- Auth Server (backends, DNSSEC, API), Recursor (RPZ, Lua), DNSdist (LB, DoH/DoT)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!