Attachment 'qns.py'
Download 1 #!/usr/bin/env python
2 import sys
3 import time
4 import datetime
5 import threading
6 import traceback
7 import SocketServer
8 from sets import Set
9
10 import dnslib
11 from dnslib import QTYPE, SOA, NS, A, AAAA, MX, CNAME
12 from dnslib import DNSRecord, DNSHeader, RR, RCODE
13
14 IP= '192.168.10.7'
15 TTL = 60 * 5
16 PORT = 5053
17
18 #---------------- read zone -----------------------
19 zone = {} #Dict; key is a domain name
20 #value: Dict for rtype
21 # value: RRSet
22 cuts = Set([]) # delegation point; Set
23
24 # ---- open zone data -------
25 zonetxt = open('zone.txt').read()
26 #print(zonetxt)
27
28 z = '' # zone name
29 for rr in RR.fromZone(zonetxt):
30 name = str(rr.rname)
31 if not(name in zone) : #new name
32 zone[name] = {} # make empty node
33 elif rr.rtype == QTYPE.CNAME :
34 print 'CNAME error', zone[name], rr
35
36 if QTYPE.CNAME in zone[name]: # CNAME exists
37 print 'CNAME error', zone[name], rr
38 if not(rr.rtype in zone[name]): # new rtype -> rrset
39 zone[name][rr.rtype] = Set([]) # empty query type
40 zone[name][rr.rtype].add(rr)
41
42 if rr.rtype == QTYPE.SOA :
43 if z == '':
44 z = name
45 print 'SOA == ', z, zone[name]
46 else :
47 print 'SOA duplicate ', z, name
48
49 if len(z)==0 :
50 print 'No zone found'
51 exit
52
53 zsuffix = '.'+ z
54 #----- remove out of zone name ------
55 for name in zone:
56 if not (name== z or name.endswith(zsuffix)) :
57 delete(zone[name])
58 print 'Out of zone record',
59 print name, (zone[name])
60
61 rrs = zone[z] # zone apex node
62 if QTYPE.SOA in rrs:
63 soa_record = rrs[QTYPE.SOA].copy().pop()
64 ns_record = rrs[QTYPE.NS]
65
66 print '---- zone apex record ----'
67 print zone[z]
68 print '-----'
69 print 'SOA = ',soa_record
70 print 'NS = ', ns_record
71
72 # delegation list
73 for name in zone:
74 if name == z : continue
75 if QTYPE.NS in zone[name]:
76 cuts.add(name)
77 print 'cut found: ', name
78 print 'cuts =', cuts
79
80 print '-------- Zone processed ---------'
81
82 #------ zone server ---------
83 IP= '192.168.10.7'
84 TTL = 60 * 5
85 PORT = 5053
86 ServerIP = '192.168.10.7'
87
88 def dns_response(packet):
89 query = DNSRecord.parse(packet)
90 print '--- query ---'
91 print query
92 print '------------'
93
94 reply = DNSRecord(DNSHeader(id=query.header.id, qr=1, aa=1), q=query.q)
95 reply #debug print
96 qname = query.q.qname
97 qtype = query.q.qtype
98 qt = QTYPE[qtype]
99 qn = str(qname).lower()
100
101 if qn in zone :
102 print zone[qn]
103 if qtype in zone[qn]:
104 for rr in zone[qn][qtype]: #rrset
105 print 'found RRSet', rr
106 reply.add_answer(rr) # answer RRSet
107 elif (QTYPE.CNAME in zone[qn]) :
108 print 'CNAME found. ---', zone[qn][QTYPE.CNAME]
109 for rr in zone[qn][QTYPE.CNAME]:
110 reply.add_answer(RR(qname, QTYPE.CNAME, ttl=TTL, rdata=rr.rdata))
111
112 # reply.add_answer(RR(qname, QTYPE.NS, ttl=TTL, rdata=rdata)
113 else: #NoData response here
114 reply.add_auth(soa_record)
115
116 else: # NXDomain
117 if not (qn.endswith('.' + z)): return
118 reply.add_auth(soa_record)
119 #NoData response here may be
120 reply.header.rcode = getattr(RCODE,'NXDOMAIN')
121
122 print "---- Reply:\n", reply
123 return reply.pack()
124
125 #---------------------------------------------------------
126 class BaseRequestHandler(SocketServer.BaseRequestHandler):
127
128 def get_data(self):
129 raise NotImplementedError
130
131 def send_data(self, data):
132 raise NotImplementedError
133
134 def handle(self):
135 now = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')
136 print "\n\n%s request %s (%s %s):" % (self.__class__.__name__[:3], now, self.client_address[0],
137 self.client_address[1])
138 try:
139 data = self.get_data()
140 print len(data), data.encode('hex') # repr(data).replace('\\x', '')[1:-1]
141 self.send_data(dns_response(data))
142 except Exception:
143 traceback.print_exc(file=sys.stderr)
144
145
146 class UDPRequestHandler(BaseRequestHandler):
147
148 def get_data(self):
149 return self.request[0].strip()
150
151 def send_data(self, data):
152 return self.request[1].sendto(data, self.client_address)
153
154
155 if __name__ == '__main__':
156 print "Starting nameserver..."
157
158 servers = [
159 SocketServer.ThreadingUDPServer((ServerIP, PORT), UDPRequestHandler),
160 # SocketServer.ThreadingTCPServer((ServerIP, PORT), TCPRequestHandler),
161 ]
162 for s in servers:
163 thread = threading.Thread(target=s.serve_forever) # that thread will start one more thread for each request
164 thread.daemon = True # exit the server thread when the main thread terminates
165 thread.start()
166 print "%s server loop running in thread: %s" % (s.RequestHandlerClass.__name__[:3], thread.name)
167
168 try:
169 while 1:
170 time.sleep(1)
171 sys.stderr.flush()
172 sys.stdout.flush()
173
174 except KeyboardInterrupt:
175 pass
176 finally:
177 for s in servers:
178 s.shutdown()
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.