用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退出的功能,虽然我也懒得加了喵(

相关推荐
打工仔折腾 AI几秒前
飞牛OS上用Docker Compose部署ExerciseDiary运动记录并配置远程访问
运维·人工智能·后端·python·docker·容器·ai agent 实战
阿钱真强道6 分钟前
28 嵌入式操作系统 | 网关加 TCP 命令通道:粘包/半包怎么切
网络·网络协议·tcp/ip·粘包
小蒜学长12 分钟前
基于Python的动物救助站管理系统的设计与实现(代码+数据库+LW)
数据库·后端·python·django·动物救助
小小张说故事21 分钟前
Python 中 __new__ 和 __init__ 到底谁才是构造函数?一文讲透区别与 5 个坑
后端·python
HY小宝F29 分钟前
树莓派智能摄像头系统 30 天重学计划之 Day 03 · 网络基础:建立“包“的思维 —— 学习总结
网络·学习
言乐630 分钟前
Python实现关税自动计算模型
开发语言·python·django·virtualenv·pygame
伞伞悦读30 分钟前
从零打通 Hermes Agent:Windows + WSL2 + Clash 全链路安装、认证与首次实战
python·语言模型
ayaya_mana32 分钟前
MCTier 组网联机工具:安装、配置与私有化部署
网络·windows·内网穿透·联机
故七月36 分钟前
GEO 信源评估体系:如何判断一条网页信源能否被大模型采信
前端·网络·人工智能
happylifetree1 小时前
Python17:核心语法-数据存储与运算-输入与输出
python