Wireshark有抓包功能,可以用于流量分析,但是用于某些特殊场合则不具有灵便性,这里我们参考了《Python黑帽子编程》这本书,并改进了他,用于实现一个高性能的TCP代理
基本原理
作为一个代理(参考BurpSuite),基本的思路应该是:
1.接收客户端的数据,处理和编辑,发送给服务端
2.接收服务器的数据,处理和编辑,发送给客户端
基本的TCP连接示例如下
##Todo: add
异步TCP
TCP会话过程中,随时可能接收到数据,为了提高代理性能,我们使用异步模式,该过程中使用epoll(仅限Linux系统)功能(Select也可以)来提高整个代理的性能
epoll用法如下:
import select
epoll = select.epoll()
epoll.register(file_number,select.EPOLLIN)
epoll.register(file_number,select.EPOLLOUT)
##设置相关file_number为非阻塞
....
events = epoll.poll(TIMEOUT)
#events为一个List[],成员为tuple(),其数据为(file_number,event)
多线程
客户端的连接可能不止一个,我们需要使用多线程来操作
核心代码 - 代理handler
###参数分别为客户端连接的socket,要连接的远程服务器host和port
def proxy_handler(client_socket,remote_host,remote_port):
MAXLENGTH = 4096
TIMEOUT = 300
##和远程服务器建立连接
remote_socket= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
remote_socket.connect((remote_host,remote_port))
epoll = select.epoll()
epoll.register(client_socket.fileno(),select.EPOLLIN)
epoll.register(remote_socket.fileno(),select.EPOLLIN)
###向系统注册epoll事件,事件为:文件有数据传入
remote_socket.setblocking(False)
client_socket.setblocking(False)
###设置非阻塞Socket
flag_loop = True
while flag_loop:
# 查询epoll时间
events = epoll.poll(TIMEOUT)
if not events:
##返回为空表明连接崩溃,退出循环
break
###解析相应的事件
for fd, status in events:
# 客户端 >> 服务器
if fd == client_socket.fileno():
msg = client_socket.recv(MAXLENGTH)
if not msg:
# Connection closed
flag_loop = False
break
print("[*] Received %d bytes from the client" % (len(msg)))
##request_handler和下面的response_handler用来审查和修改中间经过的数据
msg = request_handler(msg)
remote_socket.send(msg)
print("[*] Send %d bytes to the remote" % (len(msg)))
# 服务器 >> 客户端
elif fd == remote_socket.fileno():
msg = remote_socket.recv(MAXLENGTH)
if not msg:
# Connection closed
flag_loop = False
break
print("[*] Received %d bytes from the remote" % (len(msg)))
msg = response_handler(msg)
client_socket.send(msg)
print("[*] Send %d bytes to the client" % (len(msg)))
remote_socket.close()
client_socket.close()
print("[*] Connection closed")
则接下来考虑输入多线程