Python写的一个简单DNS服务器实例


Posted in Python onJune 04, 2014

因为突然有个邪恶的想法,想在自己的Android平板上面搭建一个DNS服务器,因为平板上之前安装过SL4A和Python的解释器,也想继续学学Python因此,就打算用Python实现了。

在Google上面找了一下,Python实现的DNS,没找到我所希望的答案,因此就决定自己来实现了。

现在所实现的没什么高深的,只是能够对A记录查询进行简单的匹配和回复。

实现的代码如下:

'''
Created on 2012-10-15
@author: RobinTang
'''
import socketserver
import struct
# DNS Query
class SinDNSQuery:
    def __init__(self, data):
        i = 1
        self.name = ''
        while True:
            d = data[i]
            if d == 0:
                break;
            if d < 32:
                self.name = self.name + '.'
            else:
                self.name = self.name + chr(d)
            i = i + 1
        self.querybytes = data[0:i + 1]
        (self.type, self.classify) = struct.unpack('>HH', data[i + 1:i + 5])
        self.len = i + 5
    def getbytes(self):
        return self.querybytes + struct.pack('>HH', self.type, self.classify)
# DNS Answer RRS
# this class is also can be use as Authority RRS or Additional RRS 
class SinDNSAnswer:
    def __init__(self, ip):
        self.name = 49164
        self.type = 1
        self.classify = 1
        self.timetolive = 190
        self.datalength = 4
        self.ip = ip
    def getbytes(self):
        res = struct.pack('>HHHLH', self.name, self.type, self.classify, self.timetolive, self.datalength)
        s = self.ip.split('.')
        res = res + struct.pack('BBBB', int(s[0]), int(s[1]), int(s[2]), int(s[3]))
        return res
# DNS frame
# must initialized by a DNS query frame
class SinDNSFrame:
    def __init__(self, data):
        (self.id, self.flags, self.quests, self.answers, self.author, self.addition) = struct.unpack('>HHHHHH', data[0:12])
        self.query = SinDNSQuery(data[12:])
    def getname(self):
        return self.query.name
    def setip(self, ip):
        self.answer = SinDNSAnswer(ip)
        self.answers = 1
        self.flags = 33152
    def getbytes(self):
        res = struct.pack('>HHHHHH', self.id, self.flags, self.quests, self.answers, self.author, self.addition)
        res = res + self.query.getbytes()
        if self.answers != 0:
            res = res + self.answer.getbytes()
        return res
# A UDPHandler to handle DNS query
class SinDNSUDPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data = self.request[0].strip()
        dns = SinDNSFrame(data)
        socket = self.request[1]
        namemap = SinDNSServer.namemap
        if(dns.query.type==1):
            # If this is query a A record, then response it
            name = dns.getname();
            if namemap.__contains__(name):
                # If have record, response it
                dns.setip(namemap[name])
                socket.sendto(dns.getbytes(), self.client_address)
            elif namemap.__contains__('*'):
                # Response default address
                dns.setip(namemap['*'])
                socket.sendto(dns.getbytes(), self.client_address)
            else:
                # ignore it
                socket.sendto(data, self.client_address)
        else:
            # If this is not query a A record, ignore it
            socket.sendto(data, self.client_address)
# DNS Server
# It only support A record query
# user it, U can create a simple DNS server
class SinDNSServer:
    def __init__(self, port=53):
        SinDNSServer.namemap = {}
        self.port = port
    def addname(self, name, ip):
        SinDNSServer.namemap[name] = ip
    def start(self):
        HOST, PORT = "0.0.0.0", self.port
        server = socketserver.UDPServer((HOST, PORT), SinDNSUDPHandler)
        server.serve_forever()
# Now, test it
if __name__ == "__main__":
    sev = SinDNSServer()
    sev.addname('www.aa.com', '192.168.0.1')    # add a A record
    sev.addname('www.bb.com', '192.168.0.2')    # add a A record
    sev.addname('*', '0.0.0.0') # default address
    sev.start() # start DNS server
# Now, U can use "nslookup" command to test it
# Such as "nslookup www.aa.com"
Python 相关文章推荐
学习python之编写简单简单连接数据库并执行查询操作
Feb 27 Python
使用python语言,比较两个字符串是否相同的实例
Jun 29 Python
python计算阶乘和的方法(1!+2!+3!+...+n!)
Feb 01 Python
基于django channel实现websocket的聊天室的方法示例
Apr 11 Python
PyQt5 多窗口连接实例
Jun 19 Python
python处理大日志文件
Jul 23 Python
python 列表、字典和集合的添加和删除操作
Dec 16 Python
python GUI库图形界面开发之PyQt5信号与槽基础使用方法与实例
Mar 06 Python
Django 设置admin后台表和App(应用)为中文名的操作方法
May 10 Python
Python安装Bs4的多种方法
Nov 28 Python
Python调用高德API实现批量地址转经纬度并写入表格的功能
Jan 12 Python
python pygame 愤怒的小鸟游戏示例代码
Feb 25 Python
python写的ARP攻击代码实例
Jun 04 #Python
python和C语言混合编程实例
Jun 04 #Python
python实现的一个p2p文件传输实例
Jun 04 #Python
python实现文件分组复制到不同目录的例子
Jun 04 #Python
python实现的udp协议Server和Client代码实例
Jun 04 #Python
Python实现同时兼容老版和新版Socket协议的一个简单WebSocket服务器
Jun 04 #Python
Python程序员鲜为人知但你应该知道的17个问题
Jun 04 #Python
You might like
DOTA2游戏同人动画《龙之血》导演接受采访
2021/03/05 欧美动漫
动态生成gif格式的图像要注意?
2006/10/09 PHP
PHP 采集程序原理分析篇
2010/03/05 PHP
超详细的php用户注册页面填写信息完整实例(附源码)
2015/11/17 PHP
映彩衣的js随笔(js图片切换效果)
2011/07/31 Javascript
JS判断字符串长度的5个方法(区分中文和英文)
2014/03/18 Javascript
javascript实现页面内关键词高亮显示代码
2014/04/03 Javascript
JavaScript charCodeAt方法入门实例(用于取得指定位置字符的Unicode编码)
2014/10/17 Javascript
小议JavaScript中Generator和Iterator的使用
2015/07/29 Javascript
学习jQuey中的return false
2015/12/18 Javascript
深入理解JS继承和原型链的问题
2016/12/17 Javascript
angularjs实现猜大小功能
2017/10/23 Javascript
JavaScript设计模式之建造者模式实例教程
2018/07/02 Javascript
Makefile/cmake/node-gyp中区分判断不同平台的方法
2018/12/18 Javascript
原生JS实现随机点名项目的实例代码
2019/04/30 Javascript
Vue项目环境搭建详细总结
2019/09/26 Javascript
vue pages 多入口项目 + chainWebpack 全局引用缩写说明
2020/09/21 Javascript
Vue实现菜单切换功能
2020/11/08 Javascript
[51:06]DOTA2-DPC中国联赛 正赛 Elephant vs Aster BO3 第二场 1月26日
2021/03/11 DOTA
更改Python命令行交互提示符的方法
2015/01/14 Python
Python中join和split用法实例
2015/04/14 Python
解决nohup重定向python输出到文件不成功的问题
2018/05/11 Python
python opencv人脸检测提取及保存方法
2018/08/03 Python
python如何生成各种随机分布图
2018/08/27 Python
Python编写带选项的命令行程序方法
2019/08/13 Python
python中读入二维csv格式的表格方法详解(以元组/列表形式表示)
2020/04/24 Python
Python threading模块condition原理及运行流程详解
2020/10/05 Python
详解css3 Transition属性(平滑过渡菜单栏案例)
2017/09/05 HTML / CSS
CSS3中新增的对文本和字体的设置
2020/02/03 HTML / CSS
HTML5学习心得总结(推荐)
2016/07/08 HTML / CSS
Dower & Hall官网:英国小众轻奢珠宝品牌
2019/01/31 全球购物
面试后的感谢信范文
2014/02/01 职场文书
经贸专业毕业生求职信范文
2014/05/01 职场文书
公共机构节能宣传周活动总结
2014/07/09 职场文书
薪资证明范本
2015/06/19 职场文书
Spring Security使用单点登录的权限功能
2022/04/03 Java/Android