欢迎光临散文网 会员登陆 & 注册

007. 从零开始搭建 DNS 服务器——入门篇

2023-01-19 13:34 作者:姚千山  | 我要投稿

前言

简单来说,域名解析协议(DNS,Domain Name System)是一个应用层协议可以将域名和 IP 地址相互映射,使人更方便地访问互联网,而不用去记住复杂的 IP 地址。

DNS 协议建立在 UDP 或 TCP 协议之上,默认使用 53 号端口。客户端默认通过 UDP 协议进行通讯,本文就以 UDP 协议进行讲解,不考虑报文长度超过了 512 字节使用 TCP 协议的情况。

了解了 DNS 的基本原理,我们就可以写一个最简单的 DNS 服务器了。在入门阶段,这个简单的 DNS 服务器,仅具有最基本的“代理”功能。

即我们的 DNS 服务器在接到客户端发来的 DNS 请求后,直接将请求转发到其他可用的 DNS服务器(如114.114.114.114)上,而不对报文做任何修改。待 DNS 响应后,直接将响应结果返回给 DNS 客户端。

实现

DNS 服务器需要 bind 到 53 端口,而且采用 UDP 协议。先导入 Python 标准库:socket,用 socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 走的是 UDP 协议。

import socket

if __name__ == '__main__':
    # 建立一个套接字对象(UDP),负责接受 DNS 报文
    sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 绑定到 53 端口
    sk.bind(('0.0.0.0', 53))
    print('dns server is started')

在 DNS 服务器运行的逻辑中,使用 While True 循环,一直接受来自客户端的请求。接收到的数据是一个两元组,解包得到报文消息和客户端 IP 地址。

while True:
    message, addr = sk.recvfrom(1024)

新建另一个 socket 对象,直接将报文转发给 114 DNS。

# 将请求转发到 114 DNS
redirect_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
redirect_socket.sendto(message, ('114.114.114.114', 53))

最后将响应数据返回给客户端,一次 DNS 请求处理完成。

response_data, _ = redirect_socket.recvfrom(1024)
# 将114响应响应给客户
sk.sendto(response_data, addr)

完整代码如下:

# coding:utf-8
# @Author:Gscsd
import socket

if __name__ == '__main__':
    # 建立一个套接字对象(UDP),负责接受 DNS 报文
    sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 绑定到 53 端口
    sk.bind(('0.0.0.0', 53))
    print('dns server is started')
    while True:
        message, addr = sk.recvfrom(1024)
        # 将请求转发到 114 DNS
        redirect_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        redirect_socket.sendto(message, ('114.114.114.114', 53))
        response_data, _ = redirect_socket.recvfrom(1024)
        # 将114响应响应给客户
        sk.sendto(response_data, addr)

总结

这样,我们就实现了一个极其简单的 DNS 服务器(或者说是DNS 代理服务器)。审视这十来行代码,还是有很多不足之处:

  1. 单纯转发数据,徒劳无功,不如直接请求 114 DNS;

  2. 无法自定义 IP 与域名映射,即自定义记录;

  3. 没有缓存机制,每次请求都要向 114 DNS 请求;

  4. 没有处理客户端请求的错误,如请求超时等;

  5. 只能处理单个请求,没有并发处理能力。

这些不足将会在以后的文章中加以改进,敬请关注。

延伸阅读

  1. 超详细 DNS 协议解析:https://zhuanlan.zhihu.com/p/351059293

  2. socket --- 底层网络接口 — Python 3.11.1 文档:https://docs.python.org/zh-cn/3/library/socket.html

  3. DNS协议:https://www.jianshu.com/p/915de89d070e


007. 从零开始搭建 DNS 服务器——入门篇的评论 (共 条)

分享到微博请遵守国家法律