-
Notifications
You must be signed in to change notification settings - Fork 47
/
Copy pathdnsproxy.py
102 lines (82 loc) · 2.99 KB
/
dnsproxy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#! /usr/bin/python
# -*- coding: utf-8 -*-
__author__ = 'linkerlin'
import sys
import struct
import threading
import SocketServer
import optparse
try:
from dns import message as m
except ImportError as ex:
print "cannot find dnspython"
try:
from gevent import monkey
monkey.patch_all()
except ImportError as ex:
print "cannot find gevent"
import config
from dnsserver import DNSServer
from servers import Servers
reload(sys)
sys.setdefaultencoding("utf-8")
from dnsserver import bytetodomain
class DNSProxy(SocketServer.ThreadingMixIn, SocketServer.UDPServer):
SocketServer.ThreadingMixIn.daemon_threads = True
allow_reuse_address = True
def __init__(self, address=("0.0.0.0", 53), VERBOSE=2):
self.VERBOSE = VERBOSE
print "listening at:", address
SELF = self
class ProxyHandle(SocketServer.BaseRequestHandler):
# Ctrl-C will cleanly kill all spawned threads
daemon_threads = True
# much faster rebinding
allow_reuse_address = True
def handle(self):
data = self.request[0]
socket = self.request[1]
addr = self.client_address
DNSProxy.transfer(SELF, data, addr, socket)
SocketServer.UDPServer.__init__(self, address, ProxyHandle)
def loadConfig(self, config):
self.DNSS = config.DNSS
self.servers = Servers()
for s in self.DNSS:
assert len(s) == 3
ip, port, type_of_server = s
self.servers.addDNSServer(DNSServer(ip, port, type_of_server, self.VERBOSE))
self.WHITE_DNSS = config.WHITE_DNSS
for ws in self.WHITE_DNSS:
assert len(ws) == 4
ip, port, type_of_server, white_list = ws
self.servers.addWhiteDNSServer(DNSServer(ip, port, type_of_server, self.VERBOSE, white_list))
def transfer(self, query_data, addr, server):
if not query_data: return
domain = bytetodomain(query_data[12:-4])
qtype = struct.unpack('!h', query_data[-4:-2])[0]
#print 'domain:%s, qtype:%x, thread:%d' % (domain, qtype, threading.activeCount())
sys.stdout.flush()
response = None
for i in range(9):
response = self.servers.query(query_data)
if response:
# udp dns packet no length
server.sendto(response[2:], addr)
break
if response is None:
print "[ERROR] Tried 9 times and failed to resolve %s" % domain
return
def run_server():
print '>> Please wait program init....'
print '>> Init finished!'
print '>> Now you can set dns server to 127.0.0.1'
parser = optparse.OptionParser()
parser.add_option("-v", dest="verbose", default="0", help="Verbosity level, 0-2, default is 0")
options, _ = parser.parse_args()
proxy = DNSProxy(VERBOSE=options.verbose)
proxy.loadConfig(config)
proxy.serve_forever()
proxy.shutdown()
if __name__ == '__main__':
run_server()