Because of a sudden evil idea, I want to build a DNS server on my Android tablet, because I have sl4a and Python's interpreter installed on the tablet before, and I want to continue to learn python, so I intend to implement it in Python.
Looking at Google, the Python implementation of DNS, did not find the answer I wanted, so I decided to implement it.
Now the implementation is not profound, only to be able to a record query for a simple match and reply.
The implementation code is as follows:
Copy Code code as follows:
'''
Created on 2012-10-15
@author: Robintang
'''
Import Socketserver
Import struct
# DNS Query
Class 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]
(Self.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 are also can be to use as authority RRS or Additional RRS
class Sindnsanswer:
; def __init__ (self, IP):
self.name = 49164
self.type = 1
self.classify = 1
self.timetolive = 190
Self.datalength = 4
self.ip = IP
def GetBytes (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 ])
return res
# DNS Frame
# must initialized by a DNS query frame
Class Sindnsframe:
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:])
def getname (self):
Return Self.query.name
Def setip (self, IP):
Self.answer = Sindnsanswer (IP)
Self.answers = 1
Self.flags = 33152
def getbytes (self):
res = struct.pack (' >hhhhhh ', self.id, Self.flags, Self.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 query
Class Sindnsudphandler (Socketserver. Baserequesthandler):
def handle (self):
data = Self.request[0].strip ()
DNS = Sindnsframe (data)
Socket = Self.request[1]
Namemap = Sindnsserver.namemap
if (dns.query.type==1):
# If This are query a a record, 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__ (' * '):
# Response Default Address
Dns.setip (namemap[' * '])
Socket.sendto (Dns.getbytes (), self.client_address)
Else
# Ignore it
Socket.sendto (data, self.client_address)
Else
# If This isn't query a a record, ignore it
Socket.sendto (data, self.client_address)
# DNS Server
# It only support a record query
# user It, U can create A simple DNS server
class sindnsserver:< br> def __init__ (self, port=53):
Sindnsserver.namemap = {}
Self.port = Port
def AddName (self, Name, IP):
sindnsserver.namemap[name] = IP
def start (self):
HOST, PORT = "0.0.0.0", Self.port
Server = Socketserver. Udpserver (HOST, PORT, Sindnsudphandler)
server.serve_forever ()
# Now, test it
if __name__ = = "__main__":
SEv = Sindnsserver ()
Sev.addname (' www.aa.com ', ' 192.168.0.1 ') # Add a record
Sev.addname (' www.bb.com ', ' 192.168.0.2 ') # Add a record
Sev.addname (' * ', ' 0.0.0.0 ') # Default address
Sev.start () # Start DNS server
# Now, U can use ' nslookup ' command to test it
# Such as "nslookup www.aa.com"