From 463ce07426f3220e9dfe301f23a859273e5837ff Mon Sep 17 00:00:00 2001 From: breakwa11 Date: Sun, 4 Oct 2015 19:56:58 +0800 Subject: [PATCH] add verify_simple module --- shadowsocks/obfs.py | 15 +++- shadowsocks/obfsplugin/http_simple.py | 11 ++- shadowsocks/obfsplugin/plain.py | 13 +++ shadowsocks/obfsplugin/verify_simple.py | 113 ++++++++++++++++++++++++ shadowsocks/tcprelay.py | 11 ++- 5 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 shadowsocks/obfsplugin/verify_simple.py diff --git a/shadowsocks/obfs.py b/shadowsocks/obfs.py index 9d6d58e..69eed0b 100644 --- a/shadowsocks/obfs.py +++ b/shadowsocks/obfs.py @@ -23,12 +23,13 @@ import hashlib import logging from shadowsocks import common -from shadowsocks.obfsplugin import plain, http_simple +from shadowsocks.obfsplugin import plain, http_simple, verify_simple method_supported = {} method_supported.update(plain.obfs) method_supported.update(http_simple.obfs) +method_supported.update(verify_simple.obfs) class Obfs(object): def __init__(self, method): @@ -49,15 +50,27 @@ class Obfs(object): m = self._method_info return m[0](method) + def client_pre_encrypt(self, buf): + return self.obfs.client_pre_encrypt(buf) + def client_encode(self, buf): return self.obfs.client_encode(buf) def client_decode(self, buf): return self.obfs.client_decode(buf) + def client_post_decrypt(self, buf): + return self.obfs.client_post_decrypt(buf) + + def server_pre_encrypt(self, buf): + return self.obfs.server_pre_encrypt(buf) + def server_encode(self, buf): return self.obfs.server_encode(buf) def server_decode(self, buf): return self.obfs.server_decode(buf) + def server_post_decrypt(self, buf): + return self.obfs.server_post_decrypt(buf) + diff --git a/shadowsocks/obfsplugin/http_simple.py b/shadowsocks/obfsplugin/http_simple.py index 6df2f2e..9695136 100644 --- a/shadowsocks/obfsplugin/http_simple.py +++ b/shadowsocks/obfsplugin/http_simple.py @@ -24,6 +24,8 @@ import logging import binascii import base64 import datetime + +from shadowsocks.obfsplugin import plain from shadowsocks import common from shadowsocks.common import to_bytes, to_str, ord @@ -52,7 +54,7 @@ def match_begin(str1, str2): return True return False -class http_simple(object): +class http_simple(plain.plain): def __init__(self, method): self.method = method self.has_sent_header = False @@ -130,7 +132,7 @@ class http_simple(object): self.has_recv_header = True return (buf, True, False) -class http2_simple(object): +class http2_simple(plain.plain): def __init__(self, method): self.method = method self.has_sent_header = False @@ -190,7 +192,7 @@ class http2_simple(object): self.has_recv_header = True return (buf, True, False) -class tls_simple(object): +class tls_simple(plain.plain): def __init__(self, method): self.method = method self.has_sent_header = False @@ -222,7 +224,7 @@ class tls_simple(object): # (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) return (b'', False, True) -class random_head(object): +class random_head(plain.plain): def __init__(self, method): self.method = method self.has_sent_header = False @@ -252,3 +254,4 @@ class random_head(object): 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/plain.py b/shadowsocks/obfsplugin/plain.py index 5834f89..a40b993 100644 --- a/shadowsocks/obfsplugin/plain.py +++ b/shadowsocks/obfsplugin/plain.py @@ -33,6 +33,9 @@ class plain(object): def __init__(self, method): self.method = method + def client_pre_encrypt(self, buf): + return buf + def client_encode(self, buf): return buf @@ -40,9 +43,19 @@ class plain(object): # (buffer_to_recv, is_need_to_encode_and_send_back) return (buf, False) + def client_post_decrypt(self, buf): + return buf + + def server_pre_encrypt(self, buf): + return buf + 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) + + def server_post_decrypt(self, buf): + return buf + diff --git a/shadowsocks/obfsplugin/verify_simple.py b/shadowsocks/obfsplugin/verify_simple.py new file mode 100644 index 0000000..ed22b62 --- /dev/null +++ b/shadowsocks/obfsplugin/verify_simple.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +# +# Copyright 2015-2015 breakwa11 +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from __future__ import absolute_import, division, print_function, \ + with_statement + +import os +import sys +import hashlib +import logging +import binascii +import base64 +import datetime +import struct + +from shadowsocks.obfsplugin import plain +from shadowsocks import common +from shadowsocks.common import to_bytes, to_str, ord + +def create_verify_obfs(method): + return verify_simple(method) + +obfs = { + 'verify_simple': (create_verify_obfs,), +} + +def match_begin(str1, str2): + if len(str1) >= len(str2): + if str1[:len(str2)] == str2: + return True + return False + +class verify_simple(plain.plain): + def __init__(self, method): + self.method = method + self.recv_buf = b'' + self.unit_len = 8100 + + def pack_data(self, buf): + if len(buf) == 0: + return b'' + rnd_data = os.urandom(common.ord(os.urandom(1)[0]) % 16) + data = common.chr(len(rnd_data) + 1) + rnd_data + buf + data = struct.pack('>H', len(data) + 6) + data + crc = (0xffffffff - binascii.crc32(data)) & 0xffffffff + data += struct.pack(' self.unit_len: + ret += self.pack_data(buf[:self.unit_len]) + buf = buf[self.unit_len:] + ret += self.pack_data(buf) + return ret + + def client_encode(self, buf): + return buf + + def client_decode(self, buf): + # (buffer_to_recv, is_need_to_encode_and_send_back) + return (buf, False) + + def client_post_decrypt(self, buf): + return buf + + def server_pre_encrypt(self, buf): + ret = b'' + while len(buf) > self.unit_len: + ret += self.pack_data(buf[:self.unit_len]) + buf = buf[self.unit_len:] + ret += self.pack_data(buf) + return ret + + 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) + + def server_post_decrypt(self, 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') + if length > len(self.recv_buf): + break + + if (binascii.crc32(self.recv_buf[:length]) & 0xffffffff) != 0xffffffff: + 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:] + + return out_buf + diff --git a/shadowsocks/tcprelay.py b/shadowsocks/tcprelay.py index 7e2b305..6062996 100644 --- a/shadowsocks/tcprelay.py +++ b/shadowsocks/tcprelay.py @@ -321,6 +321,7 @@ class TCPRelayHandler(object): def _handle_stage_connecting(self, data): if self._is_local: + data = self._obfs.client_pre_encrypt(data) data = self._encryptor.encrypt(data) data = self._obfs.client_encode(data) self._data_to_write_to_remote.append(data) @@ -419,6 +420,7 @@ class TCPRelayHandler(object): 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('