#format python #!/usr/bin/env python import sys import time import datetime import threading import traceback import SocketServer from sets import Set import dnslib from dnslib import QTYPE, SOA, NS, A, AAAA, MX, CNAME from dnslib import DNSRecord, DNSHeader, RR, RCODE z = 'd.qmail.jp.' IP= '192.168.10.7' TTL = 60 * 5 PORT = 5053 #---------------- read zone ----------------------- zone ={} #Dict; key is a domain name #value: Dict for rtype # value: RRSet zonetxt = open('zone.txt').read() print(zonetxt) print '-----' zonerr= RR.fromZone(zonetxt) for rr in zonerr: name = str(rr.rname) if not(name in zone) : zone[name] = {} # make empty node if not(rr.rtype in zone[name]): zone[name][rr.rtype] = Set([]) # empty query type zone[name][rr.rtype].add(rr) # ----- for name in zone: print name, zone[name] print '-----' #----- for rrs in zone: print (zone[rrs]) print '--------------------------------' rrs = zone[z] # zone apex node if QTYPE.SOA in rrs: soa_record = rrs[QTYPE.SOA].pop() print 'SOA= ', soa_record #------ IP= '192.168.10.7' TTL = 60 * 5 PORT = 5053 ServerIP = '192.168.10.7' def dns_response(packet): query = DNSRecord.parse(packet) print '--- query ---' print query print '------------' reply = DNSRecord(DNSHeader(id=query.header.id, qr=1, aa=1), q=query.q) reply #debug print qname = query.q.qname qtype = query.q.qtype qt = QTYPE[qtype] qn = str(qname).lower() if qn in zone : print zone[qn] if qtype in zone[qn]: for rr in zone[qn][qtype]: #rrset print 'found RRSet', rr reply.add_answer(rr) else: if QTYPE.CNAME in zone[qn] : print 'CNAME found.' print zone[qn][QTYPE.CNAME] for rr in zone[qn][QTYPE.CNAME]: reply.add_answer(RR(qname, QTYPE.CNAME, ttl=TTL, rdata=rr.rdata)) # reply.add_answer(RR(qname, QTYPE.NS, ttl=TTL, rdata=rdata) #NoData response here # reply.add_auth(RR(D, QTYPE.NS, ttl=TTL, rdata=rdata)) else: # NXDomain if not (qn.endswith('.' + z)): return reply.add_auth(soa_record) #NoData response here may be reply.header.rcode = getattr(RCODE,'NXDOMAIN') print "---- Reply:\n", reply return reply.pack() class BaseRequestHandler(SocketServer.BaseRequestHandler): def get_data(self): raise NotImplementedError def send_data(self, data): raise NotImplementedError def handle(self): now = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f') print "\n\n%s request %s (%s %s):" % (self.__class__.__name__[:3], now, self.client_address[0], self.client_address[1]) try: data = self.get_data() print len(data), data.encode('hex') # repr(data).replace('\\x', '') [1:-1] self.send_data(dns_response(data)) except Exception: traceback.print_exc(file=sys.stderr) class UDPRequestHandler(BaseRequestHandler): def get_data(self): return self.request[0].strip() def send_data(self, data): return self.request[1].sendto(data, self.client_address) if __name__ == '__main__': print "Starting nameserver..." servers = [ SocketServer.ThreadingUDPServer((ServerIP, PORT), UDPRequestHandler), # SocketServer.ThreadingTCPServer((ServerIP, PORT), TCPRequestHandler), ] for s in servers: thread = threading.Thread(target=s.serve_forever) # that thread will st art one more thread for each request thread.daemon = True # exit the server thread when the main thread term inates thread.start() print "%s server loop running in thread: %s" % (s.RequestHandlerClass.__ name__[:3], thread.name) try: while 1: time.sleep(1) sys.stderr.flush() sys.stdout.flush() except KeyboardInterrupt: pass finally: for s in servers: s.shutdown()