Import socketserverimport struct# DNS queryclass sindnsquery:def __init__ (self, data): i = 1 Self.name = "While true:d = data[i] if d = = 0:break; If d < 32:self.name = Self.name + '. ' Else:self.name = Self.name + chr (d) i = i + 1 self.querybytes = data[0:i + 1] (SE Lf.type, self.classify) = Struct.unpack (' >hh ', Data[i + 1:i + 5]) Self.len = i + 5 def getbytes (self): return self.querybytes + struct.pack (' >hh ', Self.type, self.classify) # DNS Answer rrs# This class is also can are use a S authority RRS or Additional rrsclass sindnsanswer:def __init__ (self, IP): self.name = 49164 Self.type = 1 Self.classify = 1 self.timetolive = Self.datalength = 4 Self.ip = IP def getbytes (s ELF): res = struct.pack (' >hhhlh ', Self.name, Self.type, Self.classify, self.timetolive, SElf.datalength) s = Self.ip.split ('. ') res = res + struct.pack (' BBBB ', int (s[0]), int (s[1]), int (s[2]), int (s[3])) return res# DNS frame# must initialized By a DNS query Frameclass sindnsframe:def __init__ (self, Data): (Self.id, Self.flags, Self.quests, Self.answer S, Self.author, self.addition) = Struct.unpack (' >hhhhhh ', data[0:12]) Self.query = Sindnsquery (data[12:]) def GetName (self): return self.query.name def setip (self, IP): self.answer = Sindnsanswer (IP) self.an Swers = 1 Self.flags = 33152 def getbytes (self): res = struct.pack (' >hhhhhh ', self.id, Self.flags, sel F.quests, Self.answers, Self.author, self.addition) res = res + self.query.getbytes () if self.answers! = 0: res = res + self.answer.getbytes () return res# A Udphandler to handle DNS queryclass Sindnsudphandler (so Cketserver. Baserequesthandler): def handle (self): data = Self.request[0].strip () Print (data) DNS = Sindnsframe (data) socket = self.request[1] Namemap = Sindnsserver.namemap W if (dns.query.type==1): # If this is query a a record and then response it name = Dns.getname () ; If namemap.__contains__ (name): # If have record, response it Dns.setip (Namemap[name]) Socket.sendto (Dns.getbytes (), self.client_address) elif namemap.__contains__ (' * '): # Re Sponse Default Address Dns.setip (namemap[' * ') socket.sendto (Dns.getbytes (), Self.client_add ress) Else: # Ignore it socket.sendto (data, self.client_address) Else: # If This was not query a a record, ignore it socket.sendto (data, self.client_address) # DNS server# it O nly support A Record query# user it, U can create A simple DNS serverclass sindnsserver:def __init__ (self, port=53): SindnSserver.namemap = {} Self.port = port def addname (self, Name, IP): sindnsserver.namemap[name] = IP def Start (self): HOST, PORT = "192.168.4.231", self.port server = Socketserver. Udpserver (HOST, PORT), Sindnsudphandler) Server.serve_forever () # Now, test itif __name__ = = "__main__": SEv = S Indnsserver () sev.addname (' www.aa.com ', ' 192.168.0.1 ') # Add a A record sev.addname (' www.bb.com ', ' 192.168.0.2 ') # Add a A record sev.addname (' * ', ' 192.168.216.194 ') # Default address Sev.start () # start DNS server# now, U can Use "nslookup" command to test it# Such as "nslookup www.aa.com"
Python DNS Server