为了方便区分,以下分别使用local,server,remote代表ss客户端,ss服务端,以及ss客户端请求访问的远程主机。
在***中,无论对于local还是server,都需要建立两个socket:local_sock和remote_sock
对于local,local_sock用于和进程通讯,server_sock用于和server通讯。
对于server,local_sock用于和local通信,server_sock用于和remote通信。
上一次提到两者的事件处理均使用TCPRelayHandler,先来看一下handle_event函数。
# tcprelay.py
class TCPRelayHandler(object):
def handle_event(self, sock, event):
# handle all events in this handler and dispatch them to methods
if self._stage == STAGE_DESTROYED:
logging.debug('ignore handle_event: destroyed')
return
# order is important
# remote_socket
if sock == self._remote_sock:
if event & eventloop.POLL_ERR:
self._on_remote_error()
if self._stage == STAGE_DESTROYED:
return
if event & (eventloop.POLL_IN | eventloop.POLL_HUP):
self._on_remote_read()
if self._stage == STAGE_DESTROYED:
return
if event & eventloop.POLL_OUT:
self._on_remote_write()
# local_socket
elif sock == self._local_sock:
if event & eventloop.POLL_ERR:
self._on_local_error()
if self._stage == STAGE_DESTROYED:
return
if event & (eventloop.POLL_IN | eventloop.POLL_HUP):
self._on_local_read()
if self._stage == STAGE_DESTROYED:
return
if event & eventloop.POLL_OUT:
self._on_local_write()
else:
logging.warn('unknown socket')
该函数根据传入的socket参数来区别是local_sock,还是remote_sock,将read/write事件的处理分发到各个处理函数。
下面来具体看看这些事件处理函数。
remote_read
# tcprelay.py
class TCPRelayHandler(object):
def _on_remote_read(self):
# handle all remote read events
data = None
try:
# 从remote_sock读取数据
data = self._remote_sock.recv(BUF_SIZE)
except (OSError, IOError) as e:
if eventloop.errno_from_exception(e) in \
(errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK):
return
if not data:
self.destroy()
return
self._update_activity(len(data))
# local,说明server回反了数据
if self._is_local:
# 解密数据
data = self._encryptor.decrypt(data)
# server,说明remote响应到达
else:
# 加密数据
data = self._encryptor.encrypt(data)
try:
# 写到local_sock,对于server就是写回local,对于local就是写回进程
self._write_to_sock(data, self._local_sock)
except Exception as e:
shell.print_exception(e)
if self._config['verbose']:
traceback.print_exc()
# TODO use logging when debug completed
self.destroy()
remote_write
# tcprelay.py
class TCPRelayHandler(object):
def _on_remote_write(self):
# 进入流传输阶段
self._stage = STAGE_STREAM
# 如果有需要写的数据
if self._data_to_write_to_remote:
data = b''.join(self._data_to_write_to_remote)
self._data_to_write_to_remote = []
self._write_to_sock(data, self._remote_sock)
else:
# 否则,更新状态
self._update_stream(STREAM_UP, WAIT_STATUS_READING)
local_read
# tcprelay.py
class TCPRelayHandler(object):
def _on_local_read(self):
# handle all local read events and dispatch them to methods for
# each stage
if not self._local_sock:
return
is_local = self._is_local
data = None
try:
# 尝试读取数据
data = self._local_sock.recv(BUF_SIZE)
except (OSError, IOError) as e:
if eventloop.errno_from_exception(e) in \
(errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK):
return
if not data:
self.destroy()
return
#
self._update_activity(len(data))
if not is_local:
# server的local_sock,表明为local发来数据
# 将数据解密
data = self._encryptor.decrypt(data)
if not data:
return
# 在stream状态,此时已经建立起协议,传输的是向remote的请求细节,以及remote的响应
if self._stage == STAGE_STREAM:
# 客户端
if self._is_local:
# 将数据加密
data = self._encryptor.encrypt(data)
# 直接转发给remote
self._write_to_sock(data, self._remote_sock)
return
# 处于init状态,处理协议细节
elif is_local and self._stage == STAGE_INIT:
# TODO check auth method
# 给进程发送确认信息
self._write_to_sock(b'\x05\00', self._local_sock)
self._stage = STAGE_ADDR
return
# 处于connecting状态,处理协议细节
elif self._stage == STAGE_CONNECTING:
self._handle_stage_connecting(data)
# local,等待进程发来请求数据,或者server,初始化状态,等待local发来数据
elif (is_local and self._stage == STAGE_ADDR) or \
(not is_local and self._stage == STAGE_INIT):
# 客户端:接受进程的请求信息,服务器:接受客户端的请求信息
self._handle_stage_addr(data)
local_write
# tcprelay.py
class TCPRelayHandler(object):
def _on_local_write(self):
# 如果有数据可写
if self._data_to_write_to_local:
data = b''.join(self._data_to_write_to_local)
self._data_to_write_to_local = []
# 写到本地sock
self._write_to_sock(data, self._local_sock)
else:
# 更新流状态
self._update_stream(STREAM_DOWN, WAIT_STATUS_READING)
浙公网安备 33010602011771号