從零開始學 Mitmproxy 抓包工具
本文轉載自微信公眾號「測試開發(fā)剛哥」,作者dongfanger 。轉載本文請聯系測試開發(fā)剛哥公眾號。
Man In The Middle
mitm是Man In The Middle的首字母縮寫,意思是位于中間的人,表明mitmproxy是一個代理,可以攔截請求,實現網絡抓包。知名的網絡抓包工具有Fiddler、Charles、HttpWatch、WireShark、BurpSuite和Postman等,mitmproxy相對來說,沒有這么高的知名度,它相比于以上工具的獨特優(yōu)勢是,它提供了Python API,可以編寫Python代碼對網絡請求進行流量錄制,從而收集接口信息以及轉化為接口自動化用例等。mitmproxy官方文檔不但有mitmproxy工具使用介紹,還有代理實現原理,對我們學習掌握網絡知識有很大幫助。
安裝與使用
pip安裝
pip install mitmproxy
mitmproxy是Python開發(fā)的,用pip就能安裝成功。官方給出了二進制安裝包等方法,我覺得作為一款用Python開發(fā)的工具,用pip直接安裝是更Pythonic的。
命令啟動
可以通過3種命令啟動mitmproxy:
- mitmproxy 控制臺
- mitmweb 網頁
- mitmdump 命令行
它們的內容都是一樣的,只是UI不一樣而已。
手動設置代理
打開以后mitmproxy默認會監(jiān)聽http://localhost:8080,需要設置下代理,把代理服務器設置為這個地址。
Windows可以這樣設置:
設置后一定要記得點擊保存按鈕,否則代理不會生效。
實際上,Charles等網絡抓包工具會自動配置代理,而mitmproxy需要手動設置代理,開發(fā)團隊的解釋是因為瀏覽器版本和配置經常會變化,所以他們建議在網上根據環(huán)境搜索方法手動設置。
下載證書
訪問http://mitm.it/,如果代理配置沒有生效,打開后會是這個界面:
正常的話,會出現證書下載頁面:
根據平臺選擇相應證書安裝就OK了。
使用
mitmproxy更其他抓包工具用法類似。
官方用視頻演示了mitmproxy如何使用:
??https://docs.mitmproxy.org/stable/mitmproxytutorial-userinterface/??
并且介紹了5種運行模式:
??https://docs.mitmproxy.org/stable/concepts-modes/??
讀者可以自行閱讀下。
mitmproxy工作原理
- 客戶端(本機)連接代理服務器(http://127.0.0.1:8080),代理服務器連接服務器。
- 客戶端給代理服務器發(fā)請求,代理服務器把請求發(fā)送到服務器。
所有請求經過mitmproxy,就可以實現請求攔截。
對于HTTP來說,直接借助mitmproxy傳遞請求就可以。而對于HTTPS來說,有個SSL/TLS安全認證,必須安裝證書,服務器才會認為mitmproxy的請求是可信任的,請求才會成功傳遞。
HTTPS的代理過程就要復雜很多,客戶端先跟mitmproxy建立連接(12步),然后進行安全認證(36步),最后傳遞請求(7~8步)。
反向代理
假設在本機使用FastAPI啟動了個Mock服務,地址為http://127.0.0.1:5000,通過Postman調接口,怎么使用mitmproxy來攔截請求呢?這就需要用到反向代理。
首先以反向代理模式運行mitmproxy,服務器端口為5000,監(jiān)聽端口為8000:
mitmproxy --mode reverse:http://127.0.0.1:5000 --listen-host 127.0.0.1 --listen-port 8000
然后把請求http://127.0.0.1:5000/login里面的5000端口改成8000,訪問:
??http://127.0.0.1:8000/login??
就能在mitmproxy看到抓到請求了:
這樣就能在本地使用Mock服務來調試攔截請求的Python代碼了。
反向代理,不需要在本機手動設置代理。
Python API
Python API是mitmproxy的特色功能:
能夠在Python代碼中對攔截的請求進行處理。
addons提供了很多hook函數,比如request:
"""
Basic skeleton of a mitmproxy addon.
Run as follows: mitmproxy -s anatomy.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()
]
response:
"""Add an HTTP header to each response."""
class AddHeader:
def __init__(self):
self.num = 0
def response(self, flow):
self.num = self.num + 1
flow.response.headers["count"] = str(self.num)
addons = [
AddHeader()
]
啟動時加上-s參數指定腳本:
mitmdump -s ./anatomy.py
代碼就會在請求攔截時生效了。
更多hook函數請參考官方說明:
??https://docs.mitmproxy.org/stable/api/events.html??
這里就不再詳細說明了。
而關于如何使用mitmproxy錄制流量自動生成自動化用例的部分,我會開發(fā)完成后集成到tep新版本中,屆時再做介紹,敬請期待。
參考資料:
mitmproxy官方文檔 https://docs.mitmproxy.org/stable/