[python网络编程]DNS服务器
2014-05-09 12:30
405 查看
在上一篇中,使用scrapy修改源IP发送请求的最后我们提到由于hosts文件不支持正则,会导致我们的随机域名DNS查询失败。使用DNS代理服务器可以解决这个问题,
下面是我用gevent写的小工具,很简单。我们只拦截匹配的A记录,然后发送DNS Response,如果不匹配,那么我们服务器就是一个DNS代理,转发请求。
哈哈,刚好100行,不得不说python的强大。
来个截图:
![](http://img.blog.csdn.net/20140509123010921?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVlZ3VhbmdoYWlkYW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
功能有限,各位童鞋可以扩展,代码已经放到github,https://github.com/Skycrab/PyDnsProxy,有兴趣的童鞋一起完善。
下面是我用gevent写的小工具,很简单。我们只拦截匹配的A记录,然后发送DNS Response,如果不匹配,那么我们服务器就是一个DNS代理,转发请求。
# -*- coding=utf-8 -*- import struct from cStringIO import StringIO from collections import namedtuple from gevent import socket from gevent.server import DatagramServer Hex = lambda x : '0x{0:04x}'.format(x) # Hex(256) => "0x0100" QueryResult = namedtuple("DnsQuery", "transactionID,flags,questions,answerRrs \ authorityRrs,additionalRrs,qname,qtype,qclass" ) LOCALDNS = ("114.114.114.114",53) Hosts = { "*.ttt.com":"173.194.127.144", # google ip } def preg_match(preg,real): """ only support '*' >>>preg_match("www.*.test*.com","www.python.test.com") True >>>preg_match("www.*.test*.com","www.python.tes.com") False """ pre = 0 for s in preg.split('*'): now = real.find(s) if now < pre: return False pre = now +len(s) return True def udp_send(address,data): sock = socket.socket(type=socket.SOCK_DGRAM) sock.connect(address) sock.send(data) response, address = sock.recvfrom(8192*4) return response,address class DnsParser: @classmethod def parseQuery(self,query): """ 6a 02 01 00 00 01 j..... 00 00 00 00 00 00 03 77 77 77 03 61 61 61 03 63 .......www.aaa.c 6f 6d 00 00 01 00 01 om..... dns query package like above 03 77 77 77 : three www """ transactionID,flags,questions,answerRrs,authorityRrs,additionalRrs = map(Hex,struct.unpack("!6H",query[:12])) quries = StringIO(query[12:]) c = struct.unpack("!c",quries.read(1))[0] domain = [] while c != '\x00': n = ord(c) domain.append(''.join(struct.unpack("!%sc" % n,quries.read(ord(c))))) c = struct.unpack("!c",quries.read(1))[0] domain = '.'.join(domain) qtype,qclass = map(Hex,struct.unpack("!2H",quries.read())) return QueryResult(transactionID,flags,questions,answerRrs, authorityRrs,additionalRrs,domain,qtype,qclass) @classmethod def generateReqponse(self,queryData,ip): """ only support ipv4 """ return ''.join([queryData[:2],"\x81\x80\x00\x01\x00\x02\x00\x00\x00\x00", queryData[12:],"\xc0\x0c","\x00\x01","\x00\x01","\x00\x00\x00\x1e","\x00\x04", struct.pack('BBBB',*map(int,ip.split('.'))) ]) class DnsServer(DatagramServer): def handle(self,data,address): query = DnsParser.parseQuery(data) print "get dns query from %s,query:%s" %(str(address),str(query)) find = False for preg,ip in Hosts.iteritems(): if preg_match(preg,query.qname): find = True break if find and query.qtype == "0x0001": #only handle A record print 'domain:%s in hosts' % query.qname response = DnsParser.generateReqponse(data,ip) self.socket.sendto(response,address) else: print 'transfer for %s' % query.qname response,serveraddress = udp_send(LOCALDNS,data) self.socket.sendto(response,address) if __name__ == "__main__": DnsServer("192.168.9.178:53").serve_forever()
哈哈,刚好100行,不得不说python的强大。
来个截图:
功能有限,各位童鞋可以扩展,代码已经放到github,https://github.com/Skycrab/PyDnsProxy,有兴趣的童鞋一起完善。
相关文章推荐
- Python中利用原始套接字进行网络编程的示例
- python网络编程之tcp服务器和客户端
- 【python网络编程】多线程实现多用户全双工聊天
- Python之网络编程
- Python 网络爬虫 005 (编程) 如何编写一个可以 下载(或叫:爬取)一个网页 的网络爬虫
- Python网络编程:IO多路复用
- python天天进步(6)--网络编程之数据传输TCP
- python网络编程测试-broadcast
- python_网络编程_socket(服务器+客户端)
- Python学习笔记(五)——模块|图形界面|网络编程
- python 网络编程基础 笔记
- Python 网络编程(二)
- python 中网络编程连接以及报头
- python 网络编程——TCP编程模型
- Dave Python 练习十九 -- 网络客户端编程
- python(12-2 网络编程 udp ,tcp 协议)
- Python基础教程——14 网络编程
- python学习之路-10 网络编程之进阶
- Python_网络编程_获取百度首页代码保存到本地
- Python tensorflow实战3.神经网络 - 理解到底什么是神经网络,编程原理