在 Python 程式中啟動 mitmproxy 並控制 addon

黑水發表於2020-11-15

mitmproxy 本身是個 Python 包,比如mitmweb命令實際是如下程式碼

#!/Users/niconi/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from mitmproxy.tools.main import mitmweb
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(mitmweb())

mitmproxy 提供了 addon 的方式編寫代理規則,比如如下 addon 給每個請求加上一個請求頭 mitmproxy:default

# addon.py
from mitmproxy import contentviews, http

class Rewrite:
flag = 'default'

@classmethod
def set_flag(self, value):
self.flag = value


def request(self, flow):
flow.request.headers['mitmproxy'] = self.flag


addons = [
Rewrite()
]

如果只是想在一個 Python 程式中啟動 mitmproxy,可以用 subprocess,但因為是另一個記憶體空間,很難做到在程式執行時控制 addon,用執行緒可以達到這個效果:

# mitmweb_wraper.py
from mitmproxy import proxy, options
from mitmproxy.tools.web.master import WebMaster
import threading,asyncio

import addon


class MitmWebWraper(object):
mitmweb = None
thread = None

def loop_in_thread(self, loop, mitmweb):
asyncio.set_event_loop(loop)
mitmweb.run()

def start(self):
opts = options.Options(listen_host='0.0.0.0', listen_port=8080,
confdir='~/.mitmproxy', ssl_insecure=True)
pconf = proxy.config.ProxyConfig(opts)
self.mitmweb = WebMaster(opts)
self.mitmweb.server = proxy.server.ProxyServer(pconf)
self.mitmweb.addons.add(addon)
loop = asyncio.get_event_loop()
self.thread = threading.Thread(
target=self.loop_in_thread, args=(loop, self.mitmweb))

try:
self.thread.start()
except KeyboardInterrupt:
self.mitmweb.shutdown()


if __name__ == "__main__":
mitmweb_wraper = MitmWebWraper()
mitmweb_wraper.start()

在另一個 Python 程式中,通過 mitmweb_wraper 啟動 mitmweb,並且 import addon,對 addon 的修改會立即生效,新增的請求頭會變成 mitmproxy:changed

import mitmweb_wraper, addon

mitmweb_wraper = mitmweb_wraper.MitmWebWraper()
mitmweb_wraper.start()

addon.Rewrite().set_flag('changed')

相關文章