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
return m[0](method)
def encode(self, buf):
#if len(buf) == 0:
# return buf
return self.obfs.encode(buf)
def decode(self, buf):
#if len(buf) == 0:
# return (buf, True, False)
return self.obfs.decode(buf)
def client_encode(self, buf):
return self.obfs.client_encode(buf)
def client_decode(self, buf):
return self.obfs.client_decode(buf)
def server_encode(self, buf):
return self.obfs.server_encode(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.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:
return buf
else:
@ -50,7 +58,7 @@ class http_simple(object):
self.has_sent_header = True
return header + buf
def decode(self, buf):
def server_decode(self, buf):
if self.has_recv_header:
return (buf, True, False)
else:

11
shadowsocks/obfsplugin/plain.py

@ -33,9 +33,16 @@ class plain(object):
def __init__(self, method):
self.method = method
def encode(self, buf):
def client_encode(self, 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)
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 'True' to use new protocol ONLY, to avoid GFW detecting
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
TIMEOUTS_CLEAN_SIZE = 512
@ -250,9 +252,12 @@ class TCPRelayHandler(object):
return True
else:
try:
if sock == self._local_sock and self._encrypt_correct:
obfs_encode = self._obfs.encode(data)
data = obfs_encode
if self._is_local:
pass
else:
if sock == self._local_sock and self._encrypt_correct:
obfs_encode = self._obfs.server_encode(data)
data = obfs_encode
l = len(data)
s = sock.send(data)
if s < l:
@ -303,7 +308,7 @@ class TCPRelayHandler(object):
def _handel_protocol_error(self, client_address, ogn_data):
#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
#create redirect or disconnect by hash code
host, port = self._get_redirect_host(client_address, ogn_data)
@ -314,6 +319,7 @@ class TCPRelayHandler(object):
def _handle_stage_connecting(self, data):
if self._is_local:
data = self._encryptor.encrypt(data)
data = self._obfs.client_encode(data)
self._data_to_write_to_remote.append(data)
if self._is_local and not self._fastopen_connected and \
self._config['fast_open']:
@ -377,15 +383,18 @@ class TCPRelayHandler(object):
return
before_parse_data = data
if FORCE_NEW_PROTOCOL and 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)
if self._is_local:
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
logging.info('%s connecting %s:%d from %s:%d' %
((connecttype == 0) and 'TCP' or 'UDP',
@ -401,6 +410,12 @@ class TCPRelayHandler(object):
self._write_to_sock((b'\x05\x00\x00\x01'
b'\x00\x00\x00\x00\x10\x10'),
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)
self._data_to_write_to_remote.append(data_to_send)
# notice here may go into _handle_dns_resolved directly
@ -534,7 +549,7 @@ class TCPRelayHandler(object):
self._update_activity(len(data))
if not is_local:
if self._encrypt_correct:
obfs_decode = self._obfs.decode(data)
obfs_decode = self._obfs.server_decode(data)
if obfs_decode[2]:
self._write_to_sock("", self._local_sock)
if obfs_decode[1]:
@ -547,6 +562,7 @@ class TCPRelayHandler(object):
if self._stage == STAGE_STREAM:
if self._is_local:
data = self._encryptor.encrypt(data)
data = self._obfs.client_encode(data)
self._write_to_sock(data, self._remote_sock)
return
elif is_local and self._stage == STAGE_INIT:
@ -590,7 +606,10 @@ class TCPRelayHandler(object):
self._server.server_transfer_dl += len(data)
self._update_activity(len(data))
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:
if self._encrypt_correct:
data = self._encryptor.encrypt(data)

28
shadowsocks/udprelay.py

@ -196,16 +196,20 @@ class RecvQueue(object):
if self.end_id == pack_id:
self.end_id = pack_id + 1
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)
eid += 1
self.end_id = pack_id + 1
else:
self.miss_queue.remove(pack_id)
def set_end(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)
eid += 1
self.end_id = end_id
def get_begin_id(self):
@ -302,7 +306,7 @@ class TCPRelayHandler(object):
#loop.add(local_sock, eventloop.POLL_IN | eventloop.POLL_ERR)
self.last_activity = 0
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._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()
for i in xrange(2):
for i in range(2):
rsp_data = self._pack_rsp_data(CMD_RSP_CONNECT_REMOTE, RSP_STATE_CONNECTEDREMOTE)
self._write_to_sock(rsp_data, self._local_sock, addr)
@ -671,7 +675,7 @@ class TCPRelayHandler(object):
if self._stage == STAGE_RSP_ID:
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)
self._write_to_sock(rsp_data, self._local_sock, addr)
elif cmd == CMD_CONNECT_REMOTE:
@ -695,7 +699,7 @@ class TCPRelayHandler(object):
if cmd == CMD_CONNECT_REMOTE:
local_id = data[0:4]
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)
self._write_to_sock(rsp_data, self._local_sock, addr)
else:
@ -927,7 +931,7 @@ class UDPRelay(object):
def _pre_parse_udp_header(self, data):
if data is None:
return
datatype = ord(data[0])
datatype = common.ord(data[0])
if datatype == 0x8:
if len(data) >= 8:
crc = binascii.crc32(data) & 0xffffffff
@ -935,17 +939,17 @@ class UDPRelay(object):
logging.warn('uncorrect CRC32, maybe wrong password or '
'encryption method')
return None
cmd = ord(data[1])
cmd = common.ord(data[1])
request_id = struct.unpack('>H', data[2:4])[0]
data = data[4:-4]
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
if crc != 0xffffffff:
logging.warn('uncorrect CRC32, maybe wrong password or '
'encryption method')
return None
cmd = ord(data[1])
cmd = common.ord(data[1])
data = data[2:-4]
return (cmd, 0, data)
else:
@ -994,12 +998,12 @@ class UDPRelay(object):
try:
if data[0] == 0:
if len(data[2]) >= 4:
for i in xrange(64):
for i in range(64):
req_id = random.randint(1, 65535)
if req_id not in self._reqid_to_hd:
break
if req_id in self._reqid_to_hd:
for i in xrange(64):
for i in range(64):
req_id = random.randint(1, 65535)
if type(self._reqid_to_hd[req_id]) is tuple:
break

Loading…
Cancel
Save