I need to write a paper on how DNS works and build a small but functional DNS server in python.
I have a simple UDP socket server that opens a thread when a packet is received like this:
while 1:
try:
stream, addr = serversocket.recvfrom(buffr)
threading.Thread(target=handler, args=(stream, addr, threading.activeCount(),)).start()
except:
exc_type, exc_value, exc_traceback = sys.exc_info()
except_catch(exc_type.__name__, exc_value, exc_traceback, threading.current_thread().name)
The handler function simply tries to find the record requested in memory and if it does not it will execute another function that runs a dns query on another server to fetch the record if he does not have it. This is somewhat of a fail-safe and where my problem is.
def dnsrn(ip, type):
try:
mkr = dns.resolver.Resolver()
mkr.nameservers = ['192.168.0.1']
res = mkr.query(ip, type)
for rdata in res:
return rdata.address # this works for A records
# to do for other types of records
except:
exc_type, exc_value, exc_traceback = sys.exc_info()
except_catch(exc_type.__name__, exc_value, exc_traceback, threading.current_thread().name)
I have not yet finished it as you can see but I already have a problem.
Sometimes, this function will hand and the thread will never finish without it giving any error what so ever in the error log.
I have tested and the error log should capture all errors thrown by the child.
I have a simple client that is programmed to send a random request out a lit of presets every set time and there seems to be no pattern to when the child hangs.
After about 24 hours of testing I’m left with about 1-3 zombie threads.
In case you are wondering this is what the exception function looks like:
def except_catch(type, value, track, thread=None):
if type != "SystemExit":
import traceback
rawreport = traceback.format_exception(type, value, track)
report = "\n" . join(rawreport)
errorlog = open(error_log_path + "/errors.log", "a")
if thread != None:
errorlog.write("Exception in thread: " + thread + "\n\n")
errorlog.write(("%s\n" + "-" * 30 + "\n\n") % report)
errorlog.close()
sys.excepthook = except_catch
I would check the RFC as this is the exact specification of the protocol. The problem with DNS is, that there is more than one RFC. For a simple start, I would check RFC 1035 which contains the basics. If you need advanced functionality, check the other related RFCs.