Browse Source

add verify_simple module

dev
breakwa11 9 years ago
parent
commit
463ce07426
  1. 15
      shadowsocks/obfs.py
  2. 11
      shadowsocks/obfsplugin/http_simple.py
  3. 13
      shadowsocks/obfsplugin/plain.py
  4. 113
      shadowsocks/obfsplugin/verify_simple.py
  5. 11
      shadowsocks/tcprelay.py

15
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)

11
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)

13
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

113
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('<I', crc)
return data
def client_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 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

11
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('<I', crc)
data = self._obfs.client_pre_encrypt(data)
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
@ -559,11 +561,17 @@ class TCPRelayHandler(object):
data = self._encryptor.decrypt(obfs_decode[0])
else:
data = obfs_decode[0]
try:
data = self._obfs.server_post_decrypt(data)
except Exception as e:
shell.print_exception(e)
self.destroy()
if not data:
return
self._server.server_transfer_ul += len(data)
if self._stage == STAGE_STREAM:
if self._is_local:
data = self._obfs.client_pre_encrypt(data)
data = self._encryptor.encrypt(data)
data = self._obfs.client_encode(data)
self._write_to_sock(data, self._remote_sock)
@ -613,8 +621,10 @@ class TCPRelayHandler(object):
if obfs_decode[1]:
self._write_to_sock(b'', self._remote_sock)
data = self._encryptor.decrypt(obfs_decode[0])
data = self._obfs.client_post_decrypt(data)
else:
if self._encrypt_correct:
data = self._obfs.server_pre_encrypt(data)
data = self._encryptor.encrypt(data)
try:
self._write_to_sock(data, self._local_sock)
@ -730,7 +740,6 @@ class TCPRelayHandler(object):
self._dns_resolver.remove_callback(self._handle_dns_resolved)
self._server.remove_handler(self)
class TCPRelay(object):
def __init__(self, config, dns_resolver, is_local, stat_callback=None):
self._config = config

Loading…
Cancel
Save