在Python脚本中使用mitmproxy

10

我是mitmproxy的新手。但我无法弄清如何在Python脚本中使用它。

我想把mitmproxy像库一样放入我的Python脚本中,并指定端口或主机,以及在我的Python脚本中对请求或响应进行修改。 当我像这样启动我的脚本:

python sample.py

一切都将自动运行,无需像这样从命令行运行mitmproxy。

mitmproxy -s sample.py

谢谢阅读。
感谢您的阅读。
3个回答

12
您可以使用类似以下的代码。此代码取自于在 mitmproxy 的 Github 上发布的一个问题,链接在 这里
from mitmproxy import proxy, options
from mitmproxy.tools.dump import DumpMaster
from mitmproxy.addons import core


class AddHeader:
    def __init__(self):
        self.num = 0

    def response(self, flow):
        self.num = self.num + 1
        print(self.num)
        flow.response.headers["count"] = str(self.num)


addons = [
    AddHeader()
]

opts = options.Options(listen_host='127.0.0.1', listen_port=8080)
pconf = proxy.config.ProxyConfig(opts)

m = DumpMaster(None)
m.server = proxy.server.ProxyServer(pconf)
# print(m.addons)
m.addons.add(addons)
print(m.addons)
# m.addons.add(core.Core())

try:
    m.run()
except KeyboardInterrupt:
    m.shutdown()

1
谢谢您提供的示例!但是,对于我来说,AddHeader插件从未被触发,因为如果您使用.add()添加一个数组,实际上是将另一个数组添加到当前的“ addons”数组中,这将导致 AddHeader()插件无法读取。不管怎样,对于其他遇到相同问题的人们,请执行以下操作:m.addons.add(AddHeader())而非m.addons.add(addons)。 - Vasco
我认为你可以使用Python的list.extend方法。 - Phani Rithvij
@Vasco 非常感谢,您的补充应该修改了答案。在我按照您所写的做之前,它对我也不起作用。 - shaya ajzner

6
以编程方式在后台启动mitmproxy,以将其集成到现有应用程序中:
from mitmproxy.options import Options
from mitmproxy.proxy.config import ProxyConfig
from mitmproxy.proxy.server import ProxyServer
from mitmproxy.tools.dump import DumpMaster

import threading
import asyncio
import time

class Addon(object):
    def __init__(self):
        self.num = 1

    def request(self, flow):
        flow.request.headers["count"] = str(self.num)

    def response(self, flow):
        self.num = self.num + 1
        flow.response.headers["count"] = str(self.num)
        print(self.num)


# see source mitmproxy/master.py for details
def loop_in_thread(loop, m):
    asyncio.set_event_loop(loop)  # This is the key.
    m.run_loop(loop.run_forever)


if __name__ == "__main__":
    options = Options(listen_host='0.0.0.0', listen_port=8080, http2=True)
    m = DumpMaster(options, with_termlog=False, with_dumper=False)
    config = ProxyConfig(options)
    m.server = ProxyServer(config)
    m.addons.add(Addon())

    # run mitmproxy in backgroud, especially integrated with other server
    loop = asyncio.get_event_loop()
    t = threading.Thread( target=loop_in_thread, args=(loop,m) )
    t.start()

    # Other servers, such as a web server, might be started then.
    time.sleep(20)
    print('going to shutdown mitmproxy')
    m.shutdown()

来自我的代码片段


一般来说,我会移除额外的线程包装事件循环和 sleep(20),因为大多数情况下不需要它,而且会令人困惑。 - Jossef Harush Kadouri
在这种情况下,您如何实现流请求拦截?例如:def request(flow: http.HTTPFlow) -> None: print(flow.request.headers) - desmond
我该如何向插件发送选项?我已经在我的对象的load()方法中定义了选项,并且可以使用--set命令行参数填充它们,但不确定如何在Python脚本中实现。 - MikeSchem
1
@MikeSchem 请查看 https://github.com/mitmproxy/mitmproxy/blob/v5.3.0/examples/addons/options-simple.py#L6 - Iceberg
1
@Sully,谢谢你,但实际上它仍然是从脚本中运行的。我正在尝试在Python脚本内部运行它。我只是将我的变量传递给__init__并将它们设置为对象级别变量,这样就可以工作了。不过还是谢谢! - MikeSchem
嗨@Iceberg,我想在线程中中断或重新启动mitmproxy。 我使用m.shutdown()来中断mitmproxy,然后当我重新启动线程时出现错误: RuntimeError: Event loop is closed 这意味着当我使用asyncio.get_event_loop()时,我得到了相同的循环,所以当我执行shutdown()来关闭循环时,我无法再次启动它。 我尝试使用asyncio.new_event_loop()来获取一个新的循环,但是这似乎与mitmproxy内部的循环冲突。 - Alex

0
from mitmproxy.tools.main import mitmdump

mitmdump(args=["-s", "myaddon.py"])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接