当前位置: 首页 > news >正文

用Python实现TCP代理

依旧是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能用

sudo python TCP_proxy.py 192.168.65.128 8887 www.baidu.com 80 True

再另起一个终端,输入:

curl -x 192.168.65.128:8887 www.baidu.com

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

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

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

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

相关文章:

  • Java数据类型与数据库类型映射技术文档
  • 基础框架系列分享:一个通用的Excel报表生成管理框架
  • MQTT 服务器(emqx)搭建及使用(一)
  • [图论]拓扑排序
  • 【JavaEE】MyBatis - Plus
  • deepseek v3-0324 化学键线式Canvas编辑器设计
  • 线程池自顶向下
  • 关于 @Autowired 和 @Value 使用 private 字段的警告问题分析与解决方案
  • # C++初阶——内存管理
  • 【mysql】日志:binLog、redoLog和undoLog
  • openwebui和keycloak集成,使用keycloak的用户名和密码登录
  • Ubuntu 安全限制遭突破:攻击者可利用内核漏洞提权
  • 如何使用AI去水印(ChatGPT去除图片水印)
  • Proxmox pct 部署debian
  • Elasticsearch安全加固指南:启用登录认证与SSL加密
  • Linux服务器组建与管理
  • 使用 Selenium 构建简单高效的网页爬虫
  • 4.1 代码随想录第三十二天打卡
  • ​Android 集成 Facebook 登录
  • 2025.4.6机器学习笔记:文献阅读
  • 4月份全国企业销售收入同比增长4.3%
  • 四部门:到2025年底,全国行政村5G通达率超过90%
  • 秦洪看盘|交易新逻辑,银行股成A股稳定器
  • 广东韶关一镇干部冲进交通事故火海救人,获授“见义勇为”奖励万元
  • 我国7名优秀护理工作者荣获第50届南丁格尔奖
  • 泽连斯基:乌克兰已做好与俄罗斯举行会谈的准备