diff --git a/config.json b/config.json index 11b34c2..2052b0d 100644 --- a/config.json +++ b/config.json @@ -7,7 +7,7 @@ "password":"m", "timeout":300, "method":"aes-256-cfb", - "obfs":"http_simple", + "obfs":"http_simple_compatible", "fast_open": false, "workers": 1 } diff --git a/shadowsocks/obfsplugin/http_simple.py b/shadowsocks/obfsplugin/http_simple.py index 9695136..f9d0476 100644 --- a/shadowsocks/obfsplugin/http_simple.py +++ b/shadowsocks/obfsplugin/http_simple.py @@ -43,9 +43,13 @@ def create_random_head_obfs(method): obfs = { 'http_simple': (create_http_obfs,), + 'http_simple_compatible': (create_http_obfs,), 'http2_simple': (create_http2_obfs,), + 'http2_simple_compatible': (create_http2_obfs,), 'tls_simple': (create_tls_obfs,), + 'tls_simple_compatible': (create_tls_obfs,), 'random_head': (create_random_head_obfs,), + 'random_head_compatible': (create_random_head_obfs,), } def match_begin(str1, str2): @@ -95,6 +99,13 @@ class http_simple(plain.plain): return ret_buf return b'' + def not_match_return(self, buf): + self.has_sent_header = True + self.has_recv_header = True + if self.method == 'http_simple': + return (b'E', False, False) + return (buf, True, False) + def server_decode(self, buf): if self.has_recv_header: return (buf, True, False) @@ -103,15 +114,11 @@ class http_simple(plain.plain): if len(buf) > 10: if match_begin(buf, b'GET /') or match_begin(buf, b'POST /'): if len(buf) > 65536: - self.has_sent_header = True - self.has_recv_header = True self.recv_buffer = None - return (buf, True, False) + return self.not_match_return(buf) else: #not http header, run on original protocol - self.has_sent_header = True - self.has_recv_header = True self.recv_buffer = None - return (buf, True, False) + return self.not_match_return(buf) else: self.recv_buffer = buf return (b'', True, False) @@ -128,9 +135,7 @@ class http_simple(plain.plain): else: self.recv_buffer = buf return (b'', True, False) - self.has_sent_header = True - self.has_recv_header = True - return (buf, True, False) + return self.not_match_return(buf) class http2_simple(plain.plain): def __init__(self, method): @@ -157,6 +162,13 @@ class http2_simple(plain.plain): self.has_sent_header = True return header + buf + def not_match_return(self, buf): + self.has_sent_header = True + self.has_recv_header = True + if self.method == 'http2_simple': + return (b'E', False, False) + return (buf, True, False) + def server_decode(self, buf): if self.has_recv_header: return (buf, True, False) @@ -166,10 +178,8 @@ class http2_simple(plain.plain): if match_begin(buf, b'GET /'): pass else: #not http header, run on original protocol - self.has_sent_header = True - self.has_recv_header = True self.recv_buffer = None - return (buf, True, False) + return self.not_match_return(buf) else: self.recv_buffer = buf return (b'', True, False) @@ -188,9 +198,7 @@ class http2_simple(plain.plain): else: self.recv_buffer = buf return (b'', True, False) - self.has_sent_header = True - self.has_recv_header = True - return (buf, True, False) + return self.not_match_return(buf) class tls_simple(plain.plain): def __init__(self, method): @@ -220,6 +228,8 @@ class tls_simple(plain.plain): self.has_recv_header = True if not match_begin(buf, b'\x16\x03\x01'): self.has_sent_header = True + if self.method == 'tls_simple': + return (b'E', False, False) return (buf, True, False) # (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) return (b'', False, True) @@ -251,6 +261,8 @@ class random_head(plain.plain): crc = binascii.crc32(buf) & 0xffffffff if crc != 0xffffffff: self.has_sent_header = True + if self.method == 'random_head': + return (b'E', False, False) return (buf, True, False) # (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) return (b'', False, True) diff --git a/shadowsocks/obfsplugin/verify_simple.py b/shadowsocks/obfsplugin/verify_simple.py index ed22b62..f89e743 100644 --- a/shadowsocks/obfsplugin/verify_simple.py +++ b/shadowsocks/obfsplugin/verify_simple.py @@ -48,6 +48,8 @@ class verify_simple(plain.plain): self.method = method self.recv_buf = b'' self.unit_len = 8100 + self.decrypt_packet_num = 0 + self.raw_trans = False def pack_data(self, buf): if len(buf) == 0: @@ -75,7 +77,37 @@ class verify_simple(plain.plain): return (buf, False) def client_post_decrypt(self, buf): - return buf + if self.raw_trans: + return buf + self.recv_buf += buf + out_buf = b'' + while len(self.recv_buf) > 2: + length = struct.unpack('>H', self.recv_buf[:2])[0] + if length >= 8192: + self.raw_trans = True + self.recv_buf = b'' + if self.decrypt_packet_num == 0: + return None + else: + raise Exception('server_post_decrype data error') + if length > len(self.recv_buf): + break + + if (binascii.crc32(self.recv_buf[:length]) & 0xffffffff) != 0xffffffff: + self.raw_trans = True + self.recv_buf = b'' + if self.decrypt_packet_num == 0: + return None + else: + raise Exception('server_post_decrype data uncorrect CRC32') + + pos = common.ord(self.recv_buf[2]) + 2 + out_buf += self.recv_buf[pos:length - 4] + self.recv_buf = self.recv_buf[length:] + + if out_buf: + self.decrypt_packet_num += 1 + return out_buf def server_pre_encrypt(self, buf): ret = b'' @@ -93,21 +125,35 @@ class verify_simple(plain.plain): return (buf, True, False) def server_post_decrypt(self, buf): + if self.raw_trans: + return buf self.recv_buf += buf out_buf = b'' while len(self.recv_buf) > 2: length = struct.unpack('>H', self.recv_buf[:2])[0] if length >= 8192: - raise Exception('server_post_decrype data error') + self.raw_trans = True + self.recv_buf = b'' + if self.decrypt_packet_num == 0: + return b'E' + else: + raise Exception('server_post_decrype data error') if length > len(self.recv_buf): break if (binascii.crc32(self.recv_buf[:length]) & 0xffffffff) != 0xffffffff: - raise Exception('server_post_decrype data uncorrect CRC32') + self.raw_trans = True + self.recv_buf = b'' + if self.decrypt_packet_num == 0: + return b'E' + else: + raise Exception('server_post_decrype data uncorrect CRC32') pos = common.ord(self.recv_buf[2]) + 2 out_buf += self.recv_buf[pos:length - 4] self.recv_buf = self.recv_buf[length:] + if out_buf: + self.decrypt_packet_num += 1 return out_buf diff --git a/shadowsocks/tcprelay.py b/shadowsocks/tcprelay.py index 6062996..99ac9b3 100644 --- a/shadowsocks/tcprelay.py +++ b/shadowsocks/tcprelay.py @@ -390,7 +390,7 @@ class TCPRelayHandler(object): if self._is_local: header_result = parse_header(data) else: - if FORCE_NEW_PROTOCOL and common.ord(data[0]) != 0x88: + if data is None or 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: