|
@ -135,35 +135,25 @@ class TCPRelayHandler(object): |
|
|
self._remote_udp = False |
|
|
self._remote_udp = False |
|
|
self._config = config |
|
|
self._config = config |
|
|
self._dns_resolver = dns_resolver |
|
|
self._dns_resolver = dns_resolver |
|
|
|
|
|
if not self._create_encryptor(config): |
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
self._client_address = local_sock.getpeername()[:2] |
|
|
self._client_address = local_sock.getpeername()[:2] |
|
|
self._accept_address = local_sock.getsockname()[:2] |
|
|
self._accept_address = local_sock.getsockname()[:2] |
|
|
self._user = None |
|
|
self._user = None |
|
|
self._user_id = server._listen_port |
|
|
self._user_id = server._listen_port |
|
|
self._tcp_mss = TCP_MSS |
|
|
self._update_tcp_mss(local_sock) |
|
|
|
|
|
|
|
|
# TCP Relay works as either sslocal or ssserver |
|
|
# TCP Relay works as either sslocal or ssserver |
|
|
# if is_local, this is sslocal |
|
|
# if is_local, this is sslocal |
|
|
self._is_local = is_local |
|
|
self._is_local = is_local |
|
|
self._stage = STAGE_INIT |
|
|
self._stage = STAGE_INIT |
|
|
try: |
|
|
|
|
|
self._encryptor = encrypt.Encryptor(config['password'], |
|
|
|
|
|
config['method']) |
|
|
|
|
|
except Exception: |
|
|
|
|
|
self._stage = STAGE_DESTROYED |
|
|
|
|
|
logging.error('create encryptor fail at port %d', server._listen_port) |
|
|
|
|
|
return |
|
|
|
|
|
self._encrypt_correct = True |
|
|
self._encrypt_correct = True |
|
|
self._obfs = obfs.obfs(config['obfs']) |
|
|
self._obfs = obfs.obfs(config['obfs']) |
|
|
self._protocol = obfs.obfs(config['protocol']) |
|
|
self._protocol = obfs.obfs(config['protocol']) |
|
|
self._overhead = self._obfs.get_overhead(self._is_local) + self._protocol.get_overhead(self._is_local) |
|
|
self._overhead = self._obfs.get_overhead(self._is_local) + self._protocol.get_overhead(self._is_local) |
|
|
self._recv_buffer_size = BUF_SIZE - self._overhead |
|
|
self._recv_buffer_size = BUF_SIZE - self._overhead |
|
|
|
|
|
|
|
|
try: |
|
|
|
|
|
self._tcp_mss = local_sock.getsockopt(socket.SOL_TCP, socket.TCP_MAXSEG) |
|
|
|
|
|
logging.debug("TCP MSS = %d" % (self._tcp_mss,)) |
|
|
|
|
|
except: |
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
server_info = obfs.server_info(server.obfs_data) |
|
|
server_info = obfs.server_info(server.obfs_data) |
|
|
server_info.host = config['server'] |
|
|
server_info.host = config['server'] |
|
|
server_info.port = server._listen_port |
|
|
server_info.port = server._listen_port |
|
@ -180,6 +170,7 @@ class TCPRelayHandler(object): |
|
|
server_info.head_len = 30 |
|
|
server_info.head_len = 30 |
|
|
server_info.tcp_mss = self._tcp_mss |
|
|
server_info.tcp_mss = self._tcp_mss |
|
|
server_info.buffer_size = self._recv_buffer_size |
|
|
server_info.buffer_size = self._recv_buffer_size |
|
|
|
|
|
server_info.overhead = self._overhead |
|
|
self._obfs.set_server_info(server_info) |
|
|
self._obfs.set_server_info(server_info) |
|
|
|
|
|
|
|
|
server_info = obfs.server_info(server.protocol_data) |
|
|
server_info = obfs.server_info(server.protocol_data) |
|
@ -198,6 +189,7 @@ class TCPRelayHandler(object): |
|
|
server_info.head_len = 30 |
|
|
server_info.head_len = 30 |
|
|
server_info.tcp_mss = self._tcp_mss |
|
|
server_info.tcp_mss = self._tcp_mss |
|
|
server_info.buffer_size = self._recv_buffer_size |
|
|
server_info.buffer_size = self._recv_buffer_size |
|
|
|
|
|
server_info.overhead = self._overhead |
|
|
self._protocol.set_server_info(server_info) |
|
|
self._protocol.set_server_info(server_info) |
|
|
|
|
|
|
|
|
self._redir_list = config.get('redirect', ["*#0.0.0.0:0"]) |
|
|
self._redir_list = config.get('redirect', ["*#0.0.0.0:0"]) |
|
@ -213,27 +205,24 @@ class TCPRelayHandler(object): |
|
|
self._upstream_status = WAIT_STATUS_READING |
|
|
self._upstream_status = WAIT_STATUS_READING |
|
|
self._downstream_status = WAIT_STATUS_INIT |
|
|
self._downstream_status = WAIT_STATUS_INIT |
|
|
self._remote_address = None |
|
|
self._remote_address = None |
|
|
if 'forbidden_ip' in config: |
|
|
|
|
|
self._forbidden_iplist = config['forbidden_ip'] |
|
|
self._forbidden_iplist = config.get('forbidden_ip', None) |
|
|
else: |
|
|
self._forbidden_portset = config.get('forbidden_port', None) |
|
|
self._forbidden_iplist = None |
|
|
|
|
|
if 'forbidden_port' in config: |
|
|
|
|
|
self._forbidden_portset = config['forbidden_port'] |
|
|
|
|
|
else: |
|
|
|
|
|
self._forbidden_portset = None |
|
|
|
|
|
if is_local: |
|
|
if is_local: |
|
|
self._chosen_server = self._get_a_server() |
|
|
self._chosen_server = self._get_a_server() |
|
|
|
|
|
|
|
|
fd_to_handlers[local_sock.fileno()] = self |
|
|
fd_to_handlers[local_sock.fileno()] = self |
|
|
local_sock.setblocking(False) |
|
|
local_sock.setblocking(False) |
|
|
local_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) |
|
|
local_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) |
|
|
loop.add(local_sock, eventloop.POLL_IN | eventloop.POLL_ERR, |
|
|
loop.add(local_sock, eventloop.POLL_IN | eventloop.POLL_ERR, self._server) |
|
|
self._server) |
|
|
|
|
|
self.last_activity = 0 |
|
|
self.last_activity = 0 |
|
|
self._update_activity() |
|
|
self._update_activity() |
|
|
self._server.add_connection(1) |
|
|
self._server.add_connection(1) |
|
|
self._server.stat_add(self._client_address[0], 1) |
|
|
self._server.stat_add(self._client_address[0], 1) |
|
|
self.speed_tester_u = SpeedTester(config.get("speed_limit_per_con", 0)) |
|
|
self.speed_tester_u = SpeedTester(config.get("speed_limit_per_con", 0)) |
|
|
self.speed_tester_d = SpeedTester(config.get("speed_limit_per_con", 0)) |
|
|
self.speed_tester_d = SpeedTester(config.get("speed_limit_per_con", 0)) |
|
|
|
|
|
self._recv_pack_id = 0 |
|
|
|
|
|
|
|
|
def __hash__(self): |
|
|
def __hash__(self): |
|
|
# default __hash__ is id / 16 |
|
|
# default __hash__ is id / 16 |
|
@ -254,6 +243,23 @@ class TCPRelayHandler(object): |
|
|
logging.debug('chosen server: %s:%d', server, server_port) |
|
|
logging.debug('chosen server: %s:%d', server, server_port) |
|
|
return server, server_port |
|
|
return server, server_port |
|
|
|
|
|
|
|
|
|
|
|
def _update_tcp_mss(self, local_sock): |
|
|
|
|
|
self._tcp_mss = TCP_MSS |
|
|
|
|
|
try: |
|
|
|
|
|
self._tcp_mss = local_sock.getsockopt(socket.SOL_TCP, socket.TCP_MAXSEG) |
|
|
|
|
|
logging.debug("TCP MSS = %d" % (self._tcp_mss,)) |
|
|
|
|
|
except: |
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
def _create_encryptor(self, config): |
|
|
|
|
|
try: |
|
|
|
|
|
self._encryptor = encrypt.Encryptor(config['password'], |
|
|
|
|
|
config['method']) |
|
|
|
|
|
return True |
|
|
|
|
|
except Exception: |
|
|
|
|
|
self._stage = STAGE_DESTROYED |
|
|
|
|
|
logging.error('create encryptor fail at port %d', self._server._listen_port) |
|
|
|
|
|
|
|
|
def _update_user(self, user): |
|
|
def _update_user(self, user): |
|
|
self._user = user |
|
|
self._user = user |
|
|
self._user_id = struct.unpack('<I', user)[0] |
|
|
self._user_id = struct.unpack('<I', user)[0] |
|
@ -884,6 +890,7 @@ class TCPRelayHandler(object): |
|
|
else: |
|
|
else: |
|
|
recv_buffer_size = self._get_read_size(self._remote_sock, self._recv_buffer_size) |
|
|
recv_buffer_size = self._get_read_size(self._remote_sock, self._recv_buffer_size) |
|
|
data = self._remote_sock.recv(recv_buffer_size) |
|
|
data = self._remote_sock.recv(recv_buffer_size) |
|
|
|
|
|
self._recv_pack_id += 1 |
|
|
except (OSError, IOError) as e: |
|
|
except (OSError, IOError) as e: |
|
|
if eventloop.errno_from_exception(e) in \ |
|
|
if eventloop.errno_from_exception(e) in \ |
|
|
(errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK, 10035): #errno.WSAEWOULDBLOCK |
|
|
(errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK, 10035): #errno.WSAEWOULDBLOCK |
|
@ -912,6 +919,8 @@ class TCPRelayHandler(object): |
|
|
data = self._encryptor.decrypt(obfs_decode[0]) |
|
|
data = self._encryptor.decrypt(obfs_decode[0]) |
|
|
try: |
|
|
try: |
|
|
data = self._protocol.client_post_decrypt(data) |
|
|
data = self._protocol.client_post_decrypt(data) |
|
|
|
|
|
if self._recv_pack_id == 1: |
|
|
|
|
|
self._tcp_mss = self._protocol.get_server_info().tcp_mss |
|
|
except Exception as e: |
|
|
except Exception as e: |
|
|
shell.print_exception(e) |
|
|
shell.print_exception(e) |
|
|
logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) |
|
|
logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) |
|
|