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获取CPU、内存和硬盘等windowns系统信息的2个例子
Apr 15 Python
python检查序列seq是否含有aset中项的方法
Jun 30 Python
python3使用pyqt5制作一个超简单浏览器的实例
Oct 19 Python
tensorflow更改变量的值实例
Jul 30 Python
学生信息管理系统Python面向对象版
Jan 30 Python
python找出因数与质因数的方法
Jul 25 Python
对Django中static(静态)文件详解以及{% static %}标签的使用方法
Jul 28 Python
使用python的turtle绘画滑稽脸实例
Nov 21 Python
Python MySQLdb 执行sql语句时的参数传递方式
Mar 04 Python
Python函数的迭代器与生成器的示例代码
Jun 18 Python
Python 实现集合Set的示例
Dec 21 Python
python SOCKET编程基础入门
Feb 27 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
php学习 字符串课件
2008/06/15 PHP
php知道与问问的采集插件代码
2010/10/12 PHP
解决ajax+php中文乱码的方法详解
2013/06/09 PHP
laravel安装和配置教程
2014/10/29 PHP
PHP中字符安全过滤函数使用小结
2015/02/25 PHP
PHP+Ajax+JS实现多图上传
2016/05/07 PHP
javascript读取RSS数据
2007/01/20 Javascript
js Html结构转字符串形式显示代码
2011/11/15 Javascript
js图片自动切换效果处理代码
2013/05/07 Javascript
使用jquery实现以post打开新窗口
2014/03/19 Javascript
jQuery绑定事件不执行但alert后可以正常执行
2014/06/03 Javascript
jquery+CSS3实现3D拖拽相册效果
2016/07/18 Javascript
AngularJS中$apply方法和$watch方法用法总结
2016/12/13 Javascript
js实现不提示直接关闭网页窗口
2017/03/30 Javascript
详解@angular/cli 改变默认启动端口两种方式
2018/11/29 Javascript
vue搜索和vue模糊搜索代码实例
2019/05/07 Javascript
vuex存储token示例
2019/11/11 Javascript
JS FormData对象使用方法实例详解
2020/02/12 Javascript
Python编程之Re模块下的函数介绍
2017/10/28 Python
利用pyuic5将ui文件转换为py文件的方法
2019/06/19 Python
pandas 中对特征进行硬编码和onehot编码的实现
2019/12/20 Python
Python打包模块wheel的使用方法与将python包发布到PyPI的方法详解
2020/02/12 Python
python实现图像拼接
2020/03/05 Python
浅谈Python中range与Numpy中arange的比较
2020/03/11 Python
Django mysqlclient安装和使用详解
2020/09/17 Python
利用css3实现的简单的鼠标悬停按钮
2014/11/04 HTML / CSS
HTML5如何使用SVG的方法示例
2019/01/11 HTML / CSS
企业总经理岗位职责
2014/02/13 职场文书
团日活动总结
2014/04/28 职场文书
廉洁自律承诺书2015
2015/01/22 职场文书
合作意向协议书
2015/01/29 职场文书
python pyhs2 的安装操作
2021/04/07 Python
python+opencv实现视频抽帧示例代码
2021/06/11 Python
MySQL令人大跌眼镜的隐式转换
2021/08/23 MySQL
一小时学会TensorFlow2之基本操作2实例代码
2021/09/04 Python
mysql分表之后如何平滑上线详解
2021/11/01 MySQL