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 的类、继承和多态详解
Jul 16 Python
Python面向对象编程基础解析(二)
Oct 26 Python
matplotlib在python上绘制3D散点图实例详解
Dec 09 Python
对python 操作solr索引数据的实例详解
Dec 07 Python
python实现三维拟合的方法
Dec 29 Python
python 列表中[ ]中冒号‘:’的作用
Apr 30 Python
详解python 爬取12306验证码
May 10 Python
详解Python sys.argv使用方法
May 10 Python
python中文分词库jieba使用方法详解
Feb 11 Python
python算的上脚本语言吗
Jun 22 Python
python中upper是做什么用的
Jul 20 Python
python 实现一个简单的线性回归案例
Dec 17 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
Zend Studio使用技巧两则
2016/04/01 PHP
解决PHP上传非标准格式的图片pjpeg失败的方法
2017/03/12 PHP
PHP编程实现阳历转换为阴历的方法实例
2017/08/08 PHP
在云虚拟主机部署thinkphp5项目的步骤详解
2017/12/21 PHP
php面试中关于面向对象的相关问题
2019/02/13 PHP
PHP开发的文字水印,缩略图,图片水印实现类与用法示例
2019/04/12 PHP
JavaScript 学习笔记(六)
2009/12/31 Javascript
Javascript学习笔记5 类和对象
2010/01/11 Javascript
jQuery滚动加载图片效果的实现
2013/03/06 Javascript
javascript中的绑定与解绑函数应用示例
2013/06/24 Javascript
jquery foreach使用示例
2013/09/12 Javascript
js同比例缩放图片的小例子
2013/10/30 Javascript
js控制淡入淡出示例代码
2013/11/12 Javascript
js调试工具Console命令详解
2014/10/21 Javascript
javascript实现仿腾讯游戏选择
2015/05/14 Javascript
jQuery横向擦除焦点图特效代码分享
2015/09/06 Javascript
jQuery leonaScroll 1.1 自定义滚动条插件(推荐)
2016/09/17 Javascript
jQuery加密密码到cookie的实现代码
2017/04/18 jQuery
Vuejs 页面的区域化与组件封装的实现
2017/09/11 Javascript
jQuery-Citys省市区三级菜单联动插件使用详解
2019/07/26 jQuery
JS事件流与事件处理程序实例分析
2019/08/16 Javascript
Vue页面刷新记住页面状态的实现
2019/12/27 Javascript
ES11屡试不爽的新特性,你用上了几个
2020/10/21 Javascript
MySQL最常见的操作语句小结
2015/05/07 Python
Python中的getopt函数使用详解
2015/07/28 Python
TF-IDF与余弦相似性的应用(二) 找出相似文章
2017/12/21 Python
python函数参数(必须参数、可变参数、关键字参数)
2019/08/16 Python
PyQt5+python3+pycharm开发环境配置教程
2020/03/24 Python
python 制作磁力搜索工具
2021/03/04 Python
HTML5新控件之日期和时间选择输入的实现代码
2018/09/13 HTML / CSS
美国最流行的男士时尚网站:Touch of Modern
2018/02/05 全球购物
什么是数组名
2012/05/10 面试题
SQL里面IN比较快还是EXISTS比较快
2012/07/19 面试题
《我的第一本书》教学反思
2014/02/15 职场文书
党支部三会一课计划
2014/09/24 职场文书
总结Python变量的相关知识
2021/06/28 Python