Python写的一个简单DNS服务器实例
因为突然有个邪恶的想法,想在自己的Android平板上面搭建一个DNS服务器,因为平板上之前安装过SL4A和Python的解释器,也想继续学学Python因此,就打算用Python实现了。
在Google上面找了一下,Python实现的DNS,没找到我所希望的答案,因此就决定自己来实现了。
现在所实现的没什么高深的,只是能够对A记录查询进行简单的匹配和回复。
实现的代码如下:
''' Createdon2012-10-15
@author:RobinTang '''
importsocketserver importstruct
#DNSQuery classSinDNSQuery: def__init__(self,data): i=1 self.name='' whileTrue: d=data[i] ifd==0: break; ifd<32: self.name=self.name+'.' else: self.name=self.name+chr(d) i=i+1 self.querybytes=data[0:i+1] (self.type,self.classify)=struct.unpack('>HH',data[i+1:i+5]) self.len=i+5 defgetbytes(self): returnself.querybytes+struct.pack('>HH',self.type,self.classify)
#DNSAnswerRRS #thisclassisalsocanbeuseasAuthorityRRSorAdditionalRRS classSinDNSAnswer: def__init__(self,ip): self.name=49164 self.type=1 self.classify=1 self.timetolive=190 self.datalength=4 self.ip=ip defgetbytes(self): 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])) returnres
#DNSframe #mustinitializedbyaDNSqueryframe classSinDNSFrame: def__init__(self,data): (self.id,self.flags,self.quests,self.answers,self.author,self.addition)=struct.unpack('>HHHHHH',data[0:12]) self.query=SinDNSQuery(data[12:]) defgetname(self): returnself.query.name defsetip(self,ip): self.answer=SinDNSAnswer(ip) self.answers=1 self.flags=33152 defgetbytes(self): res=struct.pack('>HHHHHH',self.id,self.flags,self.quests,self.answers,self.author,self.addition) res=res+self.query.getbytes() ifself.answers!=0: res=res+self.answer.getbytes() returnres #AUDPHandlertohandleDNSquery classSinDNSUDPHandler(socketserver.BaseRequestHandler): defhandle(self): data=self.request[0].strip() dns=SinDNSFrame(data) socket=self.request[1] namemap=SinDNSServer.namemap if(dns.query.type==1): #IfthisisqueryaArecord,thenresponseit name=dns.getname(); ifnamemap.__contains__(name): #Ifhaverecord,responseit dns.setip(namemap[name]) socket.sendto(dns.getbytes(),self.client_address) elifnamemap.__contains__('*'): #Responsedefaultaddress dns.setip(namemap['*']) socket.sendto(dns.getbytes(),self.client_address) else: #ignoreit socket.sendto(data,self.client_address) else: #IfthisisnotqueryaArecord,ignoreit socket.sendto(data,self.client_address)
#DNSServer #ItonlysupportArecordquery #userit,UcancreateasimpleDNSserver classSinDNSServer: def__init__(self,port=53): SinDNSServer.namemap={} self.port=port defaddname(self,name,ip): SinDNSServer.namemap[name]=ip defstart(self): HOST,PORT="0.0.0.0",self.port server=socketserver.UDPServer((HOST,PORT),SinDNSUDPHandler) server.serve_forever()
#Now,testit if__name__=="__main__": sev=SinDNSServer() sev.addname('www.aa.com','192.168.0.1') #addaArecord sev.addname('www.bb.com','192.168.0.2') #addaArecord sev.addname('*','0.0.0.0')#defaultaddress sev.start()#startDNSserver
#Now,Ucanuse"nslookup"commandtotestit #Suchas"nslookupwww.aa.com"