小菜鸡第一次拿python做作业
实现了一个简易的local dns server
使用迭代的方法
毫无注释,只对本部分网址有效
基于UDP
需要使用dig测试
- 迭代原理图:
- DNS 信息结构:
localDNS.py
# -*- coding: UTF-8 -*-import socket
import dnslibdef local_DNS_Server():# List of records about the domain name and IPv4 address of Root DNS servers.root_DNS_servers=[["A.root-servers.net",'198.41.0.4'],["B.root-servers.net",'192.228.79.201'],["C.root-servers.net",'192.33.4.12'],["D.root-servers.net",'128.8.10.90'],["E.root-servers.net",'192.203.230.10'],["F.root-servers.net",'192.5.5.241'],["G.root-servers.net",'192.112.36.4'],["H.root-servers.net",'128.63.2.53'],["I.root-servers.net",'192.36.148.17'],["J.root-servers.net",'192.58.128.30'],["K.root-servers.net",'193.0.14.129'],["L.root-servers.net",'198.32.64.12'],["M.root-servers.net",'202.12.27.33'],]print("========================================================================\nList of root dns servers:")for root in root_DNS_servers:print(root[0] + " " + root[1])print("===========================================")# Maintain a cache here.# cache[qname]=responseMessagecache = {}while True: # Keep the local dns server working.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)serverSocket.bind(('127.0.0.1', 12000))message, clientAddress = serverSocket.recvfrom(2048)# Parse DNS packet data and return DNSRecord instance.message_parse = dnslib.DNSRecord.parse(message)message_parse.header.set_rd(0)message = dnslib.DNSRecord.pack(message_parse)# Judge whether the query is already in the cache.if message_parse.q.qname in cache:responseMessage = cache[message_parse.q.qname]serverSocket.sendto(responseMessage, clientAddress)else:# Split the qname into ['com.', 'baidu.', 'www.']qname = str(message_parse.q.qname);qnamelist = qname.split(".")qnamelist.pop(len(qnamelist) - 1) # ['www', 'baidu.', 'com']for i in range(0, len(qnamelist)):qnamelist[i] = qnamelist[i] + "."qnamelist.reverse() # ['com.', 'baidu.', 'www.']# Select a root server from 13 root_DNS_servers randomly to begin the iteration.# I select ["A.root-servers.net",'198.41.0.4'] here.a = "A.root-servers.net"domain = ""# Do iterations, take www.baidu.com as an example:# 1. domain='com.' 2. domain='baidu.com' 3.domain='www.baidu.com'for i in qnamelist:domain = i + domainr = dnslib.DNSRecord.question(domain, qtype="NS")rr = r.send(a)res = dnslib.DNSRecord.parse(rr)# print(res)# print("==============================================")a = res.auth[0].rdata.__str__()domain = str(res.rr[0].rdata)r = dnslib.DNSRecord.question(domain, qtype="A")rr = r.send(a)res1 = dnslib.DNSRecord.parse(rr)# print(res1)# Get Answer list, for example and then add these answers to response packet:# ;; ANSWER SECTION:# www.a.shifen.com. 300 IN A 14.215.177.38# www.a.shifen.com. 300 IN A 14.215.177.39rrlist = res1.rrfor i in rrlist:res.rr.append(i)# Modify some parameters of response packetsres.header.id = message_parse.header.id # Set the id of response packet same with query packet. (dig)res.header.ra = 1res.q.qtype = 1 # Type"A"# Clear the AUTHORITY SECTION and ADDITIONAL SECTION to make the response packet simpler.res.auth = []res.ar = []print("===========================================\n response packet:")print(res)# Send the response packet back to the terminal.serverSocket.sendto(res.pack(), clientAddress)# Add the response packet into the cache.cache[message_parse.q.qname] = res.pack()if __name__ == '__main__':# dig @127.0.0.1 -p 12000 www.baidu.com# dig @127.0.0.1 -p 12000 www.sohu.comtry:local_DNS_Server()except KeyboardInterrupt:pass
-
测试:
-
pychram 结果:
-
-
写在最后:
花这么大力气来写,dns.resolver 他不香吗?