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

相关推荐
不知更鸟17 分钟前
Django 项目设置流程
后端·python·django
自动化代码美学1 小时前
【Python3.13】官网学习之控制流
开发语言·windows·python·学习
捷米研发三部2 小时前
ProfiNet转Modbus TCP协议转换网关实现西门子PLC与工控机通讯在智能交通系统的应用案例
网络·网络协议
dreamtm1233 小时前
通俗理解 TCP 拥塞控制:像 “快递员看路况调速”,避免网络 “堵车”
网络·tcp/ip·php
Cult Of3 小时前
TCP 与 UDP 的区别
网络协议·tcp/ip·udp
wanhengidc3 小时前
云手机的软件核心是什么
运维·服务器·web安全·游戏·智能手机
百锦再4 小时前
第18章 高级特征
android·java·开发语言·后端·python·rust·django
源码之家4 小时前
基于Python房价预测系统 数据分析 Flask框架 爬虫 随机森林回归预测模型、链家二手房 可视化大屏 大数据毕业设计(附源码)✅
大数据·爬虫·python·随机森林·数据分析·spark·flask
SalvoGao4 小时前
Python学习 | 怎么理解epoch?
数据结构·人工智能·python·深度学习·学习
楚疏笃5 小时前
纯Python 实现 Word 文档转换 Markdown
python·word