mitmproxy 插件编写技巧

mitmproxy官方提供了丰富的插件示例,并且mitmproxy核心的功能都是通过插件类实现的

一个基础的插件如下:

"""
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()]

这是一个简单统计请求flow数量的插件,request方法是mitmproxy暴露出的公共方法,在客户端和mitmproxy建立链接产生request事件后,会统一调用所有插件的request。在addons中官方提供了丰富的event hook 可参考Event Hooks & API,比较常用的有:

def running(self):
mitmproxy启动时调用的方法,后续不会再触发

def configure(self, updated: set[str]):
每次配置变更时触发的方法,updated是变更配置的列表

def done(self):
mitmproxy在关闭时调用的方法

def request(self, flow: mitmproxy.http.HTTPFlow):
在获取到完整的请求后,会调用该方法,flow是请求结构体,通过修改flow可以实现如修改请求头、请求内容等操作

def response(self, flow: mitmproxy.http.HTTPFlow):
在获取到完整的响应后,会调用该方法,可修改响应内容和响应头等操作

在执行 -s addons_path 启动mitmproxy后mitmproxy/addons/script.py插件会将自定义的插件注册到运行时中:

    def loadscript(self):
        ctx.log.info("Loading script %s" % self.path)
        if self.ns:
            ctx.master.addons.remove(self.ns)
        self.ns = None
        with addonmanager.safecall():
            ns = load_script(self.fullpath)
            ctx.master.addons.register(ns)
            self.ns = ns
        if self.ns:
            try:
                ctx.master.addons.invoke_addon_sync(
                    self.ns, hooks.ConfigureHook(ctx.options.keys())
                )
            except exceptions.OptionsError as e:
                script_error_handler(self.fullpath, e, msg=str(e))
            if self.is_running:
                # We're already running, so we call that on the addon now.
                ctx.master.addons.invoke_addon_sync(self.ns, hooks.RunningHook())

同时注册的插件会附带一个watcher来检查文件本身的变更,当文件发生变化时重新载入:

    async def watcher(self):
        last_mtime = 0
        while True:
            try:
                mtime = os.stat(self.fullpath).st_mtime
            except FileNotFoundError:
                ctx.log.info("Removing script %s" % self.path)
                scripts = list(ctx.options.scripts)
                scripts.remove(self.path)
                ctx.options.update(scripts=scripts)
                return
            if mtime > last_mtime:
                self.loadscript()
                last_mtime = mtime
            await asyncio.sleep(ReloadInterval)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值