mitmproxy_mitmproxy 保存请求 - CSDN
精华内容
参与话题
  • 使用 mitmproxy + python 做拦截代理

    万次阅读 2020-04-14 18:15:58
    mitmproxy 是什么 安装 运行 脚本 事件 1. 针对 HTTP 生命周期 2. 针对 TCP 生命周期 3. 针对 Websocket 生命周期 4. 针对网络连接生命周期 5. 通用生命周期 示例 最后 原文地址:...

    目录

    mitmproxy 是什么

    安装

    运行

    脚本

    事件

    1. 针对 HTTP 生命周期

    2. 针对 TCP 生命周期

    3. 针对 Websocket 生命周期

    4. 针对网络连接生命周期

    5. 通用生命周期

    示例

    最后


    本文是一个较为完整的 mitmproxy 教程,侧重于介绍如何开发拦截脚本,帮助读者能够快速得到一个自定义的代理工具。

    本文假设读者有基本的 python 知识,且已经安装好了一个 python 3 开发环境。如果你对 nodejs 的熟悉程度大于对 python,可移步到 anyproxy,anyproxy 的功能与 mitmproxy 基本一致,但使用 js 编写定制脚本。除此之外我就不知道有什么其他类似的工具了,如果你知道,欢迎评论告诉我。

    本文基于 mitmproxy v4,当前版本号为 v4.0.1

    mitmproxy 是什么

    顾名思义,mitmproxy 就是用于 MITM 的 proxy,MITM 即中间人攻击(Man-in-the-middle attack)。用于中间人攻击的代理首先会向正常的代理一样转发请求,保障服务端与客户端的通信,其次,会适时的查、记录其截获的数据,或篡改数据,引发服务端或客户端特定的行为。

    不同于 fiddler 或 wireshark 等抓包工具,mitmproxy 不仅可以截获请求帮助开发者查看、分析,更可以通过自定义脚本进行二次开发。举例来说,利用 fiddler 可以过滤出浏览器对某个特定 url 的请求,并查看、分析其数据,但实现不了高度定制化的需求,类似于:“截获对浏览器对该 url 的请求,将返回内容置空,并将真实的返回内容存到某个数据库,出现异常时发出邮件通知”。而对于 mitmproxy,这样的需求可以通过载入自定义 python 脚本轻松实现。

    但 mitmproxy 并不会真的对无辜的人发起中间人攻击,由于 mitmproxy 工作在 HTTP 层,而当前 HTTPS 的普及让客户端拥有了检测并规避中间人攻击的能力,所以要让 mitmproxy 能够正常工作,必须要让客户端(APP 或浏览器)主动信任 mitmproxy 的 SSL 证书,或忽略证书异常,这也就意味着 APP 或浏览器是属于开发者本人的——显而易见,这不是在做黑产,而是在做开发或测试。

    那这样的工具有什么实际意义呢?据我所知目前比较广泛的应用是做仿真爬虫,即利用手机模拟器、无头浏览器来爬取 APP 或网站的数据,mitmproxy 作为代理可以拦截、存储爬虫获取到的数据,或修改数据调整爬虫的行为。

    事实上,以上说的仅是 mitmproxy 以正向代理模式工作的情况,通过调整配置,mitmproxy 还可以作为透明代理、反向代理、上游代理、SOCKS 代理等,但这些工作模式针对 mitmproxy 来说似乎不大常用,故本文仅讨论正向代理模式。

    安装

    “安装 mitmproxy”这句话是有歧义的,既可以指“安装 mitmproxy 工具”,也可以指“安装 python 的 mitmproxy 包”,注意后者是包含前者的。

    如果只是拿 mitmproxy 做一个替代 fiddler 的工具,没有什么定制化的需求,那完全只需要“安装 mitmproxy 工具”即可,去 mitmproxy 官网 上下载一个 installer 便可开箱即用,不需要提前准备好 python 开发环境。但显然,这不是这里要讨论的,我们需要的是“安装 python 的 mitmproxy 包”。

    安装 python 的 mitmproxy 包除了会得到 mitmproxy 工具外,还会得到开发定制脚本所需要的包依赖,其安装过程并不复杂。

    首先需要安装好 python,版本需要不低于 3.6,且安装了附带的包管理工具 pip。不同操作系统安装 python 3 的方式不一,参考 python 的下载页,这里不做展开,假设你已经准备好这样的环境了。

    安装开始。

    在 linux 中:

    sudo pip3 install mitmproxy
    

    在 windows 中,以管理员身份运行 cmd 或 power shell:

    pip3 install mitmproxy
    

    安装结束后,系统将拥有 mitmproxymitmdumpmitmweb 三个命令,由于 mitmproxy 命令不支持在 windows 系统中运行(这没关系,不用担心),我们可以拿 mitmdump 测试一下安装是否成功,执行:

    mitmdump --version
    

    应当可以看到类似于这样的输出:

    Mitmproxy: 4.0.1
    Python:    3.6.5
    OpenSSL:   OpenSSL 1.1.0h  27 Mar 2018
    Platform:  Windows-10-10.0.16299-SP0
    

    运行

    要启动 mitmproxy 用 mitmproxymitmdumpmitmweb 这三个命令中的任意一个即可,这三个命令功能一致,且都可以加载自定义脚本,唯一的区别是交互界面的不同。

    mitmproxy 命令启动后,会提供一个命令行界面,用户可以实时看到发生的请求,并通过命令过滤请求,查看请求数据。形如:

    mitmweb 命令启动后,会提供一个 web 界面,用户可以实时看到发生的请求,并通过 GUI 交互来过滤请求,查看请求数据。形如:

    mitmdump 命令启动后——你应该猜到了,没有界面,程序默默运行,所以 mitmdump 无法提供过滤请求、查看数据的功能,只能结合自定义脚本,默默工作。

    由于 mitmproxy 命令的交互操作稍显繁杂且不支持 windows 系统,而我们主要的使用方式又是载入自定义脚本,并不需要交互,所以原则上说只需要 mitmdump 即可,但考虑到有交互界面可以更方便排查错误,所以这里以 mitmweb 命令为例。实际使用中可以根据情况选择任何一个命令。

    启动 mitmproxy:

    mitmweb
    

    应当看到如下输出:

    Web server listening at http://127.0.0.1:8081/
    Proxy server listening at http://*:8080
    

    mitmproxy 绑定了 *:8080 作为代理端口,并提供了一个 web 交互界面在 127.0.0.1:8081

    现在可以测试一下代理,让 Chrome 以 mitmproxy 为代理并忽略证书错误。为了不影响平时正常使用,我们不去改 Chrome 的配置,而是通过命令行带参数起一个 Chrome。如果你不使用 Chrome 而是其他浏览器,也可以搜一下对应的启动参数是什么,应该不会有什么坑。此外示例仅以 windows 系统为例,因为使用 linux 或 mac 开发的同学应该更熟悉命令行的使用才对,应当能自行推导出在各自环境中对应的操作。

    由于 Chrome 要开始赴汤蹈火走代理了,为了方便继续在 web 界面上与 mitmproxy 交互,我们委屈求全使用 Edge 或其他浏览器打开 127.0.0.1:8081。插一句,我用 Edge 实在是因为机器上没其他浏览器了(IE 不算),Edge 有一个默认禁止访问回环地址的狗屁设定,详见解决方案

    接下来关闭所有 Chrome 窗口,否则命令行启动时的附加参数将失效。打开 cmd,执行:

    "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server=127.0.0.1:8080 --ignore-certificate-errors
    

    前面那一长串是 Chrome 的的安装路径,应当根据系统实际情况修改,后面两参数设置了代理地址并强制忽略掉证书错误。用 Chrome 打开一个网站,可以看到:

    同时在 Edge 上可以看到:

    脚本

    完成了上述工作,我们已经具备了操作 mitmproxy 的基本能力 了。接下来开始开发自定义脚本,这才是 mitmproxy 真正强大的地方。

    脚本的编写需要遵循 mitmproxy 规定的套路,这样的套路有两个,使用时选其中一个套路即可。

    第一个套路是,编写一个 py 文件供 mitmproxy 加载,文件中定义了若干函数,这些函数实现了某些 mitmproxy 提供的事件,mitmproxy 会在某个事件发生时调用对应的函数,形如:

    import mitmproxy.http
    from mitmproxy import ctx
    
    num = 0
    
    
    def request(flow: mitmproxy.http.HTTPFlow):
        global num
        num = num + 1
        ctx.log.info("We've seen %d flows" % num)
    
    

    第二个套路是,编写一个 py 文件供 mitmproxy 加载,文件定义了变量 addons,addons 是个数组,每个元素是一个类实例,这些类有若干方法,这些方法实现了某些 mitmproxy 提供的事件,mitmproxy 会在某个事件发生时调用对应的方法。这些类,称为一个个 addon,比如一个叫 Counter 的 addon:

    import mitmproxy.http
    from mitmproxy import ctx
    
    
    class Counter:
        def __init__(self):
            self.num = 0
    
        def request(self, flow: mitmproxy.http.HTTPFlow):
            self.num = self.num + 1
            ctx.log.info("We've seen %d flows" % self.num)
    
    
    addons = [
        Counter()
    ]
    

    这里强烈建议使用第二种套路,直觉上就会感觉第二种套路更为先进,使用会更方便也更容易管理和拓展。况且这也是官方内置的一些 addon 的实现方式。

    我们将上面第二种套路的示例代码存为 addons.py,再重新启动 mitmproxy:

    mitmweb -s addons.py
    

    当浏览器使用代理进行访问时,就应该能看到控制台里有类似这样的日志:

    Web server listening at http://127.0.0.1:8081/
    Loading script addons.py
    Proxy server listening at http://*:8080
    We've seen 1 flows
    ……
    ……
    We've seen 2 flows
    ……
    We've seen 3 flows
    ……
    We've seen 4 flows
    ……
    ……
    We've seen 5 flows
    ……
    

    这就说明自定义脚本生效了。

    事件

    上述的脚本估计不用我解释相信大家也看明白了,就是当 request 发生时,计数器加一,并打印日志。这里对应的是 request 事件,那拢共有哪些事件呢?不多,也不少,这里详细介绍一下。

    事件针对不同生命周期分为 5 类。“生命周期”这里指在哪一个层面看待事件,举例来说,同样是一次 web 请求,我可以理解为“HTTP 请求 -> HTTP 响应”的过程,也可以理解为“TCP 连接 -> TCP 通信 -> TCP 断开”的过程。那么,如果我想拒绝来个某个 IP 的客户端请求,应当注册函数到针对 TCP 生命周期 的 tcp_start 事件,又或者,我想阻断对某个特定域名的请求时,则应当注册函数到针对 HTTP 声明周期的 http_connect 事件。其他情况同理。

    下面一段估计会又臭又长,如果你没有耐心看完,那至少看掉针对 HTTP 生命周期的事件,然后跳到示例

    1. 针对 HTTP 生命周期

    def http_connect(self, flow: mitmproxy.http.HTTPFlow):
    

    (Called when) 收到了来自客户端的 HTTP CONNECT 请求。在 flow 上设置非 2xx 响应将返回该响应并断开连接。CONNECT 不是常用的 HTTP 请求方法,目的是与服务器建立代理连接,仅是 client 与 proxy 的之间的交流,所以 CONNECT 请求不会触发 request、response 等其他常规的 HTTP 事件。

    def requestheaders(self, flow: mitmproxy.http.HTTPFlow):
    

    (Called when) 来自客户端的 HTTP 请求的头部被成功读取。此时 flow 中的 request 的 body 是空的。

    def request(self, flow: mitmproxy.http.HTTPFlow):
    

    (Called when) 来自客户端的 HTTP 请求被成功完整读取。

    def responseheaders(self, flow: mitmproxy.http.HTTPFlow):
    

    (Called when) 来自服务端的 HTTP 响应的头部被成功读取。此时 flow 中的 response 的 body 是空的。

    def response(self, flow: mitmproxy.http.HTTPFlow):
    

    (Called when) 来自服务端端的 HTTP 响应被成功完整读取。

    def error(self, flow: mitmproxy.http.HTTPFlow):
    

    (Called when) 发生了一个 HTTP 错误。比如无效的服务端响应、连接断开等。注意与“有效的 HTTP 错误返回”不是一回事,后者是一个正确的服务端响应,只是 HTTP code 表示错误而已。

    (好了,你可以跳到示例了。)

    2. 针对 TCP 生命周期

    def tcp_start(self, flow: mitmproxy.tcp.TCPFlow):
    

    (Called when) 建立了一个 TCP 连接。

    def tcp_message(self, flow: mitmproxy.tcp.TCPFlow):
    

    (Called when) TCP 连接收到了一条消息,最近一条消息存于 flow.messages[-1]。消息是可修改的。

    def tcp_error(self, flow: mitmproxy.tcp.TCPFlow):
    

    (Called when) 发生了 TCP 错误。

    def tcp_end(self, flow: mitmproxy.tcp.TCPFlow):
    

    (Called when) TCP 连接关闭。

    3. 针对 Websocket 生命周期

    def websocket_handshake(self, flow: mitmproxy.http.HTTPFlow):
    

    (Called when) 客户端试图建立一个 websocket 连接。可以通过控制 HTTP 头部中针对 websocket 的条目来改变握手行为。flow 的 request 属性保证是非空的的。

    def websocket_start(self, flow: mitmproxy.websocket.WebSocketFlow):
    

    (Called when) 建立了一个 websocket 连接。

    def websocket_message(self, flow: mitmproxy.websocket.WebSocketFlow):
    

    (Called when) 收到一条来自客户端或服务端的 websocket 消息。最近一条消息存于 flow.messages[-1]。消息是可修改的。目前有两种消息类型,对应 BINARY 类型的 frame 或 TEXT 类型的 frame。

    def websocket_error(self, flow: mitmproxy.websocket.WebSocketFlow):
    

    (Called when) 发生了 websocket 错误。

    def websocket_end(self, flow: mitmproxy.websocket.WebSocketFlow):
    

    (Called when) websocket 连接关闭。

    4. 针对网络连接生命周期

    def clientconnect(self, layer: mitmproxy.proxy.protocol.Layer):
    

    (Called when) 客户端连接到了 mitmproxy。注意一条连接可能对应多个 HTTP 请求。

    def clientdisconnect(self, layer: mitmproxy.proxy.protocol.Layer):
    

    (Called when) 客户端断开了和 mitmproxy 的连接。

    def serverconnect(self, conn: mitmproxy.connections.ServerConnection):
    

    (Called when) mitmproxy 连接到了服务端。注意一条连接可能对应多个 HTTP 请求。

    def serverdisconnect(self, conn: mitmproxy.connections.ServerConnection):
    

    (Called when) mitmproxy 断开了和服务端的连接。

    def next_layer(self, layer: mitmproxy.proxy.protocol.Layer):
    

    (Called when) 网络 layer 发生切换。你可以通过返回一个新的 layer 对象来改变将被使用的 layer。详见 layer 的定义

    5. 通用生命周期

    def configure(self, updated: typing.Set[str]):
    

    (Called when) 配置发生变化。updated 参数是一个类似集合的对象,包含了所有变化了的选项。在 mitmproxy 启动时,该事件也会触发,且 updated 包含所有选项。

    def done(self):
    

    (Called when) addon 关闭或被移除,又或者 mitmproxy 本身关闭。由于会先等事件循环终止后再触发该事件,所以这是一个 addon 可以看见的最后一个事件。由于此时 log 也已经关闭,所以此时调用 log 函数没有任何输出。

    def load(self, entry: mitmproxy.addonmanager.Loader):
    

    (Called when) addon 第一次加载时。entry 参数是一个 Loader 对象,包含有添加选项、命令的方法。这里是 addon 配置它自己的地方。

    def log(self, entry: mitmproxy.log.LogEntry):
    

    (Called when) 通过 mitmproxy.ctx.log 产生了一条新日志。小心不要在这个事件内打日志,否则会造成死循环。

    def running(self):
    

    (Called when) mitmproxy 完全启动并开始运行。此时,mitmproxy 已经绑定了端口,所有的 addon 都被加载了。

    def update(self, flows: typing.Sequence[mitmproxy.flow.Flow]):
    

    (Called when) 一个或多个 flow 对象被修改了,通常是来自一个不同的 addon。

    示例

    估计看了那么多的事件你已经晕了,正常,鬼才会记得那么多事件。事实上考虑到 mitmproxy 的实际使用场景,大多数情况下我们只会用到针对 HTTP 生命周期的几个事件。再精简一点,甚至只需要用到 http_connectrequestresponse 三个事件就能完成大多数需求了。

    这里以一个稍微有点黑色幽默的例子,覆盖这三个事件,展示如果利用 mitmproxy 工作。

    需求是这样的:

    1. 因为百度搜索是不靠谱的,所有当客户端发起百度搜索时,记录下用户的搜索词,再修改请求,将搜索词改为“360 搜索”;
    2. 因为 360 搜索还是不靠谱的,所有当客户端访问 360 搜索时,将页面中所有“搜索”字样改为“请使用谷歌”。
    3. 因为谷歌是个不存在的网站,所有就不要浪费时间去尝试连接服务端了,所有当发现客户端试图访问谷歌时,直接断开连接。
    4. 将上述功能组装成名为 Joker 的 addon,并保留之前展示名为 Counter 的 addon,都加载进 mitmproxy。

    第一个需求需要篡改客户端请求,所以实现一个 request 事件:

    def request(self, flow: mitmproxy.http.HTTPFlow):
        # 忽略非百度搜索地址
        if flow.request.host != "www.baidu.com" or not flow.request.path.startswith("/s"):
            return
    
        # 确认请求参数中有搜索词
        if "wd" not in flow.request.query.keys():
            ctx.log.warn("can not get search word from %s" % flow.request.pretty_url)
            return
    
        # 输出原始的搜索词
        ctx.log.info("catch search word: %s" % flow.request.query.get("wd"))
        # 替换搜索词为“360搜索”
        flow.request.query.set_all("wd", ["360搜索"])
    

    第二个需求需要篡改服务端响应,所以实现一个 response 事件:

    def response(self, flow: mitmproxy.http.HTTPFlow):
        # 忽略非 360 搜索地址
        if flow.request.host != "www.so.com":
            return
    
        # 将响应中所有“搜索”替换为“请使用谷歌”
        text = flow.response.get_text()
        text = text.replace("搜索", "请使用谷歌")
        flow.response.set_text(text)
    

    第三个需求需要拒绝客户端请求,所以实现一个 http_connect 事件:

    def http_connect(self, flow: mitmproxy.http.HTTPFlow):
        # 确认客户端是想访问 www.google.com
        if flow.request.host == "www.google.com":
            # 返回一个非 2xx 响应断开连接
            flow.response = http.HTTPResponse.make(404)
    

    为了实现第四个需求,我们需要将代码整理一下,即易于管理也易于查看。

    创建一个 joker.py 文件,内容为:

    import mitmproxy.http
    from mitmproxy import ctx, http
    
    
    class Joker:
        def request(self, flow: mitmproxy.http.HTTPFlow):
            if flow.request.host != "www.baidu.com" or not flow.request.path.startswith("/s"):
                return
    
            if "wd" not in flow.request.query.keys():
                ctx.log.warn("can not get search word from %s" % flow.request.pretty_url)
                return
    
            ctx.log.info("catch search word: %s" % flow.request.query.get("wd"))
            flow.request.query.set_all("wd", ["360搜索"])
    
        def response(self, flow: mitmproxy.http.HTTPFlow):
            if flow.request.host != "www.so.com":
                return
    
            text = flow.response.get_text()
            text = text.replace("搜索", "请使用谷歌")
            flow.response.set_text(text)
    
        def http_connect(self, flow: mitmproxy.http.HTTPFlow):
            if flow.request.host == "www.google.com":
                flow.response = http.HTTPResponse.make(404)
    
    

    创建一个 counter.py 文件,内容为:

    import mitmproxy.http
    from mitmproxy import ctx
    
    
    class Counter:
        def __init__(self):
            self.num = 0
    
        def request(self, flow: mitmproxy.http.HTTPFlow):
            self.num = self.num + 1
            ctx.log.info("We've seen %d flows" % self.num)
    
    

    创建一个 addons.py 文件,内容为:

    import counter
    import joker
    
    addons = [
        counter.Counter(),
        joker.Joker(),
    ]
    
    

    将三个文件放在相同的文件夹,在该文件夹内启动命令行,运行:

    mitmweb -s addons.py
    

    老规矩,关闭所有 Chrome 窗口,从命令行中启动 Chrome 并指定代理且忽略证书错误。

    测试一下运行效果:

     最后

    以上便是全部内容。Have fun and good luck!


    参考:

    展开全文
  • mitmproxy实战

    2020-02-03 12:50:27
    抓取某宝所有分类 ''' 操作说明: 1、mitmdump -s /Users/fanding/spiderCode/spider-python/po_taobao/taobao_category.py ... 3、执行cat category.log | grep category: | awk -F ':' '{print $4}' >...

    抓取某宝所有分类

    '''
    操作说明:
        1、mitmdump -s /Users/fanding/spiderCode/spider-python/po_taobao/taobao_category.py
        2、手动点击分类
        3、执行cat category.log | grep category: | awk -F ':' '{print $4}' > categoryTem.log | sed 's/-/,/g' > category.csv
    '''
    
    
    # 后续执行手动处理命令
    #cat category.log | grep category: | awk -F ':' '{print $4}' > categoryTem.log | sed 's/-/,/g' > category.csv
    
    
    import pdb
    import json
    import logging
    logging.basicConfig(filename='/Users/fanding/spiderCode/spider-python/po_taobao/category.log', level=logging.DEBUG)
    
    
    def response(follow):
        m_request = follow.request
        m_response = follow.response
        if 'https://guide-acs.m.taobao.com/gw/mtop.relationrecommend.wirelessrecommend.recommend/2.0' in m_request.url:
            logging.info('category: 一级分类-二级分类-三级分类')
            categoryData = json.loads(m_response.text)
            data = categoryData.get('data', {}).get('result', [])
            if not data:
                logging.warning('data is null')
                return m_response
    
            result = data[0]
    
            industryId = result.get('industryId')
            industryList = result.get('industryList')
            moduleList = result.get('moduleList')
    
            categoryOne = ''
            for industry in industryList:
                if industry.get('industryId') == industryId:
                    categoryOneName = industry.get('industryName')
    
            for module in moduleList:
                categoryTwoName = module.get('title')
                items = module.get('items')
                for item in items:
                    categoryThreeName = item.get('show_name')
                    logging.info('category: %s-%s-%s' % (categoryOneName, categoryTwoName, categoryThreeName))
            return m_response
    
    复制代码

    前提是配置好mitmproxy证书等配置,可抓取app数据包

    展开全文
  • mitmproxy是一个支持...一个是mitmdump,它是mitmproxy的命令行接口,利用它我们可以对接Python脚本,用Python实现监听后的处理。另一个是mitmweb,它是一个Web程序,通过它我们可以清楚观察mitmproxy捕获的请求。...

    mitmproxy是一个支持HTTP和HTTPS的抓包程序,有类似Fiddler、Charles的功能,只不过它是一个控制台的形式操作。

    mitmproxy还有两个关联组件。一个是mitmdump,它是mitmproxy的命令行接口,利用它我们可以对接Python脚本,用Python实现监听后的处理。另一个是mitmweb,它是一个Web程序,通过它我们可以清楚观察mitmproxy捕获的请求。

    一、准备工作

    请确保已经正确安装好了mitmproxy,并且手机和PC处于同一个局域网下,同时配置好了mitmproxy的CA证书。

    二、mitmproxy的功能

    mitmproxy有如下几项功能:

    • 拦截HTTP和HTTPS请求和响应。

    • 保存HTTP会话并进行分析。

    • 模拟客户端发起请求,模拟服务端返回响应。

    • 利用反向代理将流量转发给指定的服务器。

    • 支持Mac和Linux上的透明代理。

    利用Python对HTTP请求和响应进行实时处理。

    三、抓包原理

    和Charles一样,mitmproxy运行于自己的PC上,mitmproxy会在PC的8080端口运行,然后开启一个代理服务,这个服务实际上是一个HTTP/HTTPS的代理。

    手机和PC在同一个局域网内,设置代理为mitmproxy的代理地址,这样手机在访问互联网的时候流量数据包就会流经mitmproxy,mitmproxy再去转发这些数据包到真实的服务器,服务器返回数据包时再由mitmproxy转发回手机,这样mitmproxy就相当于起了中间人的作用,抓取到所有Request和Response,另外这个过程还可以对接mitmdump,抓取到的Request和Response的具体内容都可以直接用Python来处理,比如得到Response之后我们可以直接进行解析,然后存入数据库,这样就完成了数据的解析和存储过程。

    四、安装

    “安装 mitmproxy”这句话是有歧义的,既可以指“安装 mitmproxy 工具”,也可以指“安装 python 的 mitmproxy 包”,注意后者是包含前者的。

    如果只是拿 mitmproxy 做一个替代 fiddler 的工具,没有什么定制化的需求,那完全只需要“安装 mitmproxy 工具”即可,去 mitmproxy 官网 上下载一个 installer 便可开箱即用,不需要提前准备好 python 开发环境。但显然,这不是这里要讨论的,我们需要的是“安装 python 的 mitmproxy 包”。

    安装 python 的 mitmproxy 包除了会得到 mitmproxy 工具外,还会得到开发定制脚本所需要的包依赖,其安装过程并不复杂。

    五、运行

    要启动 mitmproxy 用 mitmproxymitmdumpmitmweb 这三个命令中的任意一个即可,这三个命令功能一致,且都可以加载自定义脚本,唯一的区别是交互界面的不同。

    mitmproxy 命令启动后,会提供一个命令行界面,用户可以实时看到发生的请求,并通过命令过滤请求,查看请求数据。形如:

    mitmweb 命令启动后,会提供一个 web 界面,用户可以实时看到发生的请求,并通过 GUI 交互来过滤请求,查看请求数据。形如:

     

    mitmdump 命令启动后——你应该猜到了,没有界面,程序默默运行,所以 mitmdump 无法提供过滤请求、查看数据的功能,只能结合自定义脚本,默默工作。

    由于 mitmproxy 命令的交互操作稍显繁杂且不支持 windows 系统,而我们主要的使用方式又是载入自定义脚本,并不需要交互,所以原则上说只需要 mitmdump 即可,但考虑到有交互界面可以更方便排查错误,所以这里以 mitmweb 命令为例。实际使用中可以根据情况选择任何一个命令。

    启动 mitmproxy:

    mitmweb

    应当看到如下输出:

    Web server listening at http://127.0.0.1:8081/
    Proxy server listening at http://*:8080

    mitmproxy 绑定了 *:8080 作为代理端口,并提供了一个 web 交互界面在 127.0.0.1:8081

    现在可以测试一下代理,让 Chrome 以 mitmproxy 为代理并忽略证书错误。为了不影响平时正常使用,我们不去改 Chrome 的配置,而是通过命令行带参数起一个 Chrome。如果你不使用 Chrome 而是其他浏览器,也可以搜一下对应的启动参数是什么,应该不会有什么坑。此外示例仅以 windows 系统为例,因为使用 linux 或 mac 开发的同学应该更熟悉命令行的使用才对,应当能自行推导出在各自环境中对应的操作。

    由于 Chrome 要开始赴汤蹈火走代理了,为了方便继续在 web 界面上与 mitmproxy 交互,我们委屈求全使用 Edge 或其他浏览器打开 127.0.0.1:8081。插一句,我用 Edge 实在是因为机器上没其他浏览器了(IE 不算),Edge 有一个默认禁止访问回环地址的狗屁设定,详见解决方案

    接下来关闭所有 Chrome 窗口,否则命令行启动时的附加参数将失效。打开 cmd,执行:

    "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server=127.0.0.1:8080 --ignore-certificate-errors
    

    前面那一长串是 Chrome 的的安装路径,应当根据系统实际情况修改,后面两参数设置了代理地址并强制忽略掉证书错误。用 Chrome 打开一个网站,可以看到:

     

    同时在 Edge 上可以看到:

     

    脚本

    完成了上述工作,我们已经具备了操作 mitmproxy 的基本能力 了。接下来开始开发自定义脚本,这才是 mitmproxy 真正强大的地方。

    脚本的编写需要遵循 mitmproxy 规定的套路,这样的套路有两个。

    第一个是,编写一个 py 文件供 mitmproxy 加载,文件中定义了若干函数,这些函数实现了某些 mitmproxy 提供的事件,mitmproxy 会在某个事件发生时调用对应的函数,形如:

    import mitmproxy.http
    from mitmproxy import ctx
    
    num = 0
    
    
    def request(flow: mitmproxy.http.HTTPFlow):
        global num
        num = num + 1
        ctx.log.info("We've seen %d flows" % num)

    第二个是,编写一个 py 文件供 mitmproxy 加载,文件定义了变量 addons,addons 是个数组,每个元素是一个类实例,这些类有若干方法,这些方法实现了某些 mitmproxy 提供的事件,mitmproxy 会在某个事件发生时调用对应的方法。这些类,称为一个个 addon,比如一个叫 Counter 的 addons:

    import mitmproxy.http
    from mitmproxy import ctx
    
    
    class Counter:
        def __init__(self):
            self.num = 0
    
        def request(self, flow: mitmproxy.http.HTTPFlow):
            self.num = self.num + 1
            ctx.log.info("We've seen %d flows" % self.num)
    
    
    addons = [
        Counter()
    ]

    这里强烈建议使用第二种套路,直觉上就会感觉第二种套路更为先进,使用会更方便也更容易管理和拓展。况且这也是官方内置的一些 addon 的实现方式。

    我们将上面第二种套路的示例代码存为 addons.py,再重新启动 mitmproxy:

    mitmweb -s addons.py

    当浏览器使用代理进行访问时,就应该能看到控制台里有类似这样的日志:

    Web server listening at http://127.0.0.1:8081/
    Loading script addons.py
    Proxy server listening at http://*:8080
    We've seen 1 flows
    ……
    ……
    We've seen 2 flows
    ……
    We've seen 3 flows
    ……
    We've seen 4 flows
    ……
    ……
    We've seen 5 flows
    ……

    这就说明自定义脚本生效了。

    事件

    上述的脚本估计不用我解释相信大家也看明白了,就是当 request 发生时,计数器加一,并打印日志。这里对应的是 request 事件,那拢共有哪些事件呢?不多,也不少,这里详细介绍一下。

    事件针对不同生命周期分为 5 类。“生命周期”这里指在哪一个层面看待事件,举例来说,同样是一次 web 请求,我可以理解为“HTTP 请求 -> HTTP 响应”的过程,也可以理解为“TCP 连接 -> TCP 通信 -> TCP 断开”的过程。那么,如果我想拒绝来个某个 IP 的客户端请求,应当注册函数到针对 TCP 生命周期 的 tcp_start 事件,又或者,我想阻断对某个特定域名的请求时,则应当注册函数到针对 HTTP 声明周期的 http_connect 事件。其他情况同理。

    下面一段估计会又臭又长,如果你没有耐心看完,那至少看掉针对 HTTP 生命周期的事件,然后跳到示例

    1. 针对 HTTP 生命周期

    def http_connect(self, flow: mitmproxy.http.HTTPFlow):

    (Called when) 收到了来自客户端的 HTTP CONNECT 请求。在 flow 上设置非 2xx 响应将返回该响应并断开连接。CONNECT 不是常用的 HTTP 请求方法,目的是与服务器建立代理连接,仅是 client 与 proxy 的之间的交流,所以 CONNECT 请求不会触发 request、response 等其他常规的 HTTP 事件。

    def requestheaders(self, flow: mitmproxy.http.HTTPFlow):
    

    (Called when) 来自客户端的 HTTP 请求的头部被成功读取。此时 flow 中的 request 的 body 是空的。

    def request(self, flow: mitmproxy.http.HTTPFlow):
    

    (Called when) 来自客户端的 HTTP 请求被成功完整读取。

    def responseheaders(self, flow: mitmproxy.http.HTTPFlow):
    

    (Called when) 来自服务端的 HTTP 响应的头部被成功读取。此时 flow 中的 response 的 body 是空的。

    def response(self, flow: mitmproxy.http.HTTPFlow):
    

    (Called when) 来自服务端端的 HTTP 响应被成功完整读取。

    def error(self, flow: mitmproxy.http.HTTPFlow):
    

    (Called when) 发生了一个 HTTP 错误。比如无效的服务端响应、连接断开等。注意与“有效的 HTTP 错误返回”不是一回事,后者是一个正确的服务端响应,只是 HTTP code 表示错误而已。

    2. 针对 TCP 生命周期

    def tcp_start(self, flow: mitmproxy.tcp.TCPFlow):

    (Called when) 建立了一个 TCP 连接。

    def tcp_message(self, flow: mitmproxy.tcp.TCPFlow):
    

    (Called when) TCP 连接收到了一条消息,最近一条消息存于 flow.messages[-1]。消息是可修改的。

    def tcp_error(self, flow: mitmproxy.tcp.TCPFlow):
    

    (Called when) 发生了 TCP 错误。

    def tcp_end(self, flow: mitmproxy.tcp.TCPFlow):
    

    (Called when) TCP 连接关闭。

    3. 针对 Websocket 生命周期

    def websocket_handshake(self, flow: mitmproxy.http.HTTPFlow):

    (Called when) 客户端试图建立一个 websocket 连接。可以通过控制 HTTP 头部中针对 websocket 的条目来改变握手行为。flow 的 request 属性保证是非空的的。

    def websocket_start(self, flow: mitmproxy.websocket.WebSocketFlow):

    (Called when) 建立了一个 websocket 连接。

    def websocket_message(self, flow: mitmproxy.websocket.WebSocketFlow):
    

    (Called when) 收到一条来自客户端或服务端的 websocket 消息。最近一条消息存于 flow.messages[-1]。消息是可修改的。目前有两种消息类型,对应 BINARY 类型的 frame 或 TEXT 类型的 frame。

    def websocket_error(self, flow: mitmproxy.websocket.WebSocketFlow):
    

    (Called when) 发生了 websocket 错误。

    def websocket_end(self, flow: mitmproxy.websocket.WebSocketFlow):
    

    (Called when) websocket 连接关闭。

    4. 针对网络连接生命周期

    def clientconnect(self, layer: mitmproxy.proxy.protocol.Layer):
    

    (Called when) 客户端连接到了 mitmproxy。注意一条连接可能对应多个 HTTP 请求。

    def clientdisconnect(self, layer: mitmproxy.proxy.protocol.Layer):
    

    (Called when) 客户端断开了和 mitmproxy 的连接。

    def serverconnect(self, conn: mitmproxy.connections.ServerConnection):
    

    (Called when) mitmproxy 连接到了服务端。注意一条连接可能对应多个 HTTP 请求。

    def serverdisconnect(self, conn: mitmproxy.connections.ServerConnection):
    

    (Called when) mitmproxy 断开了和服务端的连接。

    def next_layer(self, layer: mitmproxy.proxy.protocol.Layer):
    

    (Called when) 网络 layer 发生切换。你可以通过返回一个新的 layer 对象来改变将被使用的 layer。详见 layer 的定义

    5. 通用生命周期

    def configure(self, updated: typing.Set[str]):

    (Called when) 配置发生变化。updated 参数是一个类似集合的对象,包含了所有变化了的选项。在 mitmproxy 启动时,该事件也会触发,且 updated 包含所有选项。

    def done(self):

    (Called when) addon 关闭或被移除,又或者 mitmproxy 本身关闭。由于会先等事件循环终止后再触发该事件,所以这是一个 addon 可以看见的最后一个事件。由于此时 log 也已经关闭,所以此时调用 log 函数没有任何输出。

    def load(self, entry: mitmproxy.addonmanager.Loader):

    (Called when) addon 第一次加载时。entry 参数是一个 Loader 对象,包含有添加选项、命令的方法。这里是 addon 配置它自己的地方。

    def log(self, entry: mitmproxy.log.LogEntry):

    (Called when) 通过 mitmproxy.ctx.log 产生了一条新日志。小心不要在这个事件内打日志,否则会造成死循环。

    def running(self):

    (Called when) mitmproxy 完全启动并开始运行。此时,mitmproxy 已经绑定了端口,所有的 addon 都被加载了。

    def update(self, flows: typing.Sequence[mitmproxy.flow.Flow]):

    (Called when) 一个或多个 flow 对象被修改了,通常是来自一个不同的 addon。

    示例

    估计看了那么多的事件你已经晕了,正常,鬼才会记得那么多事件。事实上考虑到 mitmproxy 的实际使用场景,大多数情况下我们只会用到针对 HTTP 生命周期的几个事件。再精简一点,甚至只需要用到 http_connectrequestresponse 三个事件就能完成大多数需求了。

    这里以一个稍微有点黑色幽默的例子,覆盖这三个事件,展示如果利用 mitmproxy 工作。

    需求是这样的:

    1. 因为百度搜索是不靠谱的,所有当客户端发起百度搜索时,记录下用户的搜索词,再修改请求,将搜索词改为“360 搜索”;
    2. 因为 360 搜索还是不靠谱的,所有当客户端访问 360 搜索时,将页面中所有“搜索”字样改为“请使用谷歌”。
    3. 因为谷歌是个不存在的网站,所有就不要浪费时间去尝试连接服务端了,所有当发现客户端试图访问谷歌时,直接断开连接。
    4. 将上述功能组装成名为 Joker 的 addon,并保留之前展示名为 Counter 的 addon,都加载进 mitmproxy。

    第一个需求需要篡改客户端请求,所以实现一个 request 事件:

    def request(self, flow: mitmproxy.http.HTTPFlow):
        # 忽略非百度搜索地址
        if flow.request.host != "www.baidu.com" or not flow.request.path.startswith("/s"):
            return
    
        # 确认请求参数中有搜索词
        if "wd" not in flow.request.query.keys():
            ctx.log.warn("can not get search word from %s" % flow.request.pretty_url)
            return
    
        # 输出原始的搜索词
        ctx.log.info("catch search word: %s" % flow.request.query.get("wd"))
        # 替换搜索词为“360搜索”
        flow.request.query.set_all("wd", ["360搜索"])

    第二个需求需要篡改服务端响应,所以实现一个 response 事件:

    def response(self, flow: mitmproxy.http.HTTPFlow):
        # 忽略非 360 搜索地址
        if flow.request.host != "www.so.com":
            return
    
        # 将响应中所有“搜索”替换为“请使用谷歌”
        text = flow.response.get_text()
        text = text.replace("搜索", "请使用谷歌")
        flow.response.set_text(text)

    第三个需求需要拒绝客户端请求,所以实现一个 http_connect 事件:

    def http_connect(self, flow: mitmproxy.http.HTTPFlow):
        # 确认客户端是想访问 www.google.com
        if flow.request.host == "www.google.com":
            # 返回一个非 2xx 响应断开连接
            flow.response = http.HTTPResponse.make(404)

    为了实现第四个需求,我们需要将代码整理一下,即易于管理也易于查看。

    import mitmproxy.http
    from mitmproxy import ctx, http
    
    
    class Joker:
        def request(self, flow: mitmproxy.http.HTTPFlow):
            if flow.request.host != "www.baidu.com" or not flow.request.path.startswith("/s"):
                return
    
            if "wd" not in flow.request.query.keys():
                ctx.log.warn("can not get search word from %s" % flow.request.pretty_url)
                return
    
            ctx.log.info("catch search word: %s" % flow.request.query.get("wd"))
            flow.request.query.set_all("wd", ["360搜索"])
    
        def response(self, flow: mitmproxy.http.HTTPFlow):
            if flow.request.host != "www.so.com":
                return
    
            text = flow.response.get_text()
            text = text.replace("搜索", "请使用谷歌")
            flow.response.set_text(text)
    
        def http_connect(self, flow: mitmproxy.http.HTTPFlow):
            if flow.request.host == "www.google.com":
                flow.response = http.HTTPResponse.make(404)

    创建一个 counter.py 文件,内容为:

    import mitmproxy.http
    from mitmproxy import ctx
    
    
    class Counter:
        def __init__(self):
            self.num = 0
    
        def request(self, flow: mitmproxy.http.HTTPFlow):
            self.num = self.num + 1
            ctx.log.info("We've seen %d flows" % self.num)

    创建一个 addons.py 文件,内容为:

    import counter
    import joker
    
    addons = [
        counter.Counter(),
        joker.Joker(),
    ]

    将三个文件放在相同的文件夹,在该文件夹内启动命令行,运行:

    mitmweb -s addons.py

     

    展开全文
  • mitmproxy(一)整理

    千次阅读 2018-11-22 16:31:41
    1. mitmproxy工程工具包,主要包含了3个组件  mitmproxy:拦截的http(s)记录控制台显示 【window不支持】  mitmdump:命令行接口,可以对接python脚本,通过脚本实现监听后的处理,可定制个人需求  mitmweb...

    1. mitmproxy工程工具包,主要包含了3个组件

    •    mitmproxy:拦截的http(s)记录控制台显示 【window不支持】
    •    mitmdump:命令行接口,可以对接python脚本,通过脚本实现监听后的处理,可定制个人需求
    •    mitmweb:web形式展示

    2. 环境
      1.Python3.6及以上 (python -V查看版本)
       2.更新pip(避免部分依赖包未下载)
       3.安装mitmproxy
          pip install mitmproxy #安装依赖包的同时也将环境安装

    3. mitmproxy关于httpflow的api说明

      

    class         mitmproxy.flow.Error(msg:str,timestamp = None ) →无

        一个错误。

        这不同于协议错误响应(例如,HTTP代码500),它由普通HTTPResponse对象表示。该类负责指示不符合正常协议通信的错误,例如中断连接,超时,协议错误。

        揭示以下属性:

            msg:描述错误时间戳的消息:自时代以来的秒数

        get_state()

            检索对象状态。

        set_state(州)

            从get_state调用返回的数据加载对象状态。

    HTTP

    class  mitmproxy.http.HTTPRequest(first_line_format,method,scheme,host,port,path,http_version,headers,content,timestamp_start = None,timestamp_end = None,is_replay = False )

        一个mitmproxy HTTP请求。

        class method wrap(request )

            包裹一个现有的mitmproxy.net.http.Request。

        anticache()

            修改此请求以删除可能产生缓存响应的头文件。也就是说,我们删除ETags和If-Modified-Since头。

        anticomp()

            修改此请求以删除将压缩资源数据的标题。

        constrain_encoding()

            基于我们可以适当解码的限制允许的接受编码值。

        content

            用内容编码标题解码的HTTP消息体(例如gzip)
            举:     当内容编码无效且严格为True时,ValueError。

            另请参阅:raw_content,text

        cookies

            请求Cookie。

            一个空的MultiDictView物体,如果cookie怪物吃了他们全部。

        decode(strict = True )

            根据当前的Content-Encoding头解码主体,然后删除头。如果没有Content-Encoding标题,则不执行任何操作。
            举:     当内容编码无效且严格为True时,ValueError。

        encode(e )

            用编码e编码,其中e是“gzip”,“deflate”,“identity”或“br”。任何现有的内容编码都被覆盖,内容未被预先解码。
            举:     ValueError,当指定的内容编码无效时。

        first_line_format

            HTTP请求表单定义在RFC7230中。

            原始形式和星号形式被归为“相对”。

        get_content(strict:bool = True ) →bytes

            用内容编码标题解码的HTTP消息体(例如gzip)
            举:     当内容编码无效且严格为True时,ValueError。

            另请参阅:raw_content,text

        get_text(strict:bool = True ) →typing.Union [str,NoneType]

            HTTP消息体使用内容编码头(例如gzip)和内容类型头字符集进行解码。
            举:     当内容编码或字符集无效且strict为True时,ValueError。

            另请参阅:content,raw_content

        headers

            消息头对象
            返回:     mitmproxy.net.http.Headers

        host

            目标主机。这可以从原始请求解析(例如,从请求行)或从代理模式推断(例如,透明模式下的IP)。GET http://example.com/ HTTP/1.1

            设置主机属性还会更新主机头(如果存在)。

        host_header

            请求的主机/授权头。

            此属性映射到request.headers["Host"]或 request.headers[":authority"]根据是HTTP / 1.x还是HTTP / 2.0。

        http_version

            版本字符串,例如“HTTP / 1.1”

        make(method:str,url:str,content:typing.Union [bytes,str] ='',headers:typing.Union [typing.Dict [str,AnyStr],typing.Iterable [typing.Tuple [bytes,bytes] ]] =())

            用于创建请求对象的简化API。

        method

            HTTP请求方式,例如“GET”。

        multipart_form

            将多部分表单数据作为MultiDictView对象。一个空的multidict.MultiDictView如果内容类型表示非表单数据或内容无法解析。

            键和值是字节。

        path

            HTTP请求路径,例如“/index.html”。保证从斜杠开始,除了可能只是“*”的OPTIONS请求。

        path_components

            URL的路径组件作为字符串元组。组件不引用。

        port

            目标端口

        pretty_host

            类似于host,但使用主机头作为附加的首选数据源。这在透明模式下很有用,host只有IP地址,但可能不会反映实际的目的地,因为主机头可能被欺骗。

        pretty_url

            喜欢url,但使用pretty_host而不是host。

        query

            请求查询字符串作为MultiDictView对象。

        raw_content

            原始(编码)HTTP消息体

            另请参阅:content,text

        replace(pattern,repl,flags = 0,count = 0 )

            将标头,请求路径和请求正文中的repl替换为正则表达式模式。编码内容将在更换前进行解码,然后重新编码。
            返回:     更换的数量。

        scheme

            HTTP请求方案,应为“http”或“https”。

        text

            HTTP消息体使用内容编码头(例如gzip)和内容类型头字符集进行解码。
            举:     当内容编码或字符集无效且strict为True时,ValueError。

            另请参阅:content,raw_content

        timestamp_end

            最后一个字节时间戳

        timestamp_start

            第一个字节时间戳

        url

            URL字符串,由请求的URL组件构成

        urlencoded_form

            URL编码的表单数据作为MultiDictView对象。一个空的multidict.MultiDictView如果内容类型表示非表单数据或内容无法解析。

            从mitmproxy 1.0开始,键和值是字符串。

    classmitmproxy.http.HTTPResponse(http_version,status_code,reason,headers,content,timestamp_start = None,timestamp_end = None,is_replay = False )

        一个mitmproxy HTTP响应。

        classmethodwrap(response )

            包裹一个现有的mitmproxy.net.http.Response。

        content

            用内容编码标题解码的HTTP消息体(例如gzip)
            举:     当内容编码无效且严格为True时,ValueError。

            另请参阅:raw_content,text

        cookies

            响应饼干。一个可能是空的 MultiDictView,其中的键是cookie名字符串,值是(value,attr)元组。值是一个字符串,而attr是包含cookie属性的MultiDictView。在attrs中,一元属性(例如HTTPOnly)由Null值指示。

            注意事项:
                更新attr

        decode(strict = True )

            根据当前的Content-Encoding头解码主体,然后删除头。如果没有Content-Encoding标题,则不执行任何操作。
            举:     当内容编码无效且严格为True时,ValueError。

        encode(e )

            用编码e编码,其中e是“gzip”,“deflate”,“identity”或“br”。任何现有的内容编码都被覆盖,内容未被预先解码。
            举:     ValueError,当指定的内容编码无效时。

        get_content(strict:bool = True ) →bytes

            用内容编码标题解码的HTTP消息体(例如gzip)
            举:     当内容编码无效且严格为True时,ValueError。

            另请参阅:raw_content,text

        get_text(strict:bool = True ) →typing.Union [str,NoneType]

            HTTP消息体使用内容编码头(例如gzip)和内容类型头字符集进行解码。
            举:     当内容编码或字符集无效且strict为True时,ValueError。

            另请参阅:content,raw_content

        headers

            消息头对象
            返回:     mitmproxy.net.http.Headers

        http_version

            版本字符串,例如“HTTP / 1.1”

        make(status_code:int = 200,content:typing.Union [bytes,str] = b'',headers:typing.Union [typing.Dict [str,AnyStr],typing.Iterable [typing.Tuple [bytes,bytes]] ] =())

            用于创建响应对象的简化API。

        raw_content

            原始(编码)HTTP消息体

            另请参阅:content,text

        reason

            HTTP原因短语,例如“未找到”。这是始终None为HTTP2请求,因为HTTP2响应不包含原因短语。

        refresh(现在=无)

            这个相当复杂和启发式功能刷新服务器响应重播。

                    它调整日期,到期和最后修改的标题。
                    它调整cookie过期。

        replace(pattern,repl,flags = 0,count = 0 )

            将消息的头文件和正文中的repl替换为正则表达式模式。编码体将在更换前进行解码,之后重新编码。
            返回:     更换的数量。

        status_code

            HTTP状态代码,例如200。

        text

            HTTP消息体使用内容编码头(例如gzip)和内容类型头字符集进行解码。
            举:     当内容编码或字符集无效且strict为True时,ValueError。

            另请参阅:content,raw_content

        timestamp_end

            最后一个字节时间戳

        timestamp_start

            第一个字节时间戳

    classmitmproxy.http.HTTPFlow(client_conn,server_conn,live = None,mode ='regular' )

        HTTPFlow是表示单个HTTP事务的对象的集合。

        request=无

            HTTPRequest 目的

        response=无

            HTTPResponse 目的

        error=无

            Error 目的

            请注意,Flow可以同时具有响应和错误对象。例如,当从服务器收到响应时,可能会发生这种情况,但发送回客户端时发生错误。

        server_conn=无

            ServerConnection 目的

        client_conn=无

            ClientConnection 目的

        intercepted=无

            这个流程目前被截获吗?

        mode=无

            代理层在接收此请求时有什么模式?

        backup(force = False )

            保存此Flow的备份,可以恢复使用对.revert()的调用。

        intercept()

            拦截此流。处理将停止,直到恢复被调用。

        kill()

            杀死这个请求。

        modified()

            这个流程是否被修改?

        resume()

            继续流动 - 在一个intercept()之后调用。

        revert()

            恢复到最后备份状态。

        replace(pattern,repl,* args,** kwargs )

            在流的请求和响应中用repl替换正则表达式模式。编码内容将在更换前进行解码,然后重新编码。

            返回所做的替换次数。

    记录

    类mitmproxy.log.Log(主)

        中央记录器,暴露于脚本作为mitmproxy.ctx.log。

        debug(txt )

            使用级别调试登录。

        info(txt )

            记录级别信息。

        alert(txt )

            记录级别警报。警报与信息具有相同的紧急性,但是向交互式工具发出信号,即使用户当前没有查看事件日志,用户的注意力也应被绘制到输出。

        warn(txt )

            记录级别警告。

        error(txt )

            记录级别错误。
     

     

    展开全文
  • mitmProxy介绍

    千次阅读 2016-07-18 14:32:14
    1+2. 单条flow请求的大概介绍, GET请求, URL, 状态码, 响应类型, 大小; 3. 有个刷新的图标,代表重新request; 4. 橙色代表request正在被拦截, enter进入,按e可进行编辑;  5. 左边右向箭头,代表返回的response被拦截,...
  • mitmproxy

    2019-08-14 18:45:00
    mitmproxy 顾名思义中间人代理【man-in-the-middle proxy】,和fiddler、Charles等工具类似,通过代理方式实现对http(s)的拦截 环境:  1.Python3.6及以上 (python -V查看版本) 2.更新pip(避免部分依赖包未...
  • mitmProxy 总结

    千次阅读 2016-07-18 21:02:04
    mitmproxy [-b IP_ADDR] [-p PORT] ## -b:bind Mac IP -p port 快捷键: q 返回上一页 C [大写]清楚所有 tab 在req和res之间切换,response下数据显示方式切换[json/html...]: m  输入字母“i”(代表Intercept ...
  • 2019年1月1日我要上班很慌啊。。这天气应该躺在被窝里美滋滋的睡觉。...不多说,分割线------------------------------------------------------------------------------------------------------------------------.....
  • mitmproxy 实战

    千次阅读 2019-07-19 00:45:33
    首先附上github地址:https://github.com/mitmproxy/mitmprox,上面的内容永远是最新的 作为一名测试穿戴设备相关app的工程师,与数据打交道是常事,那么,如果想要获取app上传给服务器的文件,怎么获取?上传文件...
  • mitmproxy介绍

    2020-01-20 14:12:48
    文章目录安装配置mitmproxy与python结合使用 安装配置 mitmproxy 使用pip安装好之后,在cmd中直接运行即可mitweb 出现10013,实质上市8080端口号被占用 这里在计算机,管理,服务中查看一下,我的是jenkins,将...
  • MitmProxy+APPnium安装使用指导手册 1、环境搭建 1.1、环境准备 Windows 10版本 64位系统 jdk1.6.0 (64位) android-sdk_r24.3.4-windows Node.js appium .net framework Appium-Python-Client mitmproxy 1.2、...
  • Mitmproxy注意事项

    千次阅读 2018-07-06 08:57:16
    1、安装证书时,连接mitmdump所启动的代理后,访问mitm.it网站,然后选择设备类型的证书,安装即可
  • mitmproxy的安装

    2018-10-23 14:44:45
    此外,mitmproxy还有两个关联组件,一个是mitmdump,它是mitmproxy的命令行接口,利用它可以对接Python脚本,实现监听后的处理;另一个是mitmweb,它是一个Web程序,通过它以清楚地观察到mitmproxy捕获的请求。 本...
  • mitmproxy配置

    万次阅读 2019-03-08 15:02:52
    mitmproxy抓包 mitmproxy是一个支持HTTP和HTTPS的抓包程序,只不过是一个控制台的形式。 安装 pip install mitmproxy 证书配置 对于mitmproxy,如果要截取HTTPS请求,就需要设置证书。...
  •   From:https://blog.wolfogre.com/posts/usage-of-mitmproxy             http://www.cnblogs.c...
1 2 3 4 5 ... 20
收藏数 2,370
精华内容 948
关键字:

mitmproxy