小菜鸡第一次拿python做作业
实现了一个简易的local dns server
使用迭代的方法
毫无注释,只对本部分网址有效
基于UDP
需要使用dig测试
- 迭代原理图:
- DNS 信息结构:
localDNS.py
# -*- coding: UTF-8 -*-
import socket
import dnslib
def 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]=responseMessage
cache = {}
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 + domain
r = 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.39
rrlist = res1.rr
for i in rrlist:
res.rr.append(i)
# Modify some parameters of response packets
res.header.id = message_parse.header.id # Set the id of response packet same with query packet. (dig)
res.header.ra = 1
res.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.com
try:
local_DNS_Server()
except KeyboardInterrupt:
pass
-
测试:
-
pychram 结果:
-
-
写在最后:
花这么大力气来写,dns.resolver 他不香吗?