The PowerDNS Pipe Backend allows developers to attach custom external scripts (written in Python, Perl, Bash, or Go) to resolve DNS queries dynamically over standard I/O streams. This approach is ideal for dynamically serving CNAME aliases, geo-routing records, or integrating DNS responses with external APIs without rebuilding PowerDNS.
pdns-backend-pipe • Python IPC
1. Installing PowerDNS Pipe Backend (CentOS / RHEL)
yum install pdns pdns-backend-pipe -y
Configure /etc/pdns/pdns.conf to launch the pipe backend alongside standard zone providers:
launch=bind,pipe
pipe-command=/etc/pdns/pdns-backend.py
2. The Python Backend Script (/etc/pdns/pdns-backend.py)
The script communicates with PowerDNS via tab-delimited protocol over stdin/stdout. Note the -u flag on Python to ensure unbuffered I/O:
#!/usr/bin/python -u
from sys import stdin, stdout
# Handshake initialization
data = stdin.readline()
stdout.write("OK My Dynamic Python Backend
")
stdout.flush()
TARGET_CNAME = 'cname-target.example.com'
while True:
line = stdin.readline()
if not line:
break
data = line.strip()
kind, qname, qclass, qtype, qid, ip = data.split(' ')
if kind == 'Q' and qname not in TARGET_CNAME:
# Provide SOA record for authoritative delegation
soa_resp = f"DATA {qname} {qclass} SOA 86400 -1 support.{qname} ns1.example.org 2026010100 1800 3600 604800 3600
"
stdout.write(soa_resp)
# Respond to ANY or CNAME queries
if qtype in ('ANY', 'CNAME'):
cname_resp = f"DATA {qname} {qclass} CNAME 86400 {qid} {TARGET_CNAME}
"
stdout.write(cname_resp)
stdout.write("END
")
stdout.flush()
Make the script executable and restart PowerDNS:
chmod +x /etc/pdns/pdns-backend.py
systemctl restart pdns