Comprehensive security and hardening guidance for PowerDNS Authoritative Server, Recursor, and DNSdist with current best practices. This guide covers essential security measures for protecting your DNS infrastructure.
# Enable API with strong authentication
api=yes
api-key=your_very_strong_api_key_here # Generate with: openssl rand -hex 32
# Restrict API access to localhost only
webserver-address=127.0.0.1
webserver-port=8081
# If external access is required, restrict to specific networks
webserver-allow-from=127.0.0.1,10.0.0.0/8,192.168.0.0/16
# Secure web interface
webserver-password=your_very_strong_web_password
webserver-loglevel=normal
# MySQL backend with SSL
gmysql-host=localhost
gmysql-user=pdns
gmysql-password=your_secure_password
gmysql-dbname=pdns
gmysql-ssl=true
gmysql-ssl-ca-file=/path/to/ca-cert.pem
gmysql-ssl-cert-file=/path/to/client-cert.pem
gmysql-ssl-key-file=/path/to/client-key.pem
# PostgreSQL backend with SSL
gpgsql-host=localhost
gpgsql-user=pdns
gpgsql-password=your_secure_password
gpgsql-dbname=pdns
gpgsql-sslmode=require
# Restrict zone transfers to trusted IPs
allow-axfr-ips=10.0.1.10,10.0.1.11,2001:db8::10,2001:db8::11
# Require TSIG for zone transfers
allow-axfr-without-tsig=no
# Limit number of concurrent transfers
axfr-threads=10
# Define TSIG keys in database or configuration
# Example for database-based TSIG:
# Insert into tsigkeys (name, algorithm, secret) VALUES ('transfer-key', 'hmac-sha256', 'base64-encoded-secret');
# Enable DNSSEC
enable-dnssec=yes
# Use strong algorithms
default-dnssec-algorithm=13 # ECDSAP256SHA256
default-dnssec-keysize=256 # For ECDSA
# Or for RSA
# default-dnssec-algorithm=8 # RSA-SHA256
# default-dnssec-keysize=2048 # For RSA
# Secure key storage
# Store private keys securely and separately from public keys
# Restrict query access to specific networks (optional)
allow-from=0.0.0.0/0,::/0 # Usually leave open for public DNS
# Rate limiting
max-qperq=50 # Max queries per second per IP
# TCP query limits
max-tcp-connection-duration=15
max-tcp-connections-per-client=10
# Listen only on internal interfaces
local-address=127.0.0.1,::1
local-port=53
# Query source masking
query-local-address=0.0.0.0
query-local-address6=::
# Security options
chroot=""
setgid=pdns-recursor
setuid=pdns-recursor
# DNSSEC validation
dnssec=validate
# Rate limiting
max-concurrent-requests-per-tcp-connection=10
max-tcp-clients=128
# Use RPZ for threat intelligence feeds
rpz-file=/etc/powerdns/rpz-blocklist.txt
rpz-override-origin=rpz.example.com
# Web interface security
webserver("127.0.0.1:8083")
setWebserverConfig({password="strong_web_password", apiKey="strong_api_key"})
# ACL for web interface
setACL({"127.0.0.0/8", "::1/128", "10.0.0.0/8"})
# Rate limiting
-- Limit queries per second per IP
function maintenance()
purgeRateLimitDB()
end
-- Add rule to drop excessive queries
-- Drop clients exceeding 100 qps
addAction(NotRule(MaxQPSIPRule(100)), RCodeAction(DROP))
# Secure configuration files
sudo chmod 640 /etc/powerdns/pdns.conf
sudo chown pdns:pdns /etc/powerdns/pdns.conf
# Secure database credentials
sudo chmod 600 /etc/powerdns/pdns.d/db.conf
sudo chown pdns:pdns /etc/powerdns/pdns.d/db.conf
# Example iptables rules
# Allow DNS queries
iptables -A INPUT -p udp --dport 53 -j ACCEPT
iptables -A INPUT -p tcp --dport 53 -j ACCEPT
# Allow API access only from management network
iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 8081 -j ACCEPT
# Allow database connections only from local host
iptables -A INPUT -s 127.0.0.1 -p tcp --dport 3306 -j ACCEPT # MySQL
iptables -A INPUT -s 127.0.0.1 -p tcp --dport 5432 -j ACCEPT # PostgreSQL
# Enable query logging (be cautious with volume)
log-dns-details=on
log-dns-queries=on
# Log security events
loglevel=6
# Send logs to syslog
logging-facility=1 # Use facility 1 for DNS logs
# Enable extended statistics
extended-statistics=yes
# Example secure Docker Compose
version: '3.8'
services:
powerdns:
image: powerdns/pdns-auth-49:latest
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
- /var/run
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
user: "pdns:pdns"
# ... rest of configuration
Questions? Find all contact information on our contact page.