在上一篇中,使用scrapy改动源IP发送请求的最后我们提到因为hosts文件不支持正则,会导致我们的随机域名DNS查询失败。

使用DNS代理服务器能够解决问题,

以下是我用gevent写的小工具。非常easy。我们仅仅拦截匹配的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的强大。

来个截图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVlZ3VhbmdoYWlkYW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

功能有限。各位童鞋能够扩展,代码已经放到github,https://github.com/Skycrab/PyDnsProxy,有兴趣的童鞋一起完好。

[python网络编程]DNSserver的更多相关文章

  1. Python 网络编程(二)

    Python 网络编程 上一篇博客介绍了socket的基本概念以及实现了简单的TCP和UDP的客户端.服务器程序,本篇博客主要对socket编程进行更深入的讲解 一.简化版ssh实现 这是一个极其简单 ...

  2. Python 网络编程(一)

    Python 网络编程 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. ...

  3. Python学习(22)python网络编程

    Python 网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的 ...

  4. Day07 - Python 网络编程 Socket

    1. Python 网络编程 Python 提供了两个级别访问网络服务: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口 ...

  5. python网络编程-01

    python网络编程 1.socket模块介绍 ①在网络编程中的一个基本组件就是套接字(socket),socket是两个程序之间的“信息通道”. ②套接字包括两个部分:服务器套接字.客户机套接字 ③ ...

  6. 《Python网络编程》学习笔记--使用谷歌地理编码API获取一个JSON文档

    Foundations of Python Network Programing,Third Edition <python网络编程>,本书中的代码可在Github上搜索fopnp下载 本 ...

  7. Python网络编程基础pdf

    Python网络编程基础(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1VGwGtMSZbE0bSZe-MBl6qA 提取码:mert 复制这段内容后打开百度网盘手 ...

  8. python 网络编程(Socket)

    # from wsgiref.simple_server import make_server## def RunServer(environ,start_response):# start_resp ...

  9. python 网络编程 IO多路复用之epoll

    python网络编程——IO多路复用之epoll 1.内核EPOLL模型讲解     此部分参考http://blog.csdn.net/mango_song/article/details/4264 ...

随机推荐

  1. USACO Section 4.2 Drainage Ditches(最大流)

    最大流问题.ISAP算法.注意可能会有重边,不过我用的数据结构支持重边.距离d我直接初始化为0,也可以用BFS逆向找一次. -------------------------------------- ...

  2. Labview学习之程序Web发布

    Labview学习之程序Web发布 1. LabVIEW Web服务器     在LabVIEW开发环境中,自身带了一个已连接好的Web服务器.LabVIEW Web服务器除了与其他Web服务器一样能 ...

  3. ngrok原理浅析(转载)

    之前在进行 微信Demo开发时曾用到过 ngrok这个强大的tunnel(隧道)工具,ngrok在其github官方页面上的自我诠释是 "introspected tunnels to lo ...

  4. 1501 二叉树最大宽度和高度 (BFS+树的遍历)

    题目:http://www.wikioi.com/problem/1501/ 给你一颗二叉树,求该数的宽和高, 首先求出树的高,直接进行二叉树遍历,能够得到二叉树的高 然后是得到宽,本人采用的是一层一 ...

  5. CSS 基础总结

    CSS基础 Doctype 声明位于文档中的最前面,处于 标签之前.告知浏览器的解析器,用什么文档类型 规范来解析这个文档. 在标准模式中,浏览器根据规范呈现页面: 在混杂模式中,页面以一种比较宽松的 ...

  6. MySQL 数据显示宽度

    例子: 把int 的显示宽度设置为 3 create table t(x int(3) zerofill); insert into t(x) values(1); select x from t; ...

  7. jdk outMemory内存溢出

    参数的含义: -vmargs -Xms256M -Xmx768M -Xss256k -XX:PermSize=256M -XX:MaxPermSize=768M -vmargs 说明后面是vm的参数 ...

  8. 在 Visual C++ 中开发自定义的绘图控件

    本文讨论的重点介于两者 之间 — 公共控件赋予您想要的大部分功能,但控件的外观并不是您想要的.例如,列表视图控件提供在许多视图风格中显示数据列表的方式 — 小图标.大图标.列表和详细列表(报告).然而 ...

  9. 1分钟搞定超慢SQL

    前几天,一个用户的研发人员找到我了,说他们有个SQL语句非常慢,我说多慢?他们说:半个小时也没出结果.于是问他们要了SQL语句和执行计划,SQL语句就不能再这里贴出来了,下面是调整前的执行计划(略去某 ...

  10. CSS 布局总结——固定宽度布局

    固定宽度布局 单列布局 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2Fyd29sZjI0/font/5a6L5L2T/fontsize/400/fil ...