Skip to content

Commit

Permalink
merge manyuser 2.6.13
Browse files Browse the repository at this point in the history
  • Loading branch information
breakwa11 committed Nov 2, 2015
1 parent a681a72 commit 1ee3442
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 65 deletions.
3 changes: 3 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
2.6.13 2015-11-02
- add protocol setting

2.6.12 2015-10-27
- IPv6 first
- Fix mem leaks
Expand Down
41 changes: 29 additions & 12 deletions shadowsocks/asyncdns.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,11 @@ def detect_ipv6_supprot():
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
try:
s.connect(('ipv6.google.com', 0))
print('IPv6 support')
return True
except:
pass
print('IPv6 not support')
return False

IPV6_CONNECTION_SUPPORT = detect_ipv6_supprot()
Expand Down Expand Up @@ -356,19 +358,34 @@ def _handle_data(self, data):
answer[2] == QCLASS_IN:
ip = answer[0]
break
if not ip and self._hostname_status.get(hostname, STATUS_IPV4) \
== STATUS_IPV6:
self._hostname_status[hostname] = STATUS_IPV4
self._send_req(hostname, QTYPE_A)
if IPV6_CONNECTION_SUPPORT:
if not ip and self._hostname_status.get(hostname, STATUS_IPV4) \
== STATUS_IPV6:
self._hostname_status[hostname] = STATUS_IPV4
self._send_req(hostname, QTYPE_A)
else:
if ip:
self._cache[hostname] = ip
self._call_callback(hostname, ip)
elif self._hostname_status.get(hostname, None) == STATUS_IPV4:
for question in response.questions:
if question[1] == QTYPE_A:
self._call_callback(hostname, None)
break
else:
if ip:
self._cache[hostname] = ip
self._call_callback(hostname, ip)
elif self._hostname_status.get(hostname, None) == STATUS_IPV4:
for question in response.questions:
if question[1] == QTYPE_A:
self._call_callback(hostname, None)
break
if not ip and self._hostname_status.get(hostname, STATUS_IPV6) \
== STATUS_IPV4:
self._hostname_status[hostname] = STATUS_IPV6
self._send_req(hostname, QTYPE_AAAA)
else:
if ip:
self._cache[hostname] = ip
self._call_callback(hostname, ip)
elif self._hostname_status.get(hostname, None) == STATUS_IPV6:
for question in response.questions:
if question[1] == QTYPE_AAAA:
self._call_callback(hostname, None)
break

def handle_event(self, sock, fd, event):
if sock != self._sock:
Expand Down
3 changes: 3 additions & 0 deletions shadowsocks/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ def main():

config = shell.get_config(True)

if not config.get('dns_ipv6', False):
asyncdns.IPV6_CONNECTION_SUPPORT = False

daemon.daemon_exec(config)

try:
Expand Down
4 changes: 4 additions & 0 deletions shadowsocks/obfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,7 @@ def server_decode(self, buf):
def server_post_decrypt(self, buf):
return self.obfs.server_post_decrypt(buf)

def dispose(self):
self.obfs.dispose()
del self.obfs

3 changes: 3 additions & 0 deletions shadowsocks/obfsplugin/http_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ def client_encode(self, buf):
return buf
self.send_buffer += buf
if not self.has_sent_header:
port = b''
if self.server_info.port != 80:
port = b':' + common.to_bytes(str(self.server_info.port))
self.has_sent_header = True
http_head = b"GET / HTTP/1.1\r\n"
http_head += b"Host: " + (self.server_info.param or self.server_info.host) + port + b"\r\n"
Expand Down
4 changes: 4 additions & 0 deletions shadowsocks/obfsplugin/plain.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def create_obfs(method):

obfs_map = {
'plain': (create_obfs,),
'origin': (create_obfs,),
}

class plain(object):
Expand Down Expand Up @@ -66,3 +67,6 @@ def server_decode(self, buf):
def server_post_decrypt(self, buf):
return buf

def dispose(self):
pass

58 changes: 22 additions & 36 deletions shadowsocks/obfsplugin/verify_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,59 +57,42 @@ def match_begin(str1, str2):

class obfs_verify_data(object):
def __init__(self):
self.sub_obfs = None
pass

class verify_base(plain.plain):
def __init__(self, method):
super(verify_base, self).__init__(method)
self.method = method
self.sub_obfs = None

def init_data(self):
return obfs_verify_data()

def set_server_info(self, server_info):
try:
if server_info.param:
sub_param = ''
param_list = server_info.param.split(',', 1)
if len(param_list) > 1:
self.sub_obfs = shadowsocks.obfs.obfs(param_list[0])
sub_param = param_list[1]
else:
self.sub_obfs = shadowsocks.obfs.obfs(server_info.param)
if server_info.data.sub_obfs is None:
server_info.data.sub_obfs = self.sub_obfs.init_data()
_server_info = shadowsocks.obfs.server_info(server_info.data.sub_obfs)
_server_info.host = server_info.host
_server_info.port = server_info.port
_server_info.tcp_mss = server_info.tcp_mss
_server_info.param = sub_param
self.sub_obfs.set_server_info(_server_info)
except Exception as e:
shadowsocks.shell.print_exception(e)
self.server_info = server_info

def client_encode(self, buf):
if self.sub_obfs is not None:
return self.sub_obfs.client_encode(buf)
return buf

def client_decode(self, buf):
if self.sub_obfs is not None:
return self.sub_obfs.client_decode(buf)
return (buf, False)

def server_encode(self, buf):
if self.sub_obfs is not None:
return self.sub_obfs.server_encode(buf)
return buf

def server_decode(self, buf):
if self.sub_obfs is not None:
return self.sub_obfs.server_decode(buf)
return (buf, True, False)

def get_head_size(self, buf, def_value):
if len(buf) < 2:
return def_value
if ord(buf[0]) == 1:
return 7
if ord(buf[0]) == 4:
return 19
if ord(buf[0]) == 3:
return 4 + ord(buf[1])
return def_value

class verify_simple(verify_base):
def __init__(self, method):
super(verify_simple, self).__init__(method)
Expand Down Expand Up @@ -336,28 +319,28 @@ def insert(self, connection_id):

class obfs_auth_data(object):
def __init__(self):
self.sub_obfs = None
self.client_id = {}
self.startup_time = int(time.time() - 30) & 0xFFFFFFFF
self.local_client_id = b''
self.connection_id = 0
self.max_client = 16 # max active client count
self.max_buffer = max(self.max_client, 256) # max client id buffer size

def update(self, client_id, connection_id):
if client_id in self.client_id:
self.client_id[client_id].update()

def insert(self, client_id, connection_id):
max_client = 16
if client_id not in self.client_id or not self.client_id[client_id].enable:
active = 0
for c_id in self.client_id:
if self.client_id[c_id].is_active():
active += 1
if active >= max_client:
if active >= self.max_client:
logging.warn('auth_simple: max active clients exceeded')
return False

if len(self.client_id) < max_client:
if len(self.client_id) < self.max_client:
if client_id not in self.client_id:
self.client_id[client_id] = client_queue(connection_id)
else:
Expand All @@ -367,7 +350,7 @@ def insert(self, client_id, connection_id):
random.shuffle(keys)
for c_id in keys:
if not self.client_id[c_id].is_active() and self.client_id[c_id].enable:
if len(self.client_id) >= 256:
if len(self.client_id) >= self.max_buffer:
del self.client_id[c_id]
else:
self.client_id[c_id].enable = False
Expand All @@ -392,6 +375,7 @@ def __init__(self, method):
self.has_recv_header = False
self.client_id = 0
self.connection_id = 0
self.max_time_dif = 60 * 5 # time dif (second) setting

def init_data(self):
return obfs_auth_data()
Expand Down Expand Up @@ -422,7 +406,8 @@ def auth_data(self):
def client_pre_encrypt(self, buf):
ret = b''
if not self.has_sent_header:
datalen = min(len(buf), common.ord(os.urandom(1)[0]) % 32 + 4)
head_size = self.get_head_size(buf, 30)
datalen = min(len(buf), random.randint(0, 31) + head_size)
ret += self.pack_data(self.auth_data() + buf[:datalen])
buf = buf[datalen:]
self.has_sent_header = True
Expand Down Expand Up @@ -512,7 +497,8 @@ def server_post_decrypt(self, buf):
client_id = struct.unpack('<I', out_buf[4:8])[0]
connection_id = struct.unpack('<I', out_buf[8:12])[0]
time_dif = common.int32((int(time.time()) & 0xffffffff) - utc_time)
if time_dif < 60 * -3 or time_dif > 60 * 3 or common.int32(utc_time - self.server_info.data.startup_time) < 0:
if time_dif < -self.max_time_dif or time_dif > self.max_time_dif \
or common.int32(utc_time - self.server_info.data.startup_time) < 0:
self.raw_trans = True
self.recv_buf = b''
logging.info('auth_simple: wrong timestamp, time_dif %d, data %s' % (time_dif, binascii.hexlify(out_buf),))
Expand Down
18 changes: 16 additions & 2 deletions shadowsocks/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ def main():
else:
config['port_password'][str(server_port)] = config['password']

if not config.get('dns_ipv6', False):
asyncdns.IPV6_CONNECTION_SUPPORT = False

if config.get('manager_address', 0):
logging.info('entering manager mode')
manager.run(config)
Expand All @@ -65,23 +68,32 @@ def main():
port_password = config['port_password']
del config['port_password']
for port, password_obfs in port_password.items():
protocol = config.get("protocol", 'origin')
obfs_param = config.get("obfs_param", '')
if type(password_obfs) == list:
password = password_obfs[0]
obfs = password_obfs[1]
elif type(password_obfs) == dict:
password = password_obfs.get('password', 'm')
protocol = password_obfs.get('protocol', 'origin')
obfs = password_obfs.get('obfs', 'plain')
obfs_param = password_obfs.get('obfs_param', '')
else:
password = password_obfs
obfs = config["obfs"]
a_config = config.copy()
ipv6_ok = False
logging.info("server start with password [%s] method [%s] obfs [%s] obfs_param [%s]" %
(password, a_config['method'], obfs, a_config['obfs_param']))
logging.info("server start with protocol[%s] password [%s] method [%s] obfs [%s] obfs_param [%s]" %
(protocol, password, a_config['method'], obfs, obfs_param))
if 'server_ipv6' in a_config:
try:
if len(a_config['server_ipv6']) > 2 and a_config['server_ipv6'][0] == "[" and a_config['server_ipv6'][-1] == "]":
a_config['server_ipv6'] = a_config['server_ipv6'][1:-1]
a_config['server_port'] = int(port)
a_config['password'] = password
a_config['protocol'] = protocol
a_config['obfs'] = obfs
a_config['obfs_param'] = obfs_param
a_config['server'] = a_config['server_ipv6']
logging.info("starting server at [%s]:%d" %
(a_config['server'], int(port)))
Expand All @@ -96,7 +108,9 @@ def main():
a_config = config.copy()
a_config['server_port'] = int(port)
a_config['password'] = password
a_config['protocol'] = protocol
a_config['obfs'] = obfs
a_config['obfs_param'] = obfs_param
logging.info("starting server at %s:%d" %
(a_config['server'], int(port)))
tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False))
Expand Down
1 change: 1 addition & 0 deletions shadowsocks/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ def get_config(is_local):

config['password'] = to_bytes(config.get('password', b''))
config['method'] = to_str(config.get('method', 'aes-256-cfb'))
config['protocol'] = to_str(config.get('protocol', 'origin'))
config['obfs'] = to_str(config.get('obfs', 'plain'))
config['obfs_param'] = to_str(config.get('obfs_param', ''))
config['port_password'] = config.get('port_password', None)
Expand Down
Loading

0 comments on commit 1ee3442

Please sign in to comment.