Back to skills
SKILL.md
Powerdns
BSecurityExpert 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...
- 4 stars
- 0 votes
- 0 copies
- 0 views
- Added September 24, 2026
Works with
Security analysis
88/100- Exfiltrates credentials via HTTP — exact pattern from Snyk ToxicSkills study
Pro scans all 2 files and shows the line behind each finding
npx -y skills add chrishuffman5/domain-expert --skill powerdns --agent claude-codeAre you the author of Powerdns?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/chrishuffman5-powerdns)---
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)
Files in this skill
- SKILL.md
- references/architecture.md
Attribution
Comments
Loading comments…