首頁>技術>

我們通常使用的抓包工具就是Fiddler和Charles這種圖形化的,Charles的優點是跨平臺,Windows和Mac都可以使用,Fiddler的優點是功能“極其”強大,不僅擁有抓包功能,還擁有中間人攻擊的功能,但是使用成本太高了,我們做爬蟲開發,使用到Fiddler的功能不過十之二三罷了。今天我們主要講的是mitmproxy這款工具,這是一款專業的中間人攻擊工具,mitmproxy 不僅可以截獲請求幫助開發者檢視、分析,最最重要的是支援Python進行定製化二次開發。例如:截獲瀏覽器的請求內容,並將資料處理後儲存到資料庫,再將內容交給瀏覽器;如果出現異常時,發出郵件通知,並返回給瀏覽器一個空的頁面。mitmproxy有以下幾個特點:

像正常代理一樣轉發請求,保證伺服器和客戶端之間的通訊可以攔截請求/返回,並可以修改請求/返回可以載入Python指令碼執行安裝mitmproxy
pip install mitmproxy

在Python環境中安裝使用pip最為簡潔。mitmproxy安裝完成以後會包含三個工具:mitmproxy、mitmdump、mitmweb。安裝完成以後直接在控制檯輸入mitmproxy --version就可以檢視版本資訊。

檢視版本資訊

注意如果是在Windows系統中安裝,需要先安裝Microsoft Visual C++ V14.0以上版本,並且mitmproxy是不能在Windows系統中進行抓包的,在執行mitmproxy --version命令的時候會得到一個錯誤提示。

Error: mitmproxy's console interface is not supported on Windows. You can run mitmdump or mitmweb instead.

在Windows系統中我們主要使用的是安裝完以後的另外兩個工具mitmdump和mitmweb。

安裝瀏覽器代理外掛SwitchyOmega

為什麼要先安裝瀏覽器代理外掛呢?因為我們在使用抓包工具的時候,必須要通過代理訪問網路,才能抓到包,可以通過設定系統代理的方式來實現,但是直接設定瀏覽器代理會更加方便,而且使用代理外掛我們可以配置多種代理模式。Chrome瀏覽器安裝外掛需要科學上網,只要在度娘搜尋谷歌上網助手,安裝以後重啟瀏覽器,就可以訪問谷歌商店來安裝外掛了,外掛我們這裡推薦SwitchyOmega。安裝完以後要進行設定。

開啟選項開啟設定項新建情景模式

然後在瀏覽器中訪問地址前,先選擇代理方式,再進行訪問

安裝證書

正常情況下,mitmproxy啟動後,只能抓取到HTTP請求的資訊,我們要抓取HTTPS請求資訊需要安裝證書。證書安裝有兩種方式:

第一種首先開啟mitmproxy進行抓包,即執行: mitmproxy或者另外兩個命令訪問http://mitm.it/

如果你沒有開啟mitmproxy進行抓包的話,在這一步你會得到如下錯誤

上面這種方法我一直訪問不到mitm.it這個頁面,可以採用以下方式進行安裝

.cer是Mac或Linux下的證書,.p12是Windows下的證書,.pem是安卓下的證書。

通過上述兩種方式得到證書檔案後,證書按照步驟在網上找,非常多,這裡就不再敖述了。

使用mitmproxy

要啟動 mitmproxy 用 mitmproxy、mitmdump、mitmweb 這三個命令中的任意一個即可,這三個命令功能一致,且都可以載入自定義指令碼,唯一的區別是互動介面的不同。但是他們各有特點,mitmproxy是進行抓包除錯使用的,mitmweb是mitmproxy的可視版本,mitmdump主要是載入指令碼執行的,因為mitmdump抓取的資訊是不主動顯示的,由我們在指令碼中使用特定列印方式,輸出到介面,方便我們除錯,當然也可以直接使用print列印。

在控制檯中輸入mitmdump -h,可以檢視命令列幫助,我們主要使用的是-s和-p引數,-p指定監聽埠,預設埠為8080,如果和其他軟體有衝突,可以通過此引數修改;-s指定執行指令碼,這個就是我們用mitmproxy的主要作用,通過載入指令碼,執行請求過程的中間處理,修改請求資料或者儲存返回資料。目前有兩種使用方式:

from mitmproxy import httpfrom mitmproxy import ctxdef response(flow: http.HTTPFlow):    """    flow為引數,後面跟http.HTTPFlow表示宣告其型別,    這樣在IDE中就可以自動提示其屬性和方法,這是Python為我們提供的一種    便攜的方式,尤其是對外提供介面時,可以告知引數型別,這種方式是可選    的,當然你也可以使用常用方式,即不知道引數型別,只寫引數名即可    """    ctx.log.info(flow.request.url)    ctx.log.warn(flow.request.headers)

mitmproxy.ctx.log為mitmproxy為我們提供的日誌列印方式。

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

官方推薦使用類的方式,上面的程式碼可能讓你有點迷茫,無論是使用類方式還是函式方式def reqeust函式都是在mitmdump內部回撥時會呼叫的,mitmdump就是使用這種事件回撥的方式,為我們提供了資料流的操作方式,那首先我們要了解mitmproxy為我們提供的事件(我們只關注HTTP相關的事件)。

class Events:    def request(self, flow: http.HTTPFlow):        """            The full HTTP request has been read.        """    def response(self, flow: http.HTTPFlow):        """            The full HTTP response has been read.        """

request為請求傳送至伺服器前的回撥函式,如果我們想對傳送給伺服器的請求進行修改,可以在這裡進行處理。response為伺服器將請求資料返回給我們時的回撥函式,這裡就是我們爬取到的資料,在這裡我們可以對資料進行處理,做入庫處理。

我們在爬蟲中使用mitmproxy,主要就是對Request和Response物件進行操作,下面我在原始碼中把對應的屬性和方法都找出來,作為參考,就當作是字典一樣來查詢即可。原始碼在GitHub上下載,路徑為:mitmproxy/net/http/request.py和mitmproxy/net/http/response.py。

Request
flow.request.cookies       #獲取請求的cookiesflow.request.headers      # 獲取所有頭資訊,包含Host、User-Agent、Content-type等欄位flow.request.url               # 完整的請求地址,包含域名及請求引數,但是不包含放在body裡面的請求引數flow.request.host             # 域名flow.request.method        # 請求方式。POST、GET等flow.request.scheme        # 請求型別 ,如 http、httpsflow.request.path             # 請求的路徑,url除域名之外的內容flow.request.text              # 請求中body內容,可以獲取某些請求的引數,返回字典型別flow.request.replace()      # 使用正則替換content中的內容flow.request.query           # 返回MultiDictView型別的資料,url直接帶的鍵值引數,一般是GET請求的引數flow.request.content        # bytes,結果如flow.request.textflow.request.raw_content      # bytes,結果如flow.request.get_content()flow.request.urlencoded_form  # MultiDictView,content-type:application/x-www-form-urlencoded 時的請求引數,不包含url直接帶的鍵值引數flow.request.multipart_form   # MultiDictView,content-type:multipart/form-data 時的請求引數,不包含url直接帶的鍵值引數
Response
flow.response.status_code  # 狀態碼flow.response.text            # 返回內容,已解碼flow.response.content      # 返回內容,二進位制flow.response.cookies     # 返回的cookiesflow.response.headers    # 返回的請求頭flow.response.replace()      # 使用正則替換content中的內容

要特別注意,返回值為字典的型別的,不能直接在控制檯列印,可以使用str修飾,或者按照字典方式進行輸出。

以下為測試示例:

示例中使用兩個類Demo1、Demo2,主要是為大家展示類方式的好處,即可以使用多個類,每個類處理進行獨立的邏輯處理,每個類當中都可以同時使用request、response函式,希望不要因為例子裡面而誤導了大家。下面再說一點進階用法,每一個處理類,都可以單獨寫一個py檔案,再統一定義一個py檔案,匯入處理類,定義一個列表變數addons,變數中儲存所有處理類的例項,示例如下:demo1.py

from mitmproxy import httpclass Demo1:    def request(self, flow: http.HTTPFlow):        print('request url', flow.request.url)        print('request name', flow.request.query.get('name'))        print('request age', flow.request.query.get('age'))        flow.request.query['name'] = 'yuehan'

demo2.py

from mitmproxy import httpclass Demo2:    def response(self, flow: http.HTTPFlow):        print('response name', flow.request.query.get('name'))

spider.py

import demo1import demo2addons = [    demo1.Demo1(),    demo2.Demo2()]
抓包命令mitmdump -p 8888 -s spider.py

參考文章:

1.使用 mitmproxy + python 做攔截代理 https://blog.wolfogre.com/posts/usage-of-mitmproxy/

2.如何突破網站對selenium的遮蔽 https://blog.csdn.net/qq_26877377/article/details/83307208

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 《Electron實戰》中文版:構建應用程式選單及上下文選單