博客 / 詳情

返回

Mock 工具與定製化

簡介

mitmproxy 是一款開源、免費的代理工具,支持 mac、windows、linux。相比於其他代理工具,可以通過 python 和 mitmproxy 工具本身的插件機制實現通過腳本對 mitmproxy 的完全控制。強大的可拓展性和可定製性,可以讓測試工程師以 mitmproxy 工具為基礎,進行二次開發,打造更適合自己業務的 mock 工具。

官方網站:

https://mitmproxy.org/

操作步驟

安裝

mitmproxy 是一款跨平台工具,支持在 windows、linux、 mac 平台進行安裝。最推薦的安裝方式是直接通過 python 進行安裝。安裝步驟:

  • 安裝好 python 環境(最低要求 python3.6)
  • pip install pipx
  • pipx install mitmproxy

輸入命令驗證是否安裝成功:

-

mitmdump --version

如果有如下的返回信息,證明環境已經安裝成功:

Mitmproxy: 5.2Python:    3.8.7OpenSSL:   OpenSSL 1.1.1g  21 Apr 2020Platform:  macOS-10.15-x86_64-i386-64bit

證書配置

mitmproxy 的證書配置過程與 charles 類似

pc 端證書

  • 配置電腦代理,ip 配置 127.0.0.1 ,端口配置為 mitmproxy 監聽端口,默認 8080
  • 啓動 mitmprxy
  • 在瀏覽器輸入地址 mitm.it,顯示效果如果和下圖相同,證明前面的步驟都成功了
  • 選擇對應系統下載證書並安裝。
  • 信任證書:打開證書(Mac 系統為鑰匙串訪問)->點擊證書->雙擊名稱含有 charles 的選項->點擊信任->選擇始終信任。

windows 證書信任

在這裏插入圖片描述

手機端證書(安卓系統)

  • 在手機配置代理,ip 配置為電腦的 ip 地址,端口配置為 mitmproxy 監聽端口,默認 8080。
  • 啓動 mitmprxy。
  • 在手機瀏覽器輸入地址 mitm.it。
  • 選擇 Android,下載並安裝,即可成功抓取手機端的 https 的數據包。

三大核心工具

mitmproxy 有三大核心工具,分別為 mitmproxy、mitmweb、mitmdump。mitmdump 是 mitmproxy 相比於其他代理工具最獨一無二的部分,所以會以 mitmdump 的介紹為主。

  • mitmproxy

是一款交互式的命令行工具,通過命令mitmproxy啓動,需要注意的是 mitmproxy 不支持 windows 系統。下圖為 mitmproxy 啓動後的效果圖:

在這裏插入圖片描述

  • mitmweb

在 mitmweb 的圖形界面中使用 mitmproxy 的主要功能,通過命令mitmweb啓動。它和 Chrome 開發者工具中的 network 比較類似。下圖為 mitmweb 啓動後的效果圖:

在這裏插入圖片描述

  • mitmdump

用 mitmdump 編寫強大的插件和腳本。mitmproxy 腳本 API 提供了對 mitmproxy 的完全控制,可以自動修改消息、重定向流量、可視化消息或實現自定義命令。後面會通過實戰具體介紹 mitmdump 的使用。

mitmdump 實戰

  • 命令

mitmdump 可以通過參數 -s 實現執行 python 腳本

通過下面這個示例每次再發起請求時都要打印 "this is a demo"

mitm_demo.py

from mitmproxy import http
def request(flow: http.HTTPFlow):    #每次請求時都打印 this is a demo    print("this is a demo")

通過命令 mitmdump 執行 python 腳本

-

mitmdump -s ./mitm_demo.py

執行效果

Loading script ./mitm_demo.pyProxy server listening at http://*:8080127.0.0.1:53741: clientconnect127.0.0.1:53758: clientconnect127.0.0.1:53759: clientconnect127.0.0.1:53760: clientconnectthis is a demo127.0.0.1:53758: Connection killed127.0.0.1:53758: clientdisconnectthis is a demo127.0.0.1:53759: Connection killed127.0.0.1:53759: clientdisconnect
  • 插件

mitmproxy 是通過變量addons,將一個類的實例與 mitmproxy 進行關聯的。通過插件機制,可以指定在腳本運行中,與 mitmproxy 直接相關的實例。

mitm_addon.py

from mitmproxy import ctx

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

有幾點需要注意的是:

  • Mitmproxy 是通過 addons 這個全局變量獲取以及加載插件組件。
  • 每個插件都是一個實例對象,比如上面例子中的Counter()。
  • 方法 requests 是一個事件的示例。在後面會有關於事件的具體介紹。
  • 這個插件實現了在每一次請求的時候打印累計的請求 flow 數據。

執行命令

-

mitmdump -s ./mitm_demo.py

展示效果:

...省略..
127.0.0.1:49625: clientconnect
We've seen 9 flows
127.0.0.1:49600: GET https://www.baidu.com/content-search.xml
              << 200 OK 220b
We've seen 10 flows
127.0.0.1:49599: GET https://www.baidu.com/home/xman/data/tipspluslist?indextype=manht&_req_seqid=0xaf491b1700068f01&asyn=1&t=1618453717212&sid=33811_33816_33745_33344_31253_33849_33758_26350_22158
              << 200 OK 78b
  • 事件

mitmproxy 有多個事件, 每個函數或方法代表一個事件,指每一次請求響應的過程中,都會自動調用相關的方法。每一個方法的名稱都是 mitmproxy 約定好的,都代表了 flow 的不同過程。

許多事件通過參數接收一個 flow 對象,通過修改這些對象,插件就可以即時改變流量。


import mitmproxy.http
class Events:

    def request(self, flow: mitmproxy.http.HTTPFlow):
        """
            每次http發起請求之後會調用這個方法
        """


    def response(self, flow: mitmproxy.http.HTTPFlow):
        """
            每次http返回響應之後會調用這個方法
        """
  • mitmproxy 實現 map local
  • 瀏覽器訪問
  • https://httpbin.testing-studio.com/get
  • 響應結果如圖所示,成功實現 map local:
  • 在這裏插入圖片描述
  • 通過命令執行 python 腳本
  • mitmdump -s ./mitm_map_local.py
  • 編寫腳本,在請求事件中,給響應對象賦值為設定的模擬值
  • mitm_map_local.py
  • 
    import json
    
    from mitmproxy import ctx, http
    
    class Counter:
    def __init__(self):
       self.num = 0
    
    def request(self, flow):
       if "https://httpbin.testing-studio.com/get" in flow.request.pretty_url:
           # 打開文件,讀取文件數據,作為響應,給返回
           with open("./res.json", encoding="utf-8") as f:
               # 給flow.response屬性進行賦值,
               # 賦值調用mitmproxy 響應對象的 make方法
               # 響應體在make函數裏面所需要的數據為str
               flow.response = http.HTTPResponse.make\
                   (200,  # (optional) status code
                   f.read(),  # (optional) content
               {"Content-Type": "text/html"}  # (optional) headers
                   )
    
    addons = [
    Counter()
    ]
    
    創建一個本地文件,響應數據設定為
    { "status": "success" }

總結

  • 安裝
  • 證書配置
  • 三大核心工具
  • mitmdump 實戰
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.