從零開(kāi)始學(xué) Mitmproxy 抓包工具
本文轉(zhuǎn)載自微信公眾號(hào)「測(cè)試開(kāi)發(fā)剛哥」,作者dongfanger 。轉(zhuǎn)載本文請(qǐng)聯(lián)系測(cè)試開(kāi)發(fā)剛哥公眾號(hào)。
Man In The Middle
mitm是Man In The Middle的首字母縮寫,意思是位于中間的人,表明mitmproxy是一個(gè)代理,可以攔截請(qǐng)求,實(shí)現(xiàn)網(wǎng)絡(luò)抓包。知名的網(wǎng)絡(luò)抓包工具有Fiddler、Charles、HttpWatch、WireShark、BurpSuite和Postman等,mitmproxy相對(duì)來(lái)說(shuō),沒(méi)有這么高的知名度,它相比于以上工具的獨(dú)特優(yōu)勢(shì)是,它提供了Python API,可以編寫Python代碼對(duì)網(wǎng)絡(luò)請(qǐng)求進(jìn)行流量錄制,從而收集接口信息以及轉(zhuǎn)化為接口自動(dòng)化用例等。mitmproxy官方文檔不但有mitmproxy工具使用介紹,還有代理實(shí)現(xiàn)原理,對(duì)我們學(xué)習(xí)掌握網(wǎng)絡(luò)知識(shí)有很大幫助。
安裝與使用
pip安裝
pip install mitmproxy
mitmproxy是Python開(kāi)發(fā)的,用pip就能安裝成功。官方給出了二進(jìn)制安裝包等方法,我覺(jué)得作為一款用Python開(kāi)發(fā)的工具,用pip直接安裝是更Pythonic的。
命令啟動(dòng)
可以通過(guò)3種命令啟動(dòng)mitmproxy:
- mitmproxy 控制臺(tái)

- mitmweb 網(wǎng)頁(yè)

- mitmdump 命令行
它們的內(nèi)容都是一樣的,只是UI不一樣而已。
手動(dòng)設(shè)置代理
打開(kāi)以后mitmproxy默認(rèn)會(huì)監(jiān)聽(tīng)http://localhost:8080,需要設(shè)置下代理,把代理服務(wù)器設(shè)置為這個(gè)地址。
Windows可以這樣設(shè)置:

設(shè)置后一定要記得點(diǎn)擊保存按鈕,否則代理不會(huì)生效。
實(shí)際上,Charles等網(wǎng)絡(luò)抓包工具會(huì)自動(dòng)配置代理,而mitmproxy需要手動(dòng)設(shè)置代理,開(kāi)發(fā)團(tuán)隊(duì)的解釋是因?yàn)闉g覽器版本和配置經(jīng)常會(huì)變化,所以他們建議在網(wǎng)上根據(jù)環(huán)境搜索方法手動(dòng)設(shè)置。
下載證書(shū)
訪問(wèn)http://mitm.it/,如果代理配置沒(méi)有生效,打開(kāi)后會(huì)是這個(gè)界面:

正常的話,會(huì)出現(xiàn)證書(shū)下載頁(yè)面:

根據(jù)平臺(tái)選擇相應(yīng)證書(shū)安裝就OK了。
使用
mitmproxy更其他抓包工具用法類似。
官方用視頻演示了mitmproxy如何使用:
??https://docs.mitmproxy.org/stable/mitmproxytutorial-userinterface/??
并且介紹了5種運(yùn)行模式:
??https://docs.mitmproxy.org/stable/concepts-modes/??
讀者可以自行閱讀下。
mitmproxy工作原理

- 客戶端(本機(jī))連接代理服務(wù)器(http://127.0.0.1:8080),代理服務(wù)器連接服務(wù)器。
- 客戶端給代理服務(wù)器發(fā)請(qǐng)求,代理服務(wù)器把請(qǐng)求發(fā)送到服務(wù)器。
所有請(qǐng)求經(jīng)過(guò)mitmproxy,就可以實(shí)現(xiàn)請(qǐng)求攔截。
對(duì)于HTTP來(lái)說(shuō),直接借助mitmproxy傳遞請(qǐng)求就可以。而對(duì)于HTTPS來(lái)說(shuō),有個(gè)SSL/TLS安全認(rèn)證,必須安裝證書(shū),服務(wù)器才會(huì)認(rèn)為mitmproxy的請(qǐng)求是可信任的,請(qǐng)求才會(huì)成功傳遞。

HTTPS的代理過(guò)程就要復(fù)雜很多,客戶端先跟mitmproxy建立連接(12步),然后進(jìn)行安全認(rèn)證(36步),最后傳遞請(qǐng)求(7~8步)。
反向代理
假設(shè)在本機(jī)使用FastAPI啟動(dòng)了個(gè)Mock服務(wù),地址為http://127.0.0.1:5000,通過(guò)Postman調(diào)接口,怎么使用mitmproxy來(lái)攔截請(qǐng)求呢?這就需要用到反向代理。
首先以反向代理模式運(yùn)行mitmproxy,服務(wù)器端口為5000,監(jiān)聽(tīng)端口為8000:
mitmproxy --mode reverse:http://127.0.0.1:5000 --listen-host 127.0.0.1 --listen-port 8000
然后把請(qǐng)求http://127.0.0.1:5000/login里面的5000端口改成8000,訪問(wèn):
??http://127.0.0.1:8000/login??
就能在mitmproxy看到抓到請(qǐng)求了:

這樣就能在本地使用Mock服務(wù)來(lái)調(diào)試攔截請(qǐng)求的Python代碼了。
反向代理,不需要在本機(jī)手動(dòng)設(shè)置代理。
Python API
Python API是mitmproxy的特色功能:

能夠在Python代碼中對(duì)攔截的請(qǐng)求進(jìn)行處理。
addons提供了很多hook函數(shù),比如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()
]
啟動(dòng)時(shí)加上-s參數(shù)指定腳本:
mitmdump -s ./anatomy.py
代碼就會(huì)在請(qǐng)求攔截時(shí)生效了。
更多hook函數(shù)請(qǐng)參考官方說(shuō)明:
??https://docs.mitmproxy.org/stable/api/events.html??
這里就不再詳細(xì)說(shuō)明了。
而關(guān)于如何使用mitmproxy錄制流量自動(dòng)生成自動(dòng)化用例的部分,我會(huì)開(kāi)發(fā)完成后集成到tep新版本中,屆時(shí)再做介紹,敬請(qǐng)期待。
參考資料:
mitmproxy官方文檔 https://docs.mitmproxy.org/stable/


































