本地DNS服务器

小菜鸡第一次拿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 他不香吗?

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值