Browse Source

fix 'ord' bug

replace 'xrange'
support new protocol when run as a client
dev
breakwa11 9 years ago
parent
commit
2e3114f40f
  1. 20
      shadowsocks/obfs.py
  2. 12
      shadowsocks/obfsplugin/http_simple.py
  3. 11
      shadowsocks/obfsplugin/plain.py
  4. 47
      shadowsocks/tcprelay.py
  5. 28
      shadowsocks/udprelay.py

20
shadowsocks/obfs.py

@ -49,13 +49,15 @@ class Obfs(object):
m = self._method_info m = self._method_info
return m[0](method) return m[0](method)
def encode(self, buf): def client_encode(self, buf):
#if len(buf) == 0: return self.obfs.client_encode(buf)
# return buf
return self.obfs.encode(buf) def client_decode(self, buf):
return self.obfs.client_decode(buf)
def decode(self, buf):
#if len(buf) == 0: def server_encode(self, buf):
# return (buf, True, False) return self.obfs.server_encode(buf)
return self.obfs.decode(buf)
def server_decode(self, buf):
return self.obfs.server_decode(buf)

12
shadowsocks/obfsplugin/http_simple.py

@ -40,7 +40,15 @@ class http_simple(object):
self.port = 0 self.port = 0
self.recv_buffer = "" self.recv_buffer = ""
def encode(self, buf): def client_encode(self, buf):
# TODO
return buf
def client_decode(self, buf):
# TODO
return (buf, False)
def server_encode(self, buf):
if self.has_sent_header: if self.has_sent_header:
return buf return buf
else: else:
@ -50,7 +58,7 @@ class http_simple(object):
self.has_sent_header = True self.has_sent_header = True
return header + buf return header + buf
def decode(self, buf): def server_decode(self, buf):
if self.has_recv_header: if self.has_recv_header:
return (buf, True, False) return (buf, True, False)
else: else:

11
shadowsocks/obfsplugin/plain.py

@ -33,9 +33,16 @@ class plain(object):
def __init__(self, method): def __init__(self, method):
self.method = method self.method = method
def encode(self, buf): def client_encode(self, buf):
return buf return buf
def decode(self, buf): def client_decode(self, buf):
# (buffer_to_recv, is_need_to_encode_and_send_back)
return (buf, False)
def server_encode(self, buf):
return buf
def server_decode(self, buf):
# (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) # (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back)
return (buf, True, False) return (buf, True, False)

47
shadowsocks/tcprelay.py

@ -33,6 +33,8 @@ from shadowsocks.common import pre_parse_header, parse_header
# set it 'False' to use both new protocol and the original shadowsocks protocal # set it 'False' to use both new protocol and the original shadowsocks protocal
# set it 'True' to use new protocol ONLY, to avoid GFW detecting # set it 'True' to use new protocol ONLY, to avoid GFW detecting
FORCE_NEW_PROTOCOL = False FORCE_NEW_PROTOCOL = False
# set it 'True' if run as a local client and connect to a server which support new protocol
CLIENT_NEW_PROTOCOL = False
# we clear at most TIMEOUTS_CLEAN_SIZE timeouts each time # we clear at most TIMEOUTS_CLEAN_SIZE timeouts each time
TIMEOUTS_CLEAN_SIZE = 512 TIMEOUTS_CLEAN_SIZE = 512
@ -250,9 +252,12 @@ class TCPRelayHandler(object):
return True return True
else: else:
try: try:
if sock == self._local_sock and self._encrypt_correct: if self._is_local:
obfs_encode = self._obfs.encode(data) pass
data = obfs_encode else:
if sock == self._local_sock and self._encrypt_correct:
obfs_encode = self._obfs.server_encode(data)
data = obfs_encode
l = len(data) l = len(data)
s = sock.send(data) s = sock.send(data)
if s < l: if s < l:
@ -303,7 +308,7 @@ class TCPRelayHandler(object):
def _handel_protocol_error(self, client_address, ogn_data): def _handel_protocol_error(self, client_address, ogn_data):
#raise Exception('can not parse header') #raise Exception('can not parse header')
logging.warn("Protocol ERROR, TCP ogn data %s" % (binascii.hexlify(ogn_data), )) logging.warn("Protocol ERROR, TCP ogn data %s from %s:%d" % (binascii.hexlify(ogn_data), client_address[0], client_address[1]))
self._encrypt_correct = False self._encrypt_correct = False
#create redirect or disconnect by hash code #create redirect or disconnect by hash code
host, port = self._get_redirect_host(client_address, ogn_data) host, port = self._get_redirect_host(client_address, ogn_data)
@ -314,6 +319,7 @@ class TCPRelayHandler(object):
def _handle_stage_connecting(self, data): def _handle_stage_connecting(self, data):
if self._is_local: if self._is_local:
data = self._encryptor.encrypt(data) data = self._encryptor.encrypt(data)
data = self._obfs.client_encode(data)
self._data_to_write_to_remote.append(data) self._data_to_write_to_remote.append(data)
if self._is_local and not self._fastopen_connected and \ if self._is_local and not self._fastopen_connected and \
self._config['fast_open']: self._config['fast_open']:
@ -377,15 +383,18 @@ class TCPRelayHandler(object):
return return
before_parse_data = data before_parse_data = data
if FORCE_NEW_PROTOCOL and ord(data[0]) != 0x88: if self._is_local:
data = self._handel_protocol_error(self._client_address, ogn_data)
data = pre_parse_header(data)
if data is None:
data = self._handel_protocol_error(self._client_address, ogn_data)
header_result = parse_header(data)
if header_result is None:
data = self._handel_protocol_error(self._client_address, ogn_data)
header_result = parse_header(data) header_result = parse_header(data)
else:
if FORCE_NEW_PROTOCOL and common.ord(data[0]) != 0x88:
data = self._handel_protocol_error(self._client_address, ogn_data)
data = pre_parse_header(data)
if data is None:
data = self._handel_protocol_error(self._client_address, ogn_data)
header_result = parse_header(data)
if header_result is None:
data = self._handel_protocol_error(self._client_address, ogn_data)
header_result = parse_header(data)
connecttype, remote_addr, remote_port, header_length = header_result connecttype, remote_addr, remote_port, header_length = header_result
logging.info('%s connecting %s:%d from %s:%d' % logging.info('%s connecting %s:%d from %s:%d' %
((connecttype == 0) and 'TCP' or 'UDP', ((connecttype == 0) and 'TCP' or 'UDP',
@ -401,6 +410,12 @@ class TCPRelayHandler(object):
self._write_to_sock((b'\x05\x00\x00\x01' self._write_to_sock((b'\x05\x00\x00\x01'
b'\x00\x00\x00\x00\x10\x10'), b'\x00\x00\x00\x00\x10\x10'),
self._local_sock) self._local_sock)
if CLIENT_NEW_PROTOCOL:
rnd_len = random.randint(1, 32)
total_len = 7 + rnd_len + len(data)
data = b'\x88' + struct.pack('>H', total_len) + chr(rnd_len) + (b' ' * (rnd_len - 1)) + data
crc = (0xffffffff - binascii.crc32(data)) & 0xffffffff
data += struct.pack('<I', crc)
data_to_send = self._encryptor.encrypt(data) data_to_send = self._encryptor.encrypt(data)
self._data_to_write_to_remote.append(data_to_send) self._data_to_write_to_remote.append(data_to_send)
# notice here may go into _handle_dns_resolved directly # notice here may go into _handle_dns_resolved directly
@ -534,7 +549,7 @@ class TCPRelayHandler(object):
self._update_activity(len(data)) self._update_activity(len(data))
if not is_local: if not is_local:
if self._encrypt_correct: if self._encrypt_correct:
obfs_decode = self._obfs.decode(data) obfs_decode = self._obfs.server_decode(data)
if obfs_decode[2]: if obfs_decode[2]:
self._write_to_sock("", self._local_sock) self._write_to_sock("", self._local_sock)
if obfs_decode[1]: if obfs_decode[1]:
@ -547,6 +562,7 @@ class TCPRelayHandler(object):
if self._stage == STAGE_STREAM: if self._stage == STAGE_STREAM:
if self._is_local: if self._is_local:
data = self._encryptor.encrypt(data) data = self._encryptor.encrypt(data)
data = self._obfs.client_encode(data)
self._write_to_sock(data, self._remote_sock) self._write_to_sock(data, self._remote_sock)
return return
elif is_local and self._stage == STAGE_INIT: elif is_local and self._stage == STAGE_INIT:
@ -590,7 +606,10 @@ class TCPRelayHandler(object):
self._server.server_transfer_dl += len(data) self._server.server_transfer_dl += len(data)
self._update_activity(len(data)) self._update_activity(len(data))
if self._is_local: if self._is_local:
data = self._encryptor.decrypt(data) obfs_decode = self._obfs.client_decode(data)
if obfs_decode[1]:
self._write_to_sock("", self._remote_sock)
data = self._encryptor.decrypt(obfs_decode[0])
else: else:
if self._encrypt_correct: if self._encrypt_correct:
data = self._encryptor.encrypt(data) data = self._encryptor.encrypt(data)

28
shadowsocks/udprelay.py

@ -196,16 +196,20 @@ class RecvQueue(object):
if self.end_id == pack_id: if self.end_id == pack_id:
self.end_id = pack_id + 1 self.end_id = pack_id + 1
elif self.end_id < pack_id: elif self.end_id < pack_id:
for eid in xrange(self.end_id, pack_id): eid = self.end_id
while eid < pack_id:
self.miss_queue.add(eid) self.miss_queue.add(eid)
eid += 1
self.end_id = pack_id + 1 self.end_id = pack_id + 1
else: else:
self.miss_queue.remove(pack_id) self.miss_queue.remove(pack_id)
def set_end(self, end_id): def set_end(self, end_id):
if end_id > self.end_id: if end_id > self.end_id:
for eid in xrange(self.end_id, end_id): eid = self.end_id
while eid < pack_id:
self.miss_queue.add(eid) self.miss_queue.add(eid)
eid += 1
self.end_id = end_id self.end_id = end_id
def get_begin_id(self): def get_begin_id(self):
@ -302,7 +306,7 @@ class TCPRelayHandler(object):
#loop.add(local_sock, eventloop.POLL_IN | eventloop.POLL_ERR) #loop.add(local_sock, eventloop.POLL_IN | eventloop.POLL_ERR)
self.last_activity = 0 self.last_activity = 0
self._update_activity() self._update_activity()
self._random_mtu_size = [random.randint(POST_MTU_MIN, POST_MTU_MAX) for i in xrange(1024)] self._random_mtu_size = [random.randint(POST_MTU_MIN, POST_MTU_MAX) for i in range(1024)]
self._random_mtu_index = 0 self._random_mtu_index = 0
self._rand_data = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" * 4 self._rand_data = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" * 4
@ -474,7 +478,7 @@ class TCPRelayHandler(object):
addr = self.get_local_address() addr = self.get_local_address()
for i in xrange(2): for i in range(2):
rsp_data = self._pack_rsp_data(CMD_RSP_CONNECT_REMOTE, RSP_STATE_CONNECTEDREMOTE) rsp_data = self._pack_rsp_data(CMD_RSP_CONNECT_REMOTE, RSP_STATE_CONNECTEDREMOTE)
self._write_to_sock(rsp_data, self._local_sock, addr) self._write_to_sock(rsp_data, self._local_sock, addr)
@ -671,7 +675,7 @@ class TCPRelayHandler(object):
if self._stage == STAGE_RSP_ID: if self._stage == STAGE_RSP_ID:
if cmd == CMD_CONNECT: if cmd == CMD_CONNECT:
for i in xrange(2): for i in range(2):
rsp_data = self._pack_rsp_data(CMD_RSP_CONNECT, RSP_STATE_CONNECTED) rsp_data = self._pack_rsp_data(CMD_RSP_CONNECT, RSP_STATE_CONNECTED)
self._write_to_sock(rsp_data, self._local_sock, addr) self._write_to_sock(rsp_data, self._local_sock, addr)
elif cmd == CMD_CONNECT_REMOTE: elif cmd == CMD_CONNECT_REMOTE:
@ -695,7 +699,7 @@ class TCPRelayHandler(object):
if cmd == CMD_CONNECT_REMOTE: if cmd == CMD_CONNECT_REMOTE:
local_id = data[0:4] local_id = data[0:4]
if self._local_id == local_id: if self._local_id == local_id:
for i in xrange(2): for i in range(2):
rsp_data = self._pack_rsp_data(CMD_RSP_CONNECT_REMOTE, RSP_STATE_CONNECTEDREMOTE) rsp_data = self._pack_rsp_data(CMD_RSP_CONNECT_REMOTE, RSP_STATE_CONNECTEDREMOTE)
self._write_to_sock(rsp_data, self._local_sock, addr) self._write_to_sock(rsp_data, self._local_sock, addr)
else: else:
@ -927,7 +931,7 @@ class UDPRelay(object):
def _pre_parse_udp_header(self, data): def _pre_parse_udp_header(self, data):
if data is None: if data is None:
return return
datatype = ord(data[0]) datatype = common.ord(data[0])
if datatype == 0x8: if datatype == 0x8:
if len(data) >= 8: if len(data) >= 8:
crc = binascii.crc32(data) & 0xffffffff crc = binascii.crc32(data) & 0xffffffff
@ -935,17 +939,17 @@ class UDPRelay(object):
logging.warn('uncorrect CRC32, maybe wrong password or ' logging.warn('uncorrect CRC32, maybe wrong password or '
'encryption method') 'encryption method')
return None return None
cmd = ord(data[1]) cmd = common.ord(data[1])
request_id = struct.unpack('>H', data[2:4])[0] request_id = struct.unpack('>H', data[2:4])[0]
data = data[4:-4] data = data[4:-4]
return (cmd, request_id, data) return (cmd, request_id, data)
elif len(data) >= 6 and ord(data[1]) == 0x0: elif len(data) >= 6 and common.ord(data[1]) == 0x0:
crc = binascii.crc32(data) & 0xffffffff crc = binascii.crc32(data) & 0xffffffff
if crc != 0xffffffff: if crc != 0xffffffff:
logging.warn('uncorrect CRC32, maybe wrong password or ' logging.warn('uncorrect CRC32, maybe wrong password or '
'encryption method') 'encryption method')
return None return None
cmd = ord(data[1]) cmd = common.ord(data[1])
data = data[2:-4] data = data[2:-4]
return (cmd, 0, data) return (cmd, 0, data)
else: else:
@ -994,12 +998,12 @@ class UDPRelay(object):
try: try:
if data[0] == 0: if data[0] == 0:
if len(data[2]) >= 4: if len(data[2]) >= 4:
for i in xrange(64): for i in range(64):
req_id = random.randint(1, 65535) req_id = random.randint(1, 65535)
if req_id not in self._reqid_to_hd: if req_id not in self._reqid_to_hd:
break break
if req_id in self._reqid_to_hd: if req_id in self._reqid_to_hd:
for i in xrange(64): for i in range(64):
req_id = random.randint(1, 65535) req_id = random.randint(1, 65535)
if type(self._reqid_to_hd[req_id]) is tuple: if type(self._reqid_to_hd[req_id]) is tuple:
break break

Loading…
Cancel
Save