用Python实现TCP代理

依旧是Python黑帽子这本书

先附上代码,我在原书代码上加了注释,更好理解

python 复制代码
import sys
import socket
import threading

#生成可打印字符映射
HEX_FILTER=''.join(
    [(len(repr(chr(i)))==3) and chr(i) or '.' for i in range(256)])

#接收bytes或string类型的输入,并将其转换为十六进制格式输出
#数值存储
def hexdump(src,length=16,show=True):
    if isinstance(src,bytes):
        src=src.decode()

    results=list()
    for i in range(0,len(src),length):
        word=str(src[i:i+length])
        printable=word.translate(HEX_FILTER)
        hexa=' '.join([f'{ord(c):02X}' for c in word])
        hexwidth=length*3
        results.append(f'{i:04x} {hexa:<{hexwidth}} {printable}')
    if show:
        for line in results:
            print(line)
    else:
        return results

#接收本地或远程数据
def receive_from(connection):
    buffer=b""
    connection.settimeout(5)
    try:
        while True:
            data=connection.recv(4096)
            if not data:
                break
            buffer +=data
    except Exception as e:
        pass
    return buffer

#数据处理函数
#预留数据修改的钩子,可以在这里修改客户端请求或服务器响应
def request_handler(buffer):
    return buffer

def response_handler(buffer):
    return buffer

#代理处理,负责处理客户端与远程服务器间的通信,是代理的核心
def proxy_handler(client_socket,remote_host,remote_port,receive_first):
    #创建远程连接
    remote_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建TCP连接
    remote_socket.connect((remote_host,remote_port))#连接到远程服务器
    #接收远程服务器数据
    if receive_first:
        remote_buffer=receive_from(remote_socket)
        hexdump(remote_buffer)

    #处理服务器返回数据
    remote_buffer=response_handler(remote_buffer)
    if len(remote_buffer):
        print("[<==] Sending %d bytes to localhost." % len(remote_buffer))
        client_socket.send(remote_buffer)
        #循环监听客户端与服务器间的通信,直到连接关闭
        while True:
             #处理客户端数据
             local_buffer=receive_from(client_socket)#读取数据
             if len(local_buffer):
                 line= "[==>]Received %d bytes from localhost." % len(local_buffer)
                 print(line)#打印数据
                 hexdump(local_buffer)

                 local_buffer=request_handler(local_buffer)#数据修改
                 remote_socket.send(local_buffer)#转发给远程服务器
                 print("[==>]Sent to remote.")
             #处理远程服务器返回的数据
             remote_buffer=receive_from(remote_socket)
             if len(remote_buffer):
                 print("[<==] Received %d bytes from remote." % len(remote_buffer))
                 hexdump(remote_buffer)

                 remote_buffer=response_handler(remote_buffer)
                 client_socket.send(remote_buffer)
                 print("[<==] Sent to localhost.")

             #关闭连接
             if not len(local_buffer) or not len(remote_buffer):
                 client_socket.close()
                 remote_socket.close()
                 print("[*] No more data. Closing connections.")


#服务器监听
def server_loop(local_host, local_port, remote_host, remote_port, receive_first):
    #创建socket并绑定端口
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        server.bind((local_host, local_port))
    except Exception as e:
        print('problem on bind: %r' % e)

        print("[!!] Failed to listen on %s:%d" % (local_host, local_port))
        print("[!!] Check for other listening sockets or correct permissions.")
        sys.exit(0)

    #监听并等待客户端连接
    print("[*] Listening on %s:%d" % (local_host, local_port))
    server.listen(5)

    while True:
        #处理客户端连接
        client_socket, addr = server.accept()
        #输出连接信息
        line = "> Received incomming connection from %s:%d" % (addr[0], addr[1])
        print(line)
        #启动代理线程
        proxy_thread = threading.Thread(
            target=proxy_handler,
            args=(client_socket, remote_host,
                  remote_port, receive_first)
        )
        proxy_thread.start()


def main():
    if len(sys.argv[1:]) != 5:
        print("Usage: ./proxy.py [localhost] [localport]", end='')
        print("[remotehost] [remoteport] [receive_first]")
        print("Example: ./proxy.py 127.0.0.1 9000 10.12.132.1 9000 True")
        sys.exit(0)

    local_host = sys.argv[1]
    local_port = int(sys.argv[2])

    remote_host = sys.argv[3]
    remote_port = int(sys.argv[4])

    receive_first = sys.argv[5]

    if "True" in receive_first:
        receive_first = True
    else:
        receive_first = False
    #启动服务器
    server_loop(local_host, local_port, remote_host, remote_port, receive_first)


if __name__ == '__main__':
    main()

windows物理机和kali我都试了,不知道为什么只有kali能用

python 复制代码
sudo python TCP_proxy.py 192.168.65.128 8887 www.baidu.com 80 True

再另起一个终端,输入:

python 复制代码
curl -x 192.168.65.128:8887 www.baidu.com

这时候我们的脚本就会接收到数据,并以hex的形式输出

本来原书用的是ftp,但是我怎么也复现不出来,只能简单用这个代替一下的,但是原理也差不了太多

但是我发现这个似乎不太稳定,我也是试了两次才成功的

还有个问题就是程序没加入ctrl+c退出的功能,虽然我也懒得加了喵(

相关推荐
circuitsosk23 分钟前
企业知识库 RAG 从 62% 到 91%:分块策略、混合检索与重排序的调优全记录
python·知识库问答·rag·面试项目·ai工程化·混合检索
烂蜻蜓1 小时前
Flask入门教程(二十六):Session API——用户会话状态管理
后端·python·flask
2603_965148113 小时前
家居百货蓝海:API挖掘高复购率生活小商品
大数据·服务器·人工智能·python·生活
CoreTK_EMC6 小时前
机器人信号线缆屏蔽:解决伺服干扰、通讯异常的工程落地思路
网络·机器人·芯通康·机器人信号线缆屏蔽·工业机器人线缆 emc·机器人接地屏蔽·ethercat 通讯干扰
阿童木写作6 小时前
跨境电商图片翻译工具推荐:批量图片翻译+视频字幕翻译+智能抠图
python·macos·音视频·xcode
cui_ruicheng7 小时前
LangChain 应用开发(十四):Agent 上下文与记忆机制
服务器·人工智能·python·langchain
小江的记录本7 小时前
【CSS】CSS 动画:transition、animation、transform、CSS3 新特性(附《思维导图》)
前端·css·安全·spring·前端框架·css3·动画
circuitsosk7 小时前
任务规划器的三种范式对比:ReAct、Plan-and-Execute 与 Tree-of-Thought 在真实业务中的取舍
前端·javascript·python·react.js·llm·ai agent
张宇Joaquin7 小时前
鲲鹏统一并行加速库KUPL--众核并行能力介绍
java·开发语言·网络
shehuiyuelaiyuehao7 小时前
算法31,前缀和,可被k整除的子数组
数据结构·python·算法