HTML5技术

计算机网络——DNS协议的学习与实现 - 学数学的程序猿(2)

字号+ 作者:H5之家 来源:H5之家 2017-04-16 10:00 我要评论( )

import threading import socket import socketserver class Handler(socketserver.BaseRequestHandler): def handle( self ):request_data = self .request[ 0 ] # 将请求转发到 114 DNS redirect_socket = socket

import threading import socket import socketserver class Handler(socketserver.BaseRequestHandler): def handle(self): request_data = self.request[0] # 将请求转发到 114 DNS redirect_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) redirect_socket.sendto(request_data, ('114.114.114.114', 53)) response_data, address = redirect_socket.recvfrom(1024) # 将114响应响应给客户 client_socket = self.request[1] client_socket.sendto(response_data, self.client_address) class Server(socketserver.ThreadingMixIn, socketserver.UDPServer): : # 一下ip需换成自己电脑的ip server = Server(('172.16.42.254', 53), Handler) with server: server_thread = threading.Thread(target=server.serve_forever) server_thread.daemon = True server_thread.start() print('The DNS server is running at 172.16.42.254...') server_thread.join()

现在我们的DNS服务器就可以进行转发工作了。运行以上程序(需root权限),然后用nsloop命令,向我们的服务器发送DNS请求,一切OK:

$ nslookup baidu.com 172.16.42.254 Server: 172.16.42.254 Address: 172.16.42.254#53 Non-authoritative answer: Name: baidu.com Address: 123.125.114.144 Name: baidu.com Address: 180.149.132.47 Name: baidu.com Address: 111.13.101.208 Name: baidu.com Address: 220.181.57.217 4.2 缓存功能

如果仅仅做一下代理转发,那也太无聊了。现在我们再加上缓存功能,即它能够将其他DNS服务器的响应结果缓存起来。当收到请求时,若请求主机号在缓存中,且没有过期,则直接响应缓存结果;否则进行上一功能中的操作。这一功能的关键在于对DNS消息的解析,代码如下:

class Message: (, authority): self.header = header self.question = question self.answer = answer self.authority = authority self.additional = additional @classmethod def from_bytes(cls, data): scanner = Scanner(data) # 读取header header = dict() header['ID'] = scanner.next_bytes(2) header['QR'] = scanner.next_bits(1) header['OPCODE'] = scanner.next_bits(4) header['AA'] = scanner.next_bits(1) header['TC'] = scanner.next_bits(1) header['RD'] = scanner.next_bits(1) header['RA'] = scanner.next_bits(1) header['Z'] = scanner.next_bits(3) header['RCODE'] = scanner.next_bits(4) header['QDCOUNT'] = scanner.next_bytes(2) header['ANCOUNT'] = scanner.next_bytes(2) header['NSCOUNT'] = scanner.next_bytes(2) header['ARCOUNT'] = scanner.next_bytes(2) print('header:', header) # 读取question questions = list() for _ in range(header['QDCOUNT']): question = dict() question['QNAME'] = scanner.next_bytes_until(lambda current, _: current == 0) scanner.next_bytes(1) # 跳过0 question['QTYPE'] = scanner.next_bytes(2) question['QCLASS'] = scanner.next_bytes(2) questions.append(question) print('questions:', questions) message = Message(header) # 读取answer、authority、additional rrs = list() for i in range(header['ANCOUNT'] + header['NSCOUNT'] + header['ARCOUNT']): rr = dict() rr['NAME'] = cls.handle_compression(scanner) rr['TYPE'] = scanner.next_bytes(2) rr['CLASS'] = scanner.next_bytes(2) rr['TTL'] = scanner.next_bytes(4) rr['RDLENGTH'] = scanner.next_bytes(2) : # A记录 r_data = scanner.next_bytes(rr['RDLENGTH'], False) rr[) y, map(lambda num: str(num), r_data)) rr['TYPE'] == 5: # NS与CNAME记录 rr['RDATA'] = cls.handle_compression(scanner, rr['RDLENGTH']) rrs.append(rr) answer, authority, additional = list(), list(), list() for i, rr in enumerate(rrs): if i < header['ANCOUNT']: answer.append(rr) elif i < header['ANCOUNT'] + header['NSCOUNT']: authority.append(rr) else: additional.append(rr) print('answer:', answer) print('authority:', authority) print('additional:', additional) return message ("inf")): byte = scanner.next_bytes() : # a pointer pointer ) + scanner.next_bytes() return cls.handle_compression(Scanner(scanner.data, pointer)) data current offset > length) : # a sequence of labels ending in a zero octet scanner.next_bytes() return data # a sequence of labels ending with a pointer result cls.handle_compression(Scanner(scanner.data, *scanner.position())) scanner.next_bytes(2) # 跳过2个字节的指针 return result

其中用到了一个自定义的Scanner类,用来帮助我们从bytes中按字节或位读取数据,其定义如下:

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • ASP.NET Core MVC 源码学习:详解 Action 的激活 - Savorboard

    ASP.NET Core MVC 源码学习:详解 Action 的激活 - Savorboard

    2017-04-14 13:04

  • ASP.NET Core MVC 源码学习:详解 Action 的匹配 - Savorboard

    ASP.NET Core MVC 源码学习:详解 Action 的匹配 - Savorboard

    2017-03-30 18:02

  • 大数据云计算学习路线图(纯属个人看法和观点) - 别先生

    大数据云计算学习路线图(纯属个人看法和观点) - 别先生

    2017-03-30 13:00

  • 2年前端学习历程,与找不到工作的悲愤与吐槽!(100%真实经历,看博主怎么一步步走向失业) - 蒋启钲

    2年前端学习历程,与找不到工作的悲愤与吐槽!(100%真实经历,看博

    2017-03-29 11:00

网友点评