Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions common.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
except ImportError:
import Queue as queue


def eof_empty(b):
if b:
return b
raise EOFError()


class Config(dict):
def __init__(self, config):
dict.__init__(self, config)
Expand All @@ -39,31 +41,36 @@ def __init__(self, config):
log_handler.setFormatter(logging.Formatter(self['log_format']))
self['logger'].addHandler(log_handler)


class BaseServerConfig(dict):
def __init__(self, config):
dict.__init__(self, config)
if 'server_sockfamily' in self:
self['server_sockfamily'] = getattr(socket, self['server_sockfamily'])
else:
self['server_sockfamily'] = socket.AF_INET
if not 'server_addr' in self or not self['server_addr']:
if 'server_addr' not in self or not self['server_addr']:
if self['server_sockfamily'] == socket.AF_INET:
self['server_addr'] = '0.0.0.0'
elif self['server_sockfamily'] == socket.AF_INET6:
self['server_addr'] = '::'
if not 'backlog' in self:
if 'backlog' not in self:
self['backlog'] = 50


class ServerConfig(BaseServerConfig, Config):
def __init__(self, config):
Config.__init__(self, config)
BaseServerConfig.__init__(self, config)


class Server(object):
def __init__(self, config):
self.config = config

def start_peer(self, peer_sock, peer_info):
raise NotImplementedError()

def start(self):
try:
sock = socket.socket(self.config['server_sockfamily'])
Expand Down
16 changes: 12 additions & 4 deletions dns_client_tcp.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import random
import json
from common import *
from common import (
eof_empty,
socket
)


class DnsClient(object):
def __init__(self, config):
self.config = config
self.socks = []

def req_result(self, sock, host, port):
req = bytearray(json.dumps((host, port)).encode('iso-8859-1'))
req_len = len(req)
Expand All @@ -17,15 +22,16 @@ def req_result(self, sock, host, port):
while len(resp) != resp_len:
resp.extend(eof_empty(sock.recv(resp_len - len(resp))))
return json.loads(resp.decode('iso-8859-1'))

def getaddrinfo(self, host, port):
self.socks = [sock for sock in self.socks if sock != None]
self.socks.sort(key = lambda x: random.randint(-1, 1))
self.socks = [sock for sock in self.socks if sock is not None]
self.socks.sort(key=lambda x: random.randint(-1, 1))
for sock in enumerate(self.socks):
try:
return self.req_result(sock[1], host, port)
except Exception:
self.socks[sock[0]] = None
self.config['servers'].sort(key = lambda x: random.randint(-1, 1))
self.config['servers'].sort(key=lambda x: random.randint(-1, 1))
for server in self.config['servers']:
try:
sock = socket.socket()
Expand All @@ -38,9 +44,11 @@ def getaddrinfo(self, host, port):

_dns_client = None


def init(config):
global _dns_client
_dns_client = DnsClient(config)


def getaddrinfo(host, port):
return _dns_client.getaddrinfo(host, port)
16 changes: 14 additions & 2 deletions dns_server_tcp.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import sys
import json
from common import *
from common import (
Concurrent,
eof_empty,
socket,
Server,
ServerConfig
)


class DnsPeer(Concurrent):
def __init__(self, config, sock):
Concurrent.__init__(self)
self.config = config
self.sock = sock

def _run(self):
try:
while True:
Expand All @@ -22,20 +30,24 @@ def _run(self):
self.sock.sendall(resp.encode('iso-8859-1'))
except Exception as e:
self.config['logger'].debug('DnsPeer end with: %s', str(e))

def run(self):
return self._run()


class DnsServer(Server):
def __init__(self, config):
Server.__init__(self, config)

def start_peer(self, peer_sock, peer_info):
peer_sock.settimeout(self.config['timeout'])
DnsPeer(self.config, peer_sock).start()


def main(config_filename):
with open(config_filename) as config_file:
config = json.loads(config_file.read())
if not 'timeout' in config:
if 'timeout' not in config:
config['timeout'] = 2
DnsServer(ServerConfig(config)).start()

Expand Down
53 changes: 35 additions & 18 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import sys
import json
from common import *
from common import (
eof_empty,
socket,
logging,
Server,
gevent,
Concurrent,
ServerConfig
)


class SocksPipe(object):
def __call__(self, config, first_packet_processor, sock_in, sock_out):
sock_in_fileno = sock_in.fileno()
sock_out_fileno = sock_out.fileno()
config['logger'].debug('Start piping socket %d => socket %d'
, sock_in_fileno, sock_out_fileno)
config['logger'].debug('Start piping socket %d => socket %d',
sock_in_fileno, sock_out_fileno)
try:
first_packet_processor()
while True:
Expand All @@ -19,11 +28,12 @@ def __call__(self, config, first_packet_processor, sock_in, sock_out):
except Exception as e:
config['logger'].debug('Pipe(%d => %d) end with: %s', sock_in_fileno, sock_out_fileno, str(e))
finally:
config['logger'].debug('Closing socket pair %d and %d...'
, sock_in_fileno, sock_out_fileno)
config['logger'].debug('Closing socket pair %d and %d...',
sock_in_fileno, sock_out_fileno)
sock_in.close()
sock_out.close()


class SocksPeer(object):
def __call__(self, config, sock_peer):
sock_peer_fileno = sock_peer.fileno()
Expand Down Expand Up @@ -83,26 +93,28 @@ def __call__(self, config, sock_peer):
sock_remote_fileno = sock_remote.fileno()
break
except Exception as e:
config['logger'].debug('Error while connecting %s:%d for socks client %d: %s'
, dst_addr[4][0], dst_port, sock_peer.fileno(), str(e))
config['logger'].debug('Error while connecting %s:%d for socks client %d: %s',
dst_addr[4][0], dst_port, sock_peer.fileno(), str(e))
sock_remote.close()
sock_remote = None
if not sock_remote:
return
sock_peer.sendall(b'\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00')

def pipe_cs_first_packet(): # self.sock => sock
buf = sock_peer.recv(config['recv_packet_size'])
if not buf:
raise EOFError()
idx = 0
while idx < len(buf):
sock_remote.sendall(buf[idx : idx + config['send_packet_size']])
sock_remote.sendall(buf[idx: idx + config['send_packet_size']])
idx += config['send_packet_size']
sock_remote.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, config['recv_sep_size'])
sock_remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, config['tcp_nodelay'])
# The minimum (doubled) value for this option is 2048 on Linux:
# So no use for this operation on Linux:
sock_remote.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, config['so_sndbuf'])

def pipe_sc_first_packet(): # sock => self.sock
buf = sock_remote.recv(config['recv_packet_size'])
if not buf:
Expand All @@ -121,48 +133,52 @@ def pipe_sc_first_packet(): # sock => self.sock
if sock_remote:
sock_remote.close()


class SocksServer(Server):
def __init__(self, config):
Server.__init__(self, config)

def start(self):
if not gevent:
self.config['logger'].info('Cannot find gevent, using threading')
Server.start(self)

def start_peer(self, peer_sock, peer_info):
Concurrent(target=SocksPeer(), args=(self.config, peer_sock)).start()


class SocksServerConfig(ServerConfig):
def __init__(self, config):
ServerConfig.__init__(self, config)
tmp_sock = socket.socket()
if not 'tcp_nodelay' in self:
if 'tcp_nodelay' not in self:
self['tcp_nodelay'] = tmp_sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY)
if not 'so_sndbuf' in self:
if 'so_sndbuf' not in self:
self['so_sndbuf'] = tmp_sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
if not 'so_rcvbuf' in self:
if 'so_rcvbuf' not in self:
self['so_rcvbuf'] = tmp_sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)
tmp_sock.close()
if not 'send_sep_size' in self:
if 'send_sep_size' not in self:
self['send_sep_size'] = self['so_sndbuf']
if not 'send_packet_size' in self:
if 'send_packet_size' not in self:
self['send_packet_size'] = 1
if not 'recv_sep_size' in self:
if 'recv_sep_size' not in self:
self['recv_sep_size'] = self['so_rcvbuf']
if not 'recv_packet_size' in self:
if 'recv_packet_size'not in self:
self['recv_packet_size'] = 65536
bind_addr = dict()
if 'bind_addr' in self:
for family_type in self['bind_addr']:
bind_addr[getattr(socket, family_type)] = self['bind_addr'][family_type]
if not socket.AF_INET in bind_addr:
if socket.AF_INET not in bind_addr:
bind_addr[socket.AF_INET] = '0.0.0.0'
if not socket.AF_INET6 in bind_addr:
if socket.AF_INET6 not in bind_addr:
bind_addr[socket.AF_INET6] = '::'
self['bind_addr'] = bind_addr
if 'dns_client' in self:
dns_client = __import__(self['dns_client']['name'])
dns_client.init(self['dns_client']['config'])
if not 'timeout' in self['dns_client']['config']:
if 'timeout' not in self['dns_client']['config']:
self['dns_client']['config']['timeout'] = 2
for i, dns_server_addr in enumerate(self['dns_client']['config']['servers']):
self['dns_client']['config']['servers'][i] = tuple(dns_server_addr)
Expand All @@ -175,6 +191,7 @@ class dns_client:
self['dns_client'] = dns_client
self['logger'].debug('Config is "%s"', str(self))


def main(config_filename):
with open(config_filename) as config_file:
config = json.loads(config_file.read())
Expand Down
4 changes: 4 additions & 0 deletions windows/set_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,24 @@

internet_set_option = ctypes.windll.Wininet.InternetSetOptionW


def set_regkey(name, value):
_, reg_type = winreg.QueryValueEx(INTERNET_SETTINGS, name)
winreg.SetValueEx(INTERNET_SETTINGS, name, 0, reg_type, value)


def refersh_settings():
internet_set_option(0, INTERNET_OPTION_REFRESH, 0, 0)
internet_set_option(0, INTERNET_OPTION_SETTINGS_CHANGED, 0, 0)


def set_proxy(proxy_server): # proxy_server = u'X.X.X.X:8080'
set_regkey('ProxyServer', proxy_server)
# set_regkey('ProxyOverride', u'*.local;<local>') # Bypass the proxy for localhost
set_regkey('ProxyEnable', 1)
refersh_settings()


def unset_proxy():
set_regkey('ProxyEnable', 0)
refersh_settings()
Expand Down
7 changes: 7 additions & 0 deletions windows/wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@

import set_proxy


class Main(object):
def __init__(self, config):
self.config = config

def load_config(self, config_path):
with open(config_path) as config_file:
return json.loads(config_file.read())

def save_config(self, config_path, config):
with open(config_path, 'w') as config_file:
config_file.write(json.dumps(config))

def start(self):
try:
prompt_input = raw_input
Expand All @@ -36,10 +40,12 @@ def start(self):
set_proxy.set_proxy('http=127.0.0.1:%d' % (self.config['http_proxy_port'], ))
else:
print(self.config['translates']['start_menu'][language][1] % ('127.0.0.1', self.config['http_proxy_port']))

def start_main():
subprocess.call('3rd\\python\\python.exe main.py config.json > main.log 2>&1', shell=True)
threading.Thread(target=start_main).start()
main_config = self.load_config('config.json')

def start_polipo(socks_proxy_port, http_proxy_port):
subprocess.call('3rd\\polipo\polipo.exe socksParentProxy=127.0.0.1:%d proxyPort=%d > polipo.log 2>&1' % (socks_proxy_port, http_proxy_port), shell=True)
threading.Thread(target=start_polipo, args=(main_config['server_port'], self.config['http_proxy_port'])).start()
Expand Down Expand Up @@ -77,6 +83,7 @@ def start_polipo(socks_proxy_port, http_proxy_port):
elif sel == 0:
break


def main(json_path):
with open(json_path) as json_file:
config = json.loads(json_file.read())
Expand Down