Created
January 5, 2016 21:12
-
-
Save seveas/0101269a51ac765b887f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
options { | |
directory "/home/dennis/pdns-bug/inst/var/run/pdns-server/"; | |
}; | |
zone "example.com" IN { | |
type master; | |
file "example.com.zone"; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@ 900 SOA ns0.example.com. domain.example.com. 2016010401 28800 7200 604800 86402 | |
@ 900 NS ns0.example.com. | |
c 900 NS ns0.example.com. | |
ns0 900 A 127.0.0.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import logging | |
import logging.handlers | |
import os | |
import platform | |
import re | |
import select | |
import signal | |
import sys | |
import syslog | |
# Non-blocking Syslog logging handler | |
class SysLogLibHandler(logging.Handler): | |
"""A logging handler that emits messages to syslog.syslog.""" | |
priority_map = { | |
"DEBUG" : syslog.LOG_DEBUG, | |
"INFO" : syslog.LOG_INFO, | |
"WARNING" : syslog.LOG_WARNING, | |
"ERROR" : syslog.LOG_ERR, | |
"CRITICAL" : syslog.LOG_CRIT, | |
} | |
def __init__(self, facility): | |
try: | |
syslog.openlog(os.path.basename(sys.argv[0]),logoption=syslog.LOG_PID | syslog.LOG_NDELAY, facility='daemon') | |
except Exception: | |
pass | |
logging.Handler.__init__(self) | |
def emit(self, record): | |
syslog.syslog(self.priority_map[record.levelname], self.format(record)) | |
class Daemon(object): | |
addresses = { | |
'www1.c.example.com': '127.0.0.1', | |
'www2.c.example.com': '127.0.0.2', | |
} | |
def __init__(self): | |
# 0 - normal operation | |
# 1 - SIGHUP received => restarting | |
self.restarting = 0 | |
self.exiting = False | |
self.abi_version = None | |
signal.signal(signal.SIGINT, self.handle_sigint) | |
signal.signal(signal.SIGTERM, self.handle_sigint) | |
signal.signal(signal.SIGIO, self.handle_sigint) | |
signal.signal(signal.SIGPIPE, self.handle_sigint) | |
self.logger = logging.getLogger() | |
if sys.stdout.isatty(): | |
handler = logging.StreamHandler() | |
formatter = logging.Formatter("%(filename)s[%(process)d]: %(message)s") | |
handler.setFormatter(formatter) | |
else: | |
handler = SysLogLibHandler(facility='daemon') | |
self.logger.addHandler(handler) | |
self.logger.setLevel(logging.INFO) | |
def handle_sigint(self, signum, frame): | |
self.exiting = True | |
self.logger.info("Caught signal %d" % signum) | |
def handle_sighup(self, signum, frame): | |
if self.restarting == 0: | |
self.restarting = 1 | |
self.logger.info("Caught signal %d" % signum) | |
def process_requests(self): | |
self.logger.info("Backend ready using %s (%s %s)" % (sys.executable, platform.python_implementation(), platform.python_version())) | |
signal.signal(signal.SIGHUP, self.handle_sighup) | |
while not self.exiting: | |
if self.restarting: | |
signal.signal(signal.SIGHUP, signal.SIG_IGN) | |
self.logger.info("Restarting backend") | |
os.execl(sys.argv[0],*sys.argv) | |
try: | |
rin, rout, rerr = select.select([sys.stdin], [], [], 5) | |
except select.error as e: | |
# Ignore EINTR | |
if e[0] == 4: continue | |
else: raise | |
if sys.stdin in rin: | |
req = sys.stdin.readline().strip() | |
self.logger.info("[IN] " + req.replace('\t', ' ').replace('\n', ' - ')) | |
ans = self.process_single_request(req) | |
if ans: | |
sys.stdout.write(ans + "\n") | |
sys.stdout.flush() | |
self.logger.info("[OUT] " + ans.replace('\t', ' ').replace('\n', ' - ')) | |
self.logger.info("Backend exiting") | |
def process_single_request(self, req): | |
if req == '': | |
self.logger.info("EOF from powerdns") | |
self.exiting = True | |
return "" | |
req = req.split('\t') | |
reqtype = req[0].lower() | |
req = req[1:] | |
return getattr(self, 'handle_' + reqtype)(*req) | |
def handle_helo(self, abi_version): | |
self.abi_version = int(abi_version) | |
self.logger.info("Powerdns says hi, API version %d" % self.abi_version) | |
if self.abi_version not in (1,2): | |
return "FAIL" | |
return "OK\tbooking powerdns backend started" | |
def handle_axfr(self, id): | |
return "FAIL" | |
def handle_ping(self): | |
return "END" | |
def handle_q(self, qname, qclass, qtype, id, remote_ip, local_ip=None): | |
if qclass != 'IN' or remote_ip == '0.0.0.0': | |
return "END" | |
qname_l = qname.lower() | |
ret = [] | |
if qtype == 'ANY': | |
self.handle_soa(qname, ret) | |
self.handle_ns(qname, ret) | |
self.handle_a(qname, ret) | |
elif hasattr(self, 'handle_' + qtype.lower()): | |
getattr(self, 'handle_' + qtype.lower())(qname, ret) | |
else: | |
self.logger.error("Cannot handle %s queries" % qtype) | |
return "\n".join(ret + ['END']) | |
def handle_soa(self, qname, ret): | |
if qname.lower() == 'c.example.com': | |
soa = "ns0.example.com. postmaster.example.com. 2013112600 14400 900 3628800 300" | |
ret.append("DATA\t%s\tIN\tSOA\t%d\t-1\t%s" % (qname, 300, soa)) | |
def handle_ns(self, qname, ret): | |
if qname.lower() == 'c.example.com': | |
for i in range(4): | |
ret.append("DATA\t%s\tIN\tNS\t%d\t-1\tns%d.example.com." % (qname, 900, i)) | |
def handle_txt(self, qname, ret): | |
pass | |
def handle_srv(self, qname, ret): | |
pass | |
def handle_a(self, qname, ret): | |
if qname in self.addresses: | |
ret.append("DATA\t%s\tIN\tA\t600\t-1\t%s" % (qname, self.addresses[qname])) | |
if __name__ == '__main__': | |
daemon = Daemon() | |
try: | |
daemon.process_requests() | |
except Exception: | |
daemon.logger.exception("Exception occured, exiting") | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module-dir=/home/dennis/pdns-bug/inst/lib/pdns | |
socket-dir=/home/dennis/pdns-bug/inst/var/run/pdns-server | |
setuid=dennis | |
setgid=dennis | |
launch=pipe,bind | |
version-string=You might very well think I am that version but I could not possibly comment | |
local-address=127.0.0.1 | |
default-soa-name=domain.example.com | |
pipebackend-abi-version=2 | |
pipe-command=/home/dennis/pdns-bug/pdns-backend | |
pipe-timeout=2000 | |
pipe-regex=^([^.]+\.)?c\.example\.com;.*$ | |
# Disable caches | |
query-cache-ttl=0 | |
cache-ttl=0 | |
# logging | |
loglevel=7 | |
log-dns-details=no | |
bind-config=/home/dennis/pdns-bug/bind.conf |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment