Skip to content

Commit 1ee3442

Browse files
committed
merge manyuser 2.6.13
1 parent a681a72 commit 1ee3442

File tree

11 files changed

+136
-65
lines changed

11 files changed

+136
-65
lines changed

CHANGES

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2.6.13 2015-11-02
2+
- add protocol setting
3+
14
2.6.12 2015-10-27
25
- IPv6 first
36
- Fix mem leaks

shadowsocks/asyncdns.py

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,11 @@ def detect_ipv6_supprot():
8383
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
8484
try:
8585
s.connect(('ipv6.google.com', 0))
86+
print('IPv6 support')
8687
return True
8788
except:
8889
pass
90+
print('IPv6 not support')
8991
return False
9092

9193
IPV6_CONNECTION_SUPPORT = detect_ipv6_supprot()
@@ -356,19 +358,34 @@ def _handle_data(self, data):
356358
answer[2] == QCLASS_IN:
357359
ip = answer[0]
358360
break
359-
if not ip and self._hostname_status.get(hostname, STATUS_IPV4) \
360-
== STATUS_IPV6:
361-
self._hostname_status[hostname] = STATUS_IPV4
362-
self._send_req(hostname, QTYPE_A)
361+
if IPV6_CONNECTION_SUPPORT:
362+
if not ip and self._hostname_status.get(hostname, STATUS_IPV4) \
363+
== STATUS_IPV6:
364+
self._hostname_status[hostname] = STATUS_IPV4
365+
self._send_req(hostname, QTYPE_A)
366+
else:
367+
if ip:
368+
self._cache[hostname] = ip
369+
self._call_callback(hostname, ip)
370+
elif self._hostname_status.get(hostname, None) == STATUS_IPV4:
371+
for question in response.questions:
372+
if question[1] == QTYPE_A:
373+
self._call_callback(hostname, None)
374+
break
363375
else:
364-
if ip:
365-
self._cache[hostname] = ip
366-
self._call_callback(hostname, ip)
367-
elif self._hostname_status.get(hostname, None) == STATUS_IPV4:
368-
for question in response.questions:
369-
if question[1] == QTYPE_A:
370-
self._call_callback(hostname, None)
371-
break
376+
if not ip and self._hostname_status.get(hostname, STATUS_IPV6) \
377+
== STATUS_IPV4:
378+
self._hostname_status[hostname] = STATUS_IPV6
379+
self._send_req(hostname, QTYPE_AAAA)
380+
else:
381+
if ip:
382+
self._cache[hostname] = ip
383+
self._call_callback(hostname, ip)
384+
elif self._hostname_status.get(hostname, None) == STATUS_IPV6:
385+
for question in response.questions:
386+
if question[1] == QTYPE_AAAA:
387+
self._call_callback(hostname, None)
388+
break
372389

373390
def handle_event(self, sock, fd, event):
374391
if sock != self._sock:

shadowsocks/local.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ def main():
4343

4444
config = shell.get_config(True)
4545

46+
if not config.get('dns_ipv6', False):
47+
asyncdns.IPV6_CONNECTION_SUPPORT = False
48+
4649
daemon.daemon_exec(config)
4750

4851
try:

shadowsocks/obfs.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,7 @@ def server_decode(self, buf):
8383
def server_post_decrypt(self, buf):
8484
return self.obfs.server_post_decrypt(buf)
8585

86+
def dispose(self):
87+
self.obfs.dispose()
88+
del self.obfs
89+

shadowsocks/obfsplugin/http_simple.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ def client_encode(self, buf):
192192
return buf
193193
self.send_buffer += buf
194194
if not self.has_sent_header:
195+
port = b''
196+
if self.server_info.port != 80:
197+
port = b':' + common.to_bytes(str(self.server_info.port))
195198
self.has_sent_header = True
196199
http_head = b"GET / HTTP/1.1\r\n"
197200
http_head += b"Host: " + (self.server_info.param or self.server_info.host) + port + b"\r\n"

shadowsocks/obfsplugin/plain.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def create_obfs(method):
2727

2828
obfs_map = {
2929
'plain': (create_obfs,),
30+
'origin': (create_obfs,),
3031
}
3132

3233
class plain(object):
@@ -66,3 +67,6 @@ def server_decode(self, buf):
6667
def server_post_decrypt(self, buf):
6768
return buf
6869

70+
def dispose(self):
71+
pass
72+

shadowsocks/obfsplugin/verify_simple.py

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -57,59 +57,42 @@ def match_begin(str1, str2):
5757

5858
class obfs_verify_data(object):
5959
def __init__(self):
60-
self.sub_obfs = None
60+
pass
6161

6262
class verify_base(plain.plain):
6363
def __init__(self, method):
6464
super(verify_base, self).__init__(method)
6565
self.method = method
66-
self.sub_obfs = None
6766

6867
def init_data(self):
6968
return obfs_verify_data()
7069

7170
def set_server_info(self, server_info):
72-
try:
73-
if server_info.param:
74-
sub_param = ''
75-
param_list = server_info.param.split(',', 1)
76-
if len(param_list) > 1:
77-
self.sub_obfs = shadowsocks.obfs.obfs(param_list[0])
78-
sub_param = param_list[1]
79-
else:
80-
self.sub_obfs = shadowsocks.obfs.obfs(server_info.param)
81-
if server_info.data.sub_obfs is None:
82-
server_info.data.sub_obfs = self.sub_obfs.init_data()
83-
_server_info = shadowsocks.obfs.server_info(server_info.data.sub_obfs)
84-
_server_info.host = server_info.host
85-
_server_info.port = server_info.port
86-
_server_info.tcp_mss = server_info.tcp_mss
87-
_server_info.param = sub_param
88-
self.sub_obfs.set_server_info(_server_info)
89-
except Exception as e:
90-
shadowsocks.shell.print_exception(e)
9171
self.server_info = server_info
9272

9373
def client_encode(self, buf):
94-
if self.sub_obfs is not None:
95-
return self.sub_obfs.client_encode(buf)
9674
return buf
9775

9876
def client_decode(self, buf):
99-
if self.sub_obfs is not None:
100-
return self.sub_obfs.client_decode(buf)
10177
return (buf, False)
10278

10379
def server_encode(self, buf):
104-
if self.sub_obfs is not None:
105-
return self.sub_obfs.server_encode(buf)
10680
return buf
10781

10882
def server_decode(self, buf):
109-
if self.sub_obfs is not None:
110-
return self.sub_obfs.server_decode(buf)
11183
return (buf, True, False)
11284

85+
def get_head_size(self, buf, def_value):
86+
if len(buf) < 2:
87+
return def_value
88+
if ord(buf[0]) == 1:
89+
return 7
90+
if ord(buf[0]) == 4:
91+
return 19
92+
if ord(buf[0]) == 3:
93+
return 4 + ord(buf[1])
94+
return def_value
95+
11396
class verify_simple(verify_base):
11497
def __init__(self, method):
11598
super(verify_simple, self).__init__(method)
@@ -336,28 +319,28 @@ def insert(self, connection_id):
336319

337320
class obfs_auth_data(object):
338321
def __init__(self):
339-
self.sub_obfs = None
340322
self.client_id = {}
341323
self.startup_time = int(time.time() - 30) & 0xFFFFFFFF
342324
self.local_client_id = b''
343325
self.connection_id = 0
326+
self.max_client = 16 # max active client count
327+
self.max_buffer = max(self.max_client, 256) # max client id buffer size
344328

345329
def update(self, client_id, connection_id):
346330
if client_id in self.client_id:
347331
self.client_id[client_id].update()
348332

349333
def insert(self, client_id, connection_id):
350-
max_client = 16
351334
if client_id not in self.client_id or not self.client_id[client_id].enable:
352335
active = 0
353336
for c_id in self.client_id:
354337
if self.client_id[c_id].is_active():
355338
active += 1
356-
if active >= max_client:
339+
if active >= self.max_client:
357340
logging.warn('auth_simple: max active clients exceeded')
358341
return False
359342

360-
if len(self.client_id) < max_client:
343+
if len(self.client_id) < self.max_client:
361344
if client_id not in self.client_id:
362345
self.client_id[client_id] = client_queue(connection_id)
363346
else:
@@ -367,7 +350,7 @@ def insert(self, client_id, connection_id):
367350
random.shuffle(keys)
368351
for c_id in keys:
369352
if not self.client_id[c_id].is_active() and self.client_id[c_id].enable:
370-
if len(self.client_id) >= 256:
353+
if len(self.client_id) >= self.max_buffer:
371354
del self.client_id[c_id]
372355
else:
373356
self.client_id[c_id].enable = False
@@ -392,6 +375,7 @@ def __init__(self, method):
392375
self.has_recv_header = False
393376
self.client_id = 0
394377
self.connection_id = 0
378+
self.max_time_dif = 60 * 5 # time dif (second) setting
395379

396380
def init_data(self):
397381
return obfs_auth_data()
@@ -422,7 +406,8 @@ def auth_data(self):
422406
def client_pre_encrypt(self, buf):
423407
ret = b''
424408
if not self.has_sent_header:
425-
datalen = min(len(buf), common.ord(os.urandom(1)[0]) % 32 + 4)
409+
head_size = self.get_head_size(buf, 30)
410+
datalen = min(len(buf), random.randint(0, 31) + head_size)
426411
ret += self.pack_data(self.auth_data() + buf[:datalen])
427412
buf = buf[datalen:]
428413
self.has_sent_header = True
@@ -512,7 +497,8 @@ def server_post_decrypt(self, buf):
512497
client_id = struct.unpack('<I', out_buf[4:8])[0]
513498
connection_id = struct.unpack('<I', out_buf[8:12])[0]
514499
time_dif = common.int32((int(time.time()) & 0xffffffff) - utc_time)
515-
if time_dif < 60 * -3 or time_dif > 60 * 3 or common.int32(utc_time - self.server_info.data.startup_time) < 0:
500+
if time_dif < -self.max_time_dif or time_dif > self.max_time_dif \
501+
or common.int32(utc_time - self.server_info.data.startup_time) < 0:
516502
self.raw_trans = True
517503
self.recv_buf = b''
518504
logging.info('auth_simple: wrong timestamp, time_dif %d, data %s' % (time_dif, binascii.hexlify(out_buf),))

shadowsocks/server.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ def main():
5454
else:
5555
config['port_password'][str(server_port)] = config['password']
5656

57+
if not config.get('dns_ipv6', False):
58+
asyncdns.IPV6_CONNECTION_SUPPORT = False
59+
5760
if config.get('manager_address', 0):
5861
logging.info('entering manager mode')
5962
manager.run(config)
@@ -65,23 +68,32 @@ def main():
6568
port_password = config['port_password']
6669
del config['port_password']
6770
for port, password_obfs in port_password.items():
71+
protocol = config.get("protocol", 'origin')
72+
obfs_param = config.get("obfs_param", '')
6873
if type(password_obfs) == list:
6974
password = password_obfs[0]
7075
obfs = password_obfs[1]
76+
elif type(password_obfs) == dict:
77+
password = password_obfs.get('password', 'm')
78+
protocol = password_obfs.get('protocol', 'origin')
79+
obfs = password_obfs.get('obfs', 'plain')
80+
obfs_param = password_obfs.get('obfs_param', '')
7181
else:
7282
password = password_obfs
7383
obfs = config["obfs"]
7484
a_config = config.copy()
7585
ipv6_ok = False
76-
logging.info("server start with password [%s] method [%s] obfs [%s] obfs_param [%s]" %
77-
(password, a_config['method'], obfs, a_config['obfs_param']))
86+
logging.info("server start with protocol[%s] password [%s] method [%s] obfs [%s] obfs_param [%s]" %
87+
(protocol, password, a_config['method'], obfs, obfs_param))
7888
if 'server_ipv6' in a_config:
7989
try:
8090
if len(a_config['server_ipv6']) > 2 and a_config['server_ipv6'][0] == "[" and a_config['server_ipv6'][-1] == "]":
8191
a_config['server_ipv6'] = a_config['server_ipv6'][1:-1]
8292
a_config['server_port'] = int(port)
8393
a_config['password'] = password
94+
a_config['protocol'] = protocol
8495
a_config['obfs'] = obfs
96+
a_config['obfs_param'] = obfs_param
8597
a_config['server'] = a_config['server_ipv6']
8698
logging.info("starting server at [%s]:%d" %
8799
(a_config['server'], int(port)))
@@ -96,7 +108,9 @@ def main():
96108
a_config = config.copy()
97109
a_config['server_port'] = int(port)
98110
a_config['password'] = password
111+
a_config['protocol'] = protocol
99112
a_config['obfs'] = obfs
113+
a_config['obfs_param'] = obfs_param
100114
logging.info("starting server at %s:%d" %
101115
(a_config['server'], int(port)))
102116
tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False))

shadowsocks/shell.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ def get_config(is_local):
218218

219219
config['password'] = to_bytes(config.get('password', b''))
220220
config['method'] = to_str(config.get('method', 'aes-256-cfb'))
221+
config['protocol'] = to_str(config.get('protocol', 'origin'))
221222
config['obfs'] = to_str(config.get('obfs', 'plain'))
222223
config['obfs_param'] = to_str(config.get('obfs_param', ''))
223224
config['port_password'] = config.get('port_password', None)

0 commit comments

Comments
 (0)