mitmproxy模塊提供的使用方式是使用命令行來(lái)開(kāi)一個(gè)代理,這里用python代碼調(diào)用mitmproxy的方法馋劈,開(kāi)一個(gè)代理攻锰,獲取請(qǐng)求信息晾嘶,并添加到隊(duì)列中妓雾,供后續(xù)掃描使用。
本文使用的環(huán)境:
Python 3.7.0
mitmproxy 5.2
安裝
安裝:pip install mitmproxy
垒迂。依賴多械姻,國(guó)內(nèi)安裝慢,建議用國(guó)內(nèi)鏡像來(lái)安裝:pip install -i https://mirrors.aliyun.com/pypi/simple/ mitmproxy
啟動(dòng)代理
可以直接用:
from mitmproxy.tools.main import mitmdump
mitmdump(args="--listen-port=6666 -m upstream:127.0.0.1:8080 --proxyauth=root:root".split(" "))
來(lái)啟動(dòng)代理机断,args參數(shù)跟調(diào)用mitmdump
命令時(shí)傳的參數(shù)一樣楷拳。因?yàn)槠鸪踉诰W(wǎng)上搜,搜到的是另一段代碼吏奸,所以沒(méi)用這種簡(jiǎn)潔的方式欢揖,用的是:
#!/usr/bin/python3
# -*-coding:utf-8-*-
import time
import queue
from multiprocessing import Process, freeze_support, Queue
from mitmproxy import proxy, options
from mitmproxy.http import HTTPFlow
from mitmproxy.tools.dump import DumpMaster
class Handler:
"""
將請(qǐng)求加入隊(duì)列
"""
def __init__(self, req_queue: Queue):
self.req_queue = req_queue
def request(self, flow: HTTPFlow):
request_dict = {
"method": flow.request.method,
"url": flow.request.url,
"headers": [(key, flow.request.headers[key]) for key in flow.request.headers],
"cookies": [(key, flow.request.cookies[key]) for key in flow.request.cookies],
"data": flow.request.text
}
try:
print(request_dict.get("url"))
self.req_queue.put(request_dict, timeout=2)
except queue.Full:
pass
def response(self, flow: HTTPFlow):
pass
def responseheaders(self, flow: HTTPFlow):
pass
def do_start_proxy(req_queue):
opts = options.Options(listen_host="127.0.0.1", listen_port=6666)
m = DumpMaster(opts, with_termlog=False, with_dumper=False)
pconf = proxy.config.ProxyConfig(opts)
m.server = proxy.server.ProxyServer(pconf)
m.addons.add(Handler(req_queue))
print("Proxy server listening at http://127.0.0.1:6666")
m.run()
# m.shutdown()
def start_proxy(req_queue):
freeze_support()
p = Process(target=do_start_proxy, args=(req_queue, ))
p.start()
return p
if __name__ == "__main__":
req_queue = Queue(6000)
p = start_proxy(req_queue)
try:
while True:
# 從req_queue獲取請(qǐng)求,進(jìn)行處理
time.sleep(300)
except KeyboardInterrupt:
p.terminate()
p.join()
下文將以這種方式來(lái)說(shuō)明
插件編寫(xiě)
上面使用子進(jìn)程啟動(dòng)mitmproxy奋蔚,然后通過(guò)m.addons.add(Handler(req_queue))
注冊(cè)插件她混,該插件將收到的請(qǐng)求信息添加到隊(duì)列中,以便后續(xù)使用泊碑。
Handler
類就是插件坤按。其request
方法在mitmproxy接到請(qǐng)求后調(diào)用,response
方法在收到響應(yīng)后調(diào)用馒过,responseheaders
方法在收到響應(yīng)頭部時(shí)就調(diào)用.(更多的回調(diào)方法參考這里)臭脓。這些回調(diào)方法,通常接收一個(gè)flow參數(shù)腹忽,可以用來(lái)獲取請(qǐng)求和響應(yīng)信息来累,使用也簡(jiǎn)單砚作,看這里就行。
注意: 不要在
request()
里用到flow.response
嘹锁,否則會(huì)卡住
HTTPS證書(shū)
mitmproxy已經(jīng)處理好證書(shū)了偎巢。將瀏覽器代理指向mitmproxy,訪問(wèn)mitm.it
兼耀,下載安裝證書(shū)就行
option配置
上面那段代碼中:
opts = options.Options(listen_host="127.0.0.1", listen_port=6666)
m = DumpMaster(opts, with_termlog=False, with_dumper=False)
pconf = proxy.config.ProxyConfig(opts)
m.server = proxy.server.ProxyServer(pconf)
m.addons.add(Handler(req_queue))
listen_host
配置代理監(jiān)聽(tīng)地址压昼,listen_port
配置代理監(jiān)聽(tīng)端口。with_templog
為T(mén)rue時(shí)會(huì)輸出客戶端連接瘤运、斷開(kāi)信息窍霞,如:127.0.0.1:53033: clientconnect 127.0.0.1:53034: clientconnect
;with_dumper
為T(mén)rue時(shí)拯坟,輸出連接信息:請(qǐng)求方法但金、URL、狀態(tài)碼等郁季。所有可配置的option冷溃,看這里。
舉兩個(gè)其它的配置:
配置上流代理(mitmproxy的流量都傳到這個(gè)proxy):
opts.update(mode="upstream:127.0.0.1:1080") # 所有接收到流量都傳到127.0.0.1:1080這個(gè)代理去
opts.update(ssl_insecure=True) # 不驗(yàn)證上流代理給的https證書(shū)
配置代理的賬號(hào)密碼:
opts.update(proxyauth="root:root")
這句代碼要在初始化DumpMaster
類后再調(diào)用梦裂。因?yàn)檫@個(gè)配置選項(xiàng)是由內(nèi)置插件ProxyAuth
提供的似枕,該插件在初始化DumpMaster
類時(shí)添加。
總結(jié)
感覺(jué)直接調(diào)用mitmdump
函數(shù)簡(jiǎn)單些年柠。一開(kāi)始用的是網(wǎng)上給的凿歼,沒(méi)看源碼,不知道有這種方式冗恨。