mitmproxy模塊提供的使用方式是使用命令行來開一個代理,這里用python代碼調(diào)用mitmproxy的方法,開一個代理,獲取請求信息,并添加到隊列中,供后續(xù)掃描使用。
本文使用的環(huán)境:
Python 3.7.0
mitmproxy 5.2
安裝
安裝:pip install mitmproxy。依賴多,國內(nèi)安裝慢,建議用國內(nèi)鏡像來安裝:pip install -i https://mirrors.aliyun.com/pypi/simple/ mitmproxy
啟動代理
可以直接用:
from mitmproxy.tools.main import mitmdump
mitmdump(args="--listen-port=6666 -m upstream:127.0.0.1:8080 --proxyauth=root:root".split(" "))
來啟動代理,args參數(shù)跟調(diào)用mitmdump命令時傳的參數(shù)一樣。因為起初在網(wǎng)上搜,搜到的是另一段代碼,所以沒用這種簡潔的方式,用的是:
#!/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:
"""
將請求加入隊列
"""
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獲取請求,進行處理
time.sleep(300)
except KeyboardInterrupt:
p.terminate()
p.join()
下文將以這種方式來說明
插件編寫
上面使用子進程啟動mitmproxy,然后通過m.addons.add(Handler(req_queue))注冊插件,該插件將收到的請求信息添加到隊列中,以便后續(xù)使用。
Handler類就是插件。其request方法在mitmproxy接到請求后調(diào)用,response方法在收到響應(yīng)后調(diào)用,responseheaders方法在收到響應(yīng)頭部時就調(diào)用.(更多的回調(diào)方法參考這里)。這些回調(diào)方法,通常接收一個flow參數(shù),可以用來獲取請求和響應(yīng)信息,使用也簡單,看這里就行。
注意: 不要在
request()里用到flow.response,否則會卡住
HTTPS證書
mitmproxy已經(jīng)處理好證書了。將瀏覽器代理指向mitmproxy,訪問mitm.it,下載安裝證書就行
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)聽地址,listen_port配置代理監(jiān)聽端口。with_templog為True時會輸出客戶端連接、斷開信息,如:127.0.0.1:53033: clientconnect 127.0.0.1:53034: clientconnect;with_dumper為True時,輸出連接信息:請求方法、URL、狀態(tài)碼等。所有可配置的option,看這里。
舉兩個其它的配置:
配置上流代理(mitmproxy的流量都傳到這個proxy):
opts.update(mode="upstream:127.0.0.1:1080") # 所有接收到流量都傳到127.0.0.1:1080這個代理去
opts.update(ssl_insecure=True) # 不驗證上流代理給的https證書
配置代理的賬號密碼:
opts.update(proxyauth="root:root")
這句代碼要在初始化DumpMaster類后再調(diào)用。因為這個配置選項是由內(nèi)置插件ProxyAuth提供的,該插件在初始化DumpMaster類時添加。
總結(jié)
感覺直接調(diào)用mitmdump函數(shù)簡單些。一開始用的是網(wǎng)上給的,沒看源碼,不知道有這種方式。