Python3 简易DNS服务器实现
使用Python3开发一个简单的DNS服务器,支持配置资源记录(RR),并能通过dig
命令进行查询。
让自己理解DNS原理
实现方案
我们将使用socketserver
和dnslib
库来构建这个DNS服务器。dnslib
库能帮助我们处理DNS协议的复杂细节。
1. 安装依赖
首先确保安装了dnslib
库:
pip install dnslib
2. DNS服务器实现代码
#!/usr/bin/env python3
import socketserver
from dnslib import DNSRecord, DNSHeader, QTYPE, RR, A, AAAA, CNAME, TXT
from dnslib.server import DNSServer, BaseResolverclass SimpleResolver(BaseResolver):"""自定义DNS解析器,包含我们配置的资源记录"""def __init__(self):# 初始化资源记录字典self.records = {# A记录 (域名 -> IPv4)'example.com.': [RR('example.com.', QTYPE.A, rdata=A('93.184.216.34'), ttl=60),RR('example.com.', QTYPE.A, rdata=A('93.184.216.35'), ttl=60)],# AAAA记录 (域名 -> IPv6)'ipv6.example.com.': [RR('ipv6.example.com.', QTYPE.AAAA, rdata=AAAA('2606:2800:220:1:248:1893:25c8:1946'), ttl=60)],# CNAME记录 (别名)'www.example.com.': [RR('www.example.com.', QTYPE.CNAME, rdata=CNAME('example.com.'), ttl=60)],# TXT记录'txt.example.com.': [RR('txt.example.com.', QTYPE.TXT, rdata=TXT('This is a test TXT record'), ttl=60)]}def resolve(self, request, handler):"""处理DNS查询请求"""reply = request.reply()qname = request.q.qnameqtype = request.q.qtype# 记录查询日志print(f"Received query: {qname} (Type: {QTYPE[qtype]})")# 检查是否有匹配的记录if str(qname) in self.records:for record in self.records[str(qname)]:if record.rtype == qtype or qtype == QTYPE.ANY:reply.add_answer(record)return replydef main():"""启动DNS服务器"""resolver = SimpleResolver()# 创建DNS服务器,监听UDP 53端口server = DNSServer(resolver,port=53,address="0.0.0.0", # 监听所有接口tcp=False # 仅使用UDP)print("Starting DNS server on port 53...")try:server.start()except KeyboardInterrupt:server.stop()print("\nDNS server stopped")if __name__ == '__main__':main()
3. 运行服务器
由于DNS服务需要使用53端口,在Linux/macOS上需要以root权限运行:
sudo python3 dns_server.py
4. 使用dig测试
打开另一个终端窗口,使用dig
命令测试:
# 查询A记录
dig @127.0.0.1 example.com# 输出中有
# example.com. 60 IN A 93.184.216.34
# example.com. 60 IN A 93.184.216.35# 查询AAAA记录
dig @127.0.0.1 -t AAAA ipv6.example.com# 查询CNAME记录
dig @127.0.0.1 -t CNAME www.example.com# 查询TXT记录
dig @127.0.0.1 -t TXT txt.example.com
进阶功能
1. 从配置文件加载资源记录
我们可以改进代码,从JSON文件加载资源记录:
import jsonclass ConfigurableResolver(BaseResolver):def __init__(self, config_file='dns_config.json'):self.records = {}self.load_config(config_file)def load_config(self, config_file):with open(config_file) as f:config = json.load(f)for domain, records in config.items():self.records[domain] = []for record in records:rtype = record['type'].upper()if rtype == 'A':self.records[domain].append(RR(domain, QTYPE.A, rdata=A(record['value']), ttl=record.get('ttl', 60)))elif rtype == 'AAAA':self.records[domain].append(RR(domain, QTYPE.AAAA, rdata=AAAA(record['value']), ttl=record.get('ttl', 60)))elif rtype == 'CNAME':self.records[domain].append(RR(domain, QTYPE.CNAME, rdata=CNAME(record['value']), ttl=record.get('ttl', 60)))elif rtype == 'TXT':self.records[domain].append(RR(domain, QTYPE.TXT, rdata=TXT(record['value']), ttl=record.get('ttl', 60)))
示例配置文件dns_config.json
:
{"example.com.": [{"type": "A", "value": "93.184.216.34", "ttl": 300},{"type": "A", "value": "93.184.216.35", "ttl": 300}],"ipv6.example.com.": [{"type": "AAAA", "value": "2606:2800:220:1:248:1893:25c8:1946"}],"www.example.com.": [{"type": "CNAME", "value": "example.com."}],"txt.example.com.": [{"type": "TXT", "value": "This is a test TXT record"}]
}
2. 添加日志记录
我们可以添加更详细的日志记录:
import logging# 配置日志
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s - %(message)s',handlers=[logging.FileHandler('dns_server.log'),logging.StreamHandler()]
)class LoggingResolver(BaseResolver):def resolve(self, request, handler):client_ip = handler.client_address[0]qname = request.q.qnameqtype = QTYPE[request.q.qtype]logging.info(f"Query from {client_ip}: {qname} (Type: {qtype})")reply = super().resolve(request, handler)if reply.rr:for answer in reply.rr:logging.info(f"Responded with: {answer}")else:logging.warning(f"No records found for {qname} (Type: {qtype})")return reply
注意事项
-
端口权限:DNS服务器需要使用53端口,在Unix-like系统上需要root权限。
-
防火墙设置:确保防火墙允许UDP 53端口的传入连接。
-
系统DNS缓存:测试时可能需要清除本地DNS缓存:
- macOS:
sudo killall -HUP mDNSResponder
- Linux: 取决于发行版,可能是
systemd-resolve --flush-caches
- macOS:
-
性能考虑:这个实现是单线程的,对于高负载环境,可以考虑使用多线程或异步IO。
-
安全性:生产环境应考虑添加DNS查询限制、防止DNS放大攻击等安全措施。
这个实现提供了基本的DNS服务器功能,你可以根据需要扩展更多记录类型(MX, NS, SOA等)或添加更复杂的逻辑。
相关文章:
Python3 简易DNS服务器实现
使用Python3开发一个简单的DNS服务器,支持配置资源记录(RR),并能通过dig命令进行查询。 让自己理解DNS原理 实现方案 我们将使用socketserver和dnslib库来构建这个DNS服务器。dnslib库能帮助我们处理DNS协议的复杂细节。 1. 安装依赖 首先确保安装了d…...

【Win32 API】 lstrcmpA()
作用 比较两个字符字符串(比较区分大小写)。 lstrcmp 函数通过从第一个字符开始检查,若相等,则检查下一个,直到找到不相等或到达字符串的末尾。 函数 int lstrcmpA(LPCSTR lpString1, LPCSTR lpString2); 参数 lpStr…...

(C语言)超市管理系统 (正式版)(指针)(数据结构)(清屏操作)(文件读写)
目录 前言: 源代码: product.h product.c fileio.h fileio.c main.c 代码解析: 一、程序结构概述 二、product.c 函数详解 1. 初始化商品列表 Init_products 2. 添加商品 add_product 3. 显示商品 display_products 4. 修改商品 mo…...

NAT转换和ICMP
NAT nat原理示意 nat实现 ICMP ICMP支持主机或路由器: 差错或异常报告网络探寻 2类icmp报文: 差错报告报文(5种) 目的不可达源抑制--拥塞控制超时&超期--TTL超时参数问题--问题报文丢弃重定向--不应该由这个路由器转发&a…...
Executors类详解
Executors类详解 Executors 是Java中用于快速创建线程池的工具类,提供了一系列工厂方法,简化了 ThreadPoolExecutor 和 ScheduledThreadPoolExecutor 的配置。以下是其核心方法、实现原理及使用注意事项: 1. 常用线程池工厂方法 (1) newFixedThreadPool 作用:创建固定大小…...

【专利信息服务平台-注册/登录安全分析报告】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…...

BUUCTF——web刷题第一页题解
共31题,admin那题没有,因为环境问题,我做的非常卡 目录 极客大挑战 2019]Havefun [HCTF 2018]WarmU [ACTF2020 新生赛]Include [ACTF2020 新生赛]Exec [GXYCTF2019]Ping Ping Ping [SUCTF 2019]EasySQL [极客大挑战 2019]LoveSQL [极…...

哪个品牌的智能对讲机好用?推荐1款,能扛事更智能
在专业通信领域,智能对讲机早已突破传统设备的局限,成为集通信、调度、数据传输于一体的智能化终端。面对复杂多变的作业环境,用户对设备的稳定性、通信效率和智能化水平提出了更高要求。但是,市面上产品同质化严重,部…...

【Win32 API】 lstrcpyA()
作用 将字符串复制到指定的字符串缓冲区。 函数 LPSTR lstrcpyA(LPSTR lpString1, LPCSTR lpString2); 参数 lpString1 类型:LPTSTR 一个缓冲区,用于接收由 lpString2 参数指向的字符串的内容。 缓冲区必须足够大才能包含字符串,包括终止…...

Vue3——Watch侦听器
目录 手动指定监听对象 侦听ref对象 侦听ref对象中的某个属性 reactive写法 watchEffect 自动侦听 多源侦听 一次性侦听器 watch 是⼀个⽤于观察和响应Vue响应式系统中数据变化的⽅法。它允许你指定⼀个数据源(可以是 响应式引⽤、计算属性、组件的属性等…...

Go的单测gomock及覆盖率命令
安装gomock: go get github.com/golang/mock/gomockgo get github.com/golang/mock/mockgen 使用 mockgen 生成 mock 代码: 参考 mockgen -sourceservice/user.go -destinationservice/mocks/mock_user_service.go -packagemocks go test -coverprofilecoverage.out…...

Leetcode209做题笔记
力扣209 题目分析:想象一个窗口遍历着这个数组,不断扩大右边界,让r。往窗口中添加数字: 此时我们找到了这个窗口,它的和满足了大于等于target的条件,题目让我求最短的,那么我们就尝试来缩短它&…...

Suna: 开源多面手 AI 代理
GitHub:GitHub - kortix-ai/suna: Suna - Open Source Generalist AI Agent 更多AI开源软件:发现分享好用的AI工具、AI开源软件、AI模型、AI变现 - 小众AI Suna 是一个完全开源的 AI 助手,可帮助您轻松完成实际任务。通过自然对话,…...

25-05-16计算机网络学习笔记Day1
深入剖析计算机网络:今日学习笔记总结 本系列博客源自作者在大二期末复习计算机网络时所记录笔记,看的视频资料是B站湖科大教书匠的计算机网络微课堂,每篇博客结尾附书写笔记(字丑见谅哈哈) 视频链接地址 一、计算机网络基础概念 …...

12 web 自动化之基于关键字+数据驱动-反射自动化框架搭建
文章目录 一、如何实现一条用例,实现覆盖所有用例的测试1、结合数据驱动:编辑一条用例,外部导入数据实现循环测试2、用例体:实现不同用例的操作步骤对应的断言 二、实战1、项目路径总览2、common 文件夹下的代码文件3、keywords 文…...

动态IP赋能业务增效:技术解构与实战应用指南
在数字化转型加速的今天,IP地址作为网络通信的基础设施,其技术特性正深刻影响着企业业务架构的效率与安全性。动态IP(Dynamic IP)作为互联网资源分配的核心机制,早已突破传统认知中的"临时地址"定位…...

【Java ee初阶】http(1)
HTTP 全称为“超文本传输协议”,由名字可知,这是一个基于文本格式的协议,而TCP,UDP,以太网,IP...都是基于二进制格式的协议。 如何区别该协议是基于哪种格式的协议? 形如这种协议格式…...
OkHttp用法-Java调用http服务
特点:高性能,支持异步请求,连接池优化 官方文档:提供快速入门指南和高级功能(如拦截器、连接池)的详细说明,GitHub仓库包含丰富示例。 社区资源:中文教程丰富,GitHub高…...

day18-数据结构引言
一、 概述 数据结构:相互之间存在一种或多种特定关系的数据元素的集合。 1.1 特定关系: 1. 逻辑结构 2.物理结构(在内存当中的存储关系) 逻辑结构物理结构集合,所有数据在同一个集合中,关系平等顺…...

我开源了一个免费在线工具!UIED Tools
UIED Tools - 免费在线工具集合 最近更新:修改了文档说明,优化了项目结构介绍 这是设计师转开发的第一个开源项目,bug和代码规范可能有些欠缺。 这是一个功能丰富的免费在线工具集合网站,集成了多种实用工具,包括 AI …...

什么时候可以开始学习深度学习?
咱们先来聊聊机器学习和深度学习的关系~ 这个问题其实挺常见的,之前我也跟不少同事、同学聊过。最近有好几个同学也聊过。 简单说,深度学习是机器学习的一个子集,两者不是并列关系,而是“包含”关系。 你可以这么理解ÿ…...

初学python的我开始Leetcode题8-5
提示:100道LeetCode热题-8-5主要是二叉树相关,包括三题:路径总和 III、二叉树的最近公共祖先、二叉树中的最大路径和。由于初学,所以我的代码部分仅供参考。 前言 二叉树完结撒花~ 下一次的图论会是一些有趣的应用案例~ 提示&am…...

构建RAG混合开发---PythonAI+JavaEE+Vue.js前端的实践
写在前文:之所以设计这一套流程,是因为 Python在前沿的科技前沿的生态要比Java好,而Java在企业级应用层开发比较活跃; 毕竟许多企业的后端服务、应用程序均采用Java开发,涵盖权限管理、后台应用、缓存机制、中间件集成…...

08.webgl_buffergeometry_attributes_none ,three官方示例+编辑器+AI快速学习
本实例主要讲解内容 这个Three.js示例展示了无属性几何体渲染技术,通过WebGL 2的gl_VertexID特性和伪随机数生成算法,在着色器中动态计算顶点位置和颜色,而不需要在CPU端预先定义几何体数据。 核心技术包括: WebGL 2的顶点ID特…...

26考研 | 王道 | 计算机组成原理 | 一、计算机系统概述
26考研 | 王道 | 计算机组成原理 | 一、计算机系统概述 文章目录 26考研 | 王道 | 计算机组成原理 | 一、计算机系统概述1.1 计算机的发展1.2 计算机硬件和软件1.2.1 计算机硬件的基本组成1.2.2 各个硬件的工作原理1.2.3 计算机软件1.2.4 计算机系统的层次结构1.2.5 计算机系统…...
转换算子介绍
### 转换算子的定义与用法 #### 定义 转换算子(Transformation Operators)是指用于处理分布式数据集的操作符,在大数据框架中广泛使用,例如Apache Flink和Apache Spark。这些操作符允许开发者对数据集执行各种变换操作࿰…...
Android学习总结之Glide自定义三级缓存(实战篇)
一、为什么需要三级缓存 内存缓存(Memory Cache) 内存缓存旨在快速显示刚浏览过的图片,例如在滑动列表时来回切换的图片。在 Glide 中,内存缓存使用 LruCache 算法(最近最少使用),能自动清理长…...
单片机开发软件
目录 纯编码 vscode Ardunio Keil 1. 集成化开发环境(IDE) 2. 多架构芯片支持 3. 高效的代码生成与优化 4. 强大的调试与仿真功能 5. 丰富的库函数与生态系统 6. 教育与企业级适用性 典型应用场景 半编码半图形化 STM32CUBEIED 1. 图形化配置…...

LeetCode100.2 字母异位词分组
观察题目,需要把strs中的元素按照字母进行归类,一个朴素的思路是:遍历strs,对每个元素排序后插入哈希表中,随后再遍历一遍表将其转化为vector<vector<string>>。 class Solution { public:vector<vect…...
深入了解 Stable Diffusion:AI 图像生成的奥秘
一、引言 AI 艺术与图像生成技术的兴起改变了我们创造和体验视觉内容的方式。在过去几年里,深度学习模型已经能够创造出令人惊叹的艺术作品,这些作品不仅模仿了人类艺术家的风格,甚至还能创造出前所未有的新风格。在这个领域,Sta…...