O PowerDNS suporta vários back-ends, um deles é um back-end de pipe que você pode usar para processar a consulta e enviar o que você solicita. Se você adicionar as diretivas para usar pipe (neste exemplo, suponho que você tenha alguns arquivos de zona, é por isso que o launch
o bind
backend.
launch=bind,pipe
pipe-command=/etc/pdns/pdns-backend-ip.py
pipe-regex=^.*\.host\.example\.com;.*$
Depois, você pode usar um script Python pdns-backend.py
para processar as consultas e enviar os resultados. Algo parecido com o código abaixo:
#!/usr/bin/python -u
# Implementation of a Pipe Backend for PowerDNS
# https://doc.powerdns.com/md/authoritative/backend-pipe/
# We need Python unbuffered so we use -u
# Another ways to achieve it in
# http://stackoverflow.com/questions/107705/disable-output-buffering
import sys
def build_answer(qname, qtype, answer, ttl=60):
return("%s\tIN\t%s\t%d\t1\t%s" % (qname, qtype, ttl, answer))
def send_log(msg):
sys.stdout.write("LOG\t%s\n" % msg)
def send_data(msg):
sys.stdout.write("DATA\t%s\n" % msg)
send_log("Sent %s" % msg)
# Check first line to ensure that we are properly initialized
line = sys.stdin.readline().rstrip()
if line != "HELO\t1":
sys.stdout.write("FAIL\n")
sys.exit(1)
sys.stdout.write("OK Python backend is alive!\n")
# Process each line!
while True:
raw_line = sys.stdin.readline()
line = raw_line.rstrip()
args = line.split("\t")
if len(args) < 6:
send_log("PowerDNS sent me unparseable line")
sys.stdout.write("FAIL\n")
continue
rtype,qname,qclass,qtype,id,ip = args
send_log("Received [[ %s ]]" % line)
# PDNS will use the SOA to decide which backend to use. We have to answer only
# when the query is as close as possible:
# i.e.: answer host.example.com not to example.com.
if qtype == "SOA" and qname.endswith('host.example.com'):
send_data(build_answer(qname, 'SOA', 'ns1.example.com ahu.example.com 2008080300 1800 3600 604800 3600'))
if qtype in ("A", "ANY") and qname.endswith("host.example.com"):
ip_requested = qname.split('.')[0]
send_data(build_answer(qname, 'A', ip_requested.replace('-','.')))
sys.stdout.write("END\n")
Tendo essa configuração de DNS, você pode processar essa zona como dinâmica:
$ host 11-22-33-44.host.example.com 127.0.0.1
Using domain server:
Name: 127.0.0.1
Address: 127.0.0.1#53
Aliases:
11-22-33-44.host.example.com has address 11.22.33.44
Talvez algo como isso seja um exagero e difícil de depurar (o script python de amostra não faz nenhuma verificação de erros), mas pode ser um bom ponto de partida para ter um servidor DNS realmente dinâmico e programável.