Browse Source

add obfs_param

catch TCP&UDP exceptions
verify_simple&verify_deflate support sub obfs
dev
breakwa11 9 years ago
parent
commit
612c1e2ab3
  1. 15
      config.json
  2. 2
      server.py
  3. 21
      shadowsocks/obfs.py
  4. 4
      shadowsocks/obfsplugin/http_simple.py
  5. 9
      shadowsocks/obfsplugin/plain.py
  6. 71
      shadowsocks/obfsplugin/verify_simple.py
  7. 1
      shadowsocks/shell.py
  8. 39
      shadowsocks/tcprelay.py
  9. 23
      shadowsocks/udprelay.py

15
config.json

@ -1,13 +1,14 @@
{ {
"server":"0.0.0.0", "server": "0.0.0.0",
"server_ipv6": "::", "server_ipv6": "::",
"server_port":8388, "server_port": 8388,
"local_address": "127.0.0.1", "local_address": "127.0.0.1",
"local_port":1080, "local_port": 1080,
"password":"m", "password": "m",
"timeout":300, "timeout": 300,
"method":"aes-256-cfb", "method": "aes-256-cfb",
"obfs":"http_simple_compatible", "obfs": "http_simple_compatible",
"obfs_param": "",
"fast_open": false, "fast_open": false,
"workers": 1 "workers": 1
} }

2
server.py

@ -22,7 +22,7 @@ class MainThread(threading.Thread):
def main(): def main():
shell.check_python() shell.check_python()
if len(sys.argv) <= 3: if True:
db_transfer.DbTransfer.thread_db() db_transfer.DbTransfer.thread_db()
else: else:
thread = MainThread() thread = MainThread()

21
shadowsocks/obfs.py

@ -27,19 +27,28 @@ from shadowsocks.obfsplugin import plain, http_simple, verify_simple
method_supported = {} method_supported = {}
method_supported.update(plain.obfs) method_supported.update(plain.obfs_map)
method_supported.update(http_simple.obfs) method_supported.update(http_simple.obfs_map)
method_supported.update(verify_simple.obfs) method_supported.update(verify_simple.obfs_map)
class Obfs(object): class server_info(object):
def __init__(self, data):
self.data = data
class obfs(object):
def __init__(self, method): def __init__(self, method):
self.method = method self.method = method
self._method_info = self.get_method_info(method) self._method_info = self.get_method_info(method)
if self._method_info: if self._method_info:
self.obfs = self.get_obfs(method) self.obfs = self.get_obfs(method)
else: else:
logging.error('method %s not supported' % method) raise Exception('method %s not supported' % method)
sys.exit(1)
def init_data(self):
return self.obfs.init_data()
def set_server_info(self, server_info):
return self.obfs.set_server_info(server_info)
def get_method_info(self, method): def get_method_info(self, method):
method = method.lower() method = method.lower()

4
shadowsocks/obfsplugin/http_simple.py

@ -25,8 +25,8 @@ import binascii
import base64 import base64
import datetime import datetime
from shadowsocks.obfsplugin import plain
from shadowsocks import common from shadowsocks import common
from shadowsocks.obfsplugin import plain
from shadowsocks.common import to_bytes, to_str, ord from shadowsocks.common import to_bytes, to_str, ord
def create_http_obfs(method): def create_http_obfs(method):
@ -41,7 +41,7 @@ def create_tls_obfs(method):
def create_random_head_obfs(method): def create_random_head_obfs(method):
return random_head(method) return random_head(method)
obfs = { obfs_map = {
'http_simple': (create_http_obfs,), 'http_simple': (create_http_obfs,),
'http_simple_compatible': (create_http_obfs,), 'http_simple_compatible': (create_http_obfs,),
'http2_simple': (create_http2_obfs,), 'http2_simple': (create_http2_obfs,),

9
shadowsocks/obfsplugin/plain.py

@ -25,13 +25,20 @@ import logging
def create_obfs(method): def create_obfs(method):
return plain(method) return plain(method)
obfs = { obfs_map = {
'plain': (create_obfs,), 'plain': (create_obfs,),
} }
class plain(object): class plain(object):
def __init__(self, method): def __init__(self, method):
self.method = method self.method = method
self.server_info = None
def init_data(self):
return b''
def set_server_info(self, server_info):
self.server_info = server_info
def client_pre_encrypt(self, buf): def client_pre_encrypt(self, buf):
return buf return buf

71
shadowsocks/obfsplugin/verify_simple.py

@ -27,8 +27,9 @@ import datetime
import struct import struct
import zlib import zlib
from shadowsocks.obfsplugin import plain import shadowsocks
from shadowsocks import common from shadowsocks import common
from shadowsocks.obfsplugin import plain
from shadowsocks.common import to_bytes, to_str, ord from shadowsocks.common import to_bytes, to_str, ord
def create_verify_obfs(method): def create_verify_obfs(method):
@ -37,7 +38,7 @@ def create_verify_obfs(method):
def create_verify_deflate(method): def create_verify_deflate(method):
return verify_deflate(method) return verify_deflate(method)
obfs = { obfs_map = {
'verify_simple': (create_verify_obfs,), 'verify_simple': (create_verify_obfs,),
'verify_deflate': (create_verify_deflate,), 'verify_deflate': (create_verify_deflate,),
} }
@ -48,6 +49,10 @@ def match_begin(str1, str2):
return True return True
return False return False
class sub_encode_obfs(object):
def __init__(self):
self.sub_obfs = None
class verify_simple(plain.plain): class verify_simple(plain.plain):
def __init__(self, method): def __init__(self, method):
self.method = method self.method = method
@ -55,6 +60,26 @@ class verify_simple(plain.plain):
self.unit_len = 8100 self.unit_len = 8100
self.decrypt_packet_num = 0 self.decrypt_packet_num = 0
self.raw_trans = False self.raw_trans = False
self.sub_obfs = None
def init_data(self):
return sub_encode_obfs()
def set_server_info(self, server_info):
try:
if server_info.param:
self.sub_obfs = shadowsocks.obfs.obfs(server_info.param)
if server_info.data.sub_obfs is None:
server_info.data.sub_obfs = self.sub_obfs.init_data()
_server_info = shadowsocks.obfs.server_info(server_info.data.sub_obfs)
_server_info.host = server_info.host
_server_info.port = server_info.port
_server_info.tcp_mss = server_info.tcp_mss
_server_info.param = ''
self.sub_obfs.set_server_info(_server_info)
except Exception as e:
shadowsocks.shell.print_exception(e)
self.server_info = server_info
def pack_data(self, buf): def pack_data(self, buf):
if len(buf) == 0: if len(buf) == 0:
@ -75,10 +100,13 @@ class verify_simple(plain.plain):
return ret return ret
def client_encode(self, buf): def client_encode(self, buf):
if self.sub_obfs is not None:
return self.sub_obfs.client_encode(buf)
return buf return buf
def client_decode(self, buf): def client_decode(self, buf):
# (buffer_to_recv, is_need_to_encode_and_send_back) if self.sub_obfs is not None:
return self.sub_obfs.client_decode(buf)
return (buf, False) return (buf, False)
def client_post_decrypt(self, buf): def client_post_decrypt(self, buf):
@ -123,10 +151,13 @@ class verify_simple(plain.plain):
return ret return ret
def server_encode(self, buf): def server_encode(self, buf):
if self.sub_obfs is not None:
return self.sub_obfs.server_encode(buf)
return buf return buf
def server_decode(self, buf): def server_decode(self, buf):
# (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) if self.sub_obfs is not None:
return self.sub_obfs.server_decode(buf)
return (buf, True, False) return (buf, True, False)
def server_post_decrypt(self, buf): def server_post_decrypt(self, buf):
@ -169,6 +200,26 @@ class verify_deflate(plain.plain):
self.unit_len = 32700 self.unit_len = 32700
self.decrypt_packet_num = 0 self.decrypt_packet_num = 0
self.raw_trans = False self.raw_trans = False
self.sub_obfs = None
def init_data(self):
return sub_encode_obfs()
def set_server_info(self, server_info):
try:
if server_info.param:
self.sub_obfs = shadowsocks.obfs.obfs(server_info.param)
if server_info.data.sub_obfs is None:
server_info.data.sub_obfs = self.sub_obfs.init_data()
_server_info = shadowsocks.obfs.server_info(server_info.data.sub_obfs)
_server_info.host = server_info.host
_server_info.port = server_info.port
_server_info.tcp_mss = server_info.tcp_mss
_server_info.param = ''
self.sub_obfs.set_server_info(_server_info)
except Exception as e:
shadowsocks.shell.print_exception(e)
self.server_info = server_info
def pack_data(self, buf): def pack_data(self, buf):
if len(buf) == 0: if len(buf) == 0:
@ -186,10 +237,13 @@ class verify_deflate(plain.plain):
return ret return ret
def client_encode(self, buf): def client_encode(self, buf):
if self.sub_obfs is not None:
return self.sub_obfs.client_encode(buf)
return buf return buf
def client_decode(self, buf): def client_decode(self, buf):
# (buffer_to_recv, is_need_to_encode_and_send_back) if self.sub_obfs is not None:
return self.sub_obfs.client_decode(buf)
return (buf, False) return (buf, False)
def client_post_decrypt(self, buf): def client_post_decrypt(self, buf):
@ -225,10 +279,13 @@ class verify_deflate(plain.plain):
return ret return ret
def server_encode(self, buf): def server_encode(self, buf):
if self.sub_obfs is not None:
return self.sub_obfs.server_encode(buf)
return buf return buf
def server_decode(self, buf): def server_decode(self, buf):
# (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) if self.sub_obfs is not None:
return self.sub_obfs.server_decode(buf)
return (buf, True, False) return (buf, True, False)
def server_post_decrypt(self, buf): def server_post_decrypt(self, buf):
@ -248,7 +305,7 @@ class verify_deflate(plain.plain):
if length > len(self.recv_buf): if length > len(self.recv_buf):
break break
out_buf += zlib.decompress(b'x\x9c' + self.recv_buf[2:length]) out_buf += zlib.decompress(b'\x78\x9c' + self.recv_buf[2:length])
self.recv_buf = self.recv_buf[length:] self.recv_buf = self.recv_buf[length:]
if out_buf: if out_buf:

1
shadowsocks/shell.py

@ -217,6 +217,7 @@ def get_config(is_local):
config['password'] = to_bytes(config.get('password', b'')) config['password'] = to_bytes(config.get('password', b''))
config['method'] = to_str(config.get('method', 'aes-256-cfb')) config['method'] = to_str(config.get('method', 'aes-256-cfb'))
config['obfs'] = to_str(config.get('obfs', 'plain')) config['obfs'] = to_str(config.get('obfs', 'plain'))
config['obfs_param'] = to_str(config.get('obfs_param', ''))
config['port_password'] = config.get('port_password', None) config['port_password'] = config.get('port_password', None)
config['timeout'] = int(config.get('timeout', 300)) config['timeout'] = int(config.get('timeout', 300))
config['fast_open'] = config.get('fast_open', False) config['fast_open'] = config.get('fast_open', False)

39
shadowsocks/tcprelay.py

@ -117,7 +117,16 @@ class TCPRelayHandler(object):
self._encryptor = encrypt.Encryptor(config['password'], self._encryptor = encrypt.Encryptor(config['password'],
config['method']) config['method'])
self._encrypt_correct = True self._encrypt_correct = True
self._obfs = obfs.Obfs(config['obfs']) self._obfs = obfs.obfs(config['obfs'])
if server.obfs_data is None:
server.obfs_data = self._obfs.init_data()
server_info = obfs.server_info(server.obfs_data)
server_info.host = config['server']
server_info.port = server._listen_port
server_info.tcp_mss = 1440
server_info.param = config['obfs_param']
self._obfs.set_server_info(server_info)
self._fastopen_connected = False self._fastopen_connected = False
self._data_to_write_to_local = [] self._data_to_write_to_local = []
self._data_to_write_to_remote = [] self._data_to_write_to_remote = []
@ -139,6 +148,7 @@ class TCPRelayHandler(object):
self._server) self._server)
self.last_activity = 0 self.last_activity = 0
self._update_activity() self._update_activity()
self._server.add_connection(1)
def __hash__(self): def __hash__(self):
# default __hash__ is id / 16 # default __hash__ is id / 16
@ -276,6 +286,10 @@ class TCPRelayHandler(object):
shell.print_exception(e) shell.print_exception(e)
self.destroy() self.destroy()
return False return False
except Exception as e:
shell.print_exception(e)
self.destroy()
return False
if uncomplete: if uncomplete:
if sock == self._local_sock: if sock == self._local_sock:
self._data_to_write_to_local.append(data) self._data_to_write_to_local.append(data)
@ -467,7 +481,7 @@ class TCPRelayHandler(object):
remote_sock.setblocking(False) remote_sock.setblocking(False)
if self._remote_udp: if self._remote_udp:
pass remote_sock_v6.setblocking(False)
else: else:
remote_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) remote_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
return remote_sock return remote_sock
@ -515,7 +529,9 @@ class TCPRelayHandler(object):
except (OSError, IOError) as e: except (OSError, IOError) as e:
if eventloop.errno_from_exception(e) == \ if eventloop.errno_from_exception(e) == \
errno.EINPROGRESS: errno.EINPROGRESS:
pass pass # always goto here
else:
raise e
self._loop.add(remote_sock, self._loop.add(remote_sock,
eventloop.POLL_ERR | eventloop.POLL_OUT, eventloop.POLL_ERR | eventloop.POLL_OUT,
self._server) self._server)
@ -721,13 +737,19 @@ class TCPRelayHandler(object):
logging.debug('destroy') logging.debug('destroy')
if self._remote_sock: if self._remote_sock:
logging.debug('destroying remote') logging.debug('destroying remote')
self._loop.remove(self._remote_sock) try:
self._loop.remove(self._remote_sock)
except Exception as e:
pass
del self._fd_to_handlers[self._remote_sock.fileno()] del self._fd_to_handlers[self._remote_sock.fileno()]
self._remote_sock.close() self._remote_sock.close()
self._remote_sock = None self._remote_sock = None
if self._remote_sock_v6: if self._remote_sock_v6:
logging.debug('destroying remote') logging.debug('destroying remote')
self._loop.remove(self._remote_sock_v6) try:
self._loop.remove(self._remote_sock_v6)
except Exception as e:
pass
del self._fd_to_handlers[self._remote_sock_v6.fileno()] del self._fd_to_handlers[self._remote_sock_v6.fileno()]
self._remote_sock_v6.close() self._remote_sock_v6.close()
self._remote_sock_v6 = None self._remote_sock_v6 = None
@ -739,6 +761,7 @@ class TCPRelayHandler(object):
self._local_sock = None self._local_sock = None
self._dns_resolver.remove_callback(self._handle_dns_resolved) self._dns_resolver.remove_callback(self._handle_dns_resolved)
self._server.remove_handler(self) self._server.remove_handler(self)
self._server.add_connection(-1)
class TCPRelay(object): class TCPRelay(object):
def __init__(self, config, dns_resolver, is_local, stat_callback=None): def __init__(self, config, dns_resolver, is_local, stat_callback=None):
@ -750,6 +773,8 @@ class TCPRelay(object):
self._fd_to_handlers = {} self._fd_to_handlers = {}
self.server_transfer_ul = 0 self.server_transfer_ul = 0
self.server_transfer_dl = 0 self.server_transfer_dl = 0
self.server_connections = 0
self.obfs_data = None
self._timeout = config['timeout'] self._timeout = config['timeout']
self._timeouts = [] # a list for all the handlers self._timeouts = [] # a list for all the handlers
@ -802,6 +827,10 @@ class TCPRelay(object):
self._timeouts[index] = None self._timeouts[index] = None
del self._handler_to_timeouts[hash(handler)] del self._handler_to_timeouts[hash(handler)]
def add_connection(self, val):
self.server_connections += val
logging.debug('server port %5d connections = %d' % (self._listen_port, self.server_connections,))
def update_activity(self, handler, data_len): def update_activity(self, handler, data_len):
if data_len and self._stat_callback: if data_len and self._stat_callback:
self._stat_callback(self._listen_port, data_len) self._stat_callback(self._listen_port, data_len)

23
shadowsocks/udprelay.py

@ -1095,6 +1095,12 @@ class UDPRelay(object):
self._sockets.add(client.fileno()) self._sockets.add(client.fileno())
self._eventloop.add(client, eventloop.POLL_IN, self) self._eventloop.add(client, eventloop.POLL_IN, self)
logging.debug('UDP port %5d sockets %d' % (self._listen_port, len(self._sockets)))
logging.info('UDP data to %s:%d from %s:%d' %
(common.to_str(server_addr), server_port,
r_addr[0], r_addr[1]))
if self._is_local: if self._is_local:
data = encrypt.encrypt_all(self._password, self._method, 1, data) data = encrypt.encrypt_all(self._password, self._method, 1, data)
if not data: if not data:
@ -1254,11 +1260,21 @@ class UDPRelay(object):
if sock == self._server_socket: if sock == self._server_socket:
if event & eventloop.POLL_ERR: if event & eventloop.POLL_ERR:
logging.error('UDP server_socket err') logging.error('UDP server_socket err')
self._handle_server() try:
self._handle_server()
except Exception as e:
shell.print_exception(e)
if self._config['verbose']:
traceback.print_exc()
elif sock and (fd in self._sockets): elif sock and (fd in self._sockets):
if event & eventloop.POLL_ERR: if event & eventloop.POLL_ERR:
logging.error('UDP client_socket err') logging.error('UDP client_socket err')
self._handle_client(sock) try:
self._handle_client(sock)
except Exception as e:
shell.print_exception(e)
if self._config['verbose']:
traceback.print_exc()
else: else:
if sock: if sock:
handler = self._fd_to_handlers.get(fd, None) handler = self._fd_to_handlers.get(fd, None)
@ -1275,7 +1291,10 @@ class UDPRelay(object):
for sock in self._sockets: for sock in self._sockets:
sock.close() sock.close()
logging.info('closed UDP port %d', self._listen_port) logging.info('closed UDP port %d', self._listen_port)
before_sweep_size = len(self._sockets)
self._cache.sweep() self._cache.sweep()
if before_sweep_size != len(self._sockets):
logging.debug('UDP port %5d sockets %d' % (self._listen_port, len(self._sockets)))
self._client_fd_to_server_addr.sweep() self._client_fd_to_server_addr.sweep()
self._sweep_timeout() self._sweep_timeout()

Loading…
Cancel
Save