9

I new in mitmproxy. But I can't figure out how to used that in python script.

I want to put mitmproxy into my python script just like a library and also specific everything like port or host and do some modify with Request or Response in my python script. So when I start my script like this

python sample.py

Everything will run automatic without run mitmproxy from commandline like this

mitmproxy -s sample.py

Thanks for reading.

j3ssie
  • 91
  • 1
  • 2
  • 3

3 Answers3

11

You can use something like this. This code was taken from an issue posted on the mithproxy github found here

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()
securisec
  • 3,435
  • 6
  • 36
  • 63
  • 1
    Thanks for your example! Only for me the AddHeader addon never got triggered, because if you .add() the array, you're essentially adding another array to the current 'addons' array, which will result in the AddHeader() addon not being read. Eitherway for other people experiencing the same issue; just do do this: m.addons.add(AddHeader()) instead of m.addons.add(addons) – Vasco May 30 '20 at 09:22
  • I think you can use `list.extend` python method. – Phani Rithvij Oct 03 '21 at 05:10
  • @Vasco Thanks very much, the answer should be modified with your addition. It wasn't working for me either until I did what you wrote. – shaya ajzner Apr 04 '22 at 11:11
6

Start mitmproxy in the background programmatically to integrate it into an existing app:

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

from my gist

Iceberg
  • 2,744
  • 19
  • 19
  • generally speaking, I would remove the extra thread wrapping the event loop + `sleep(20)` since most cases would not require that and it's confusing – Jossef Harush Kadouri Oct 03 '20 at 09:04
  • in this case how do you implement the flow request interception? e.g. def request(flow: http.HTTPFlow) -> None: print(flow.request.headers) – desmond Dec 15 '20 at 12:25
  • how would I send an option to the Addon? I've already got the options defined in my load() method on my object, and can fill them with the --set command line argument, but not sure how to do that in a python script. – MikeSchem Jan 15 '21 at 01:24
  • 1
    @MikeSchem see https://github.com/mitmproxy/mitmproxy/blob/v5.3.0/examples/addons/options-simple.py#L6 – Iceberg Jan 15 '21 at 07:28
  • 1
    @Sully, thanks but that's actually still running from a script. I'm trying to run in inside a python script. I just passed my variables to the __init__ and set them to a object level var and it worked. Thanks though! – MikeSchem Jan 15 '21 at 17:19
  • Hi @Iceberg, I want to be able to interrupt or restart mitmproxy in the thread. I used m.shutdown() to interrupt mitmproxy, and then I got an error when restarting the thread: RuntimeError: Event loop is closed This means that when I use asyncio.get_event_loop(), I get the same loop, so when I execute shutdown() to close the loop, I can’t start it again. I tried to use asyncio.new_event_loop() to get a new loop, but this seems to conflict with the loop inside mitmproxy. – Alex Sep 28 '21 at 03:01
0
from mitmproxy.tools.main import mitmdump

mitmdump(args=["-s", "myaddon.py"])
Green Lei
  • 3,150
  • 2
  • 20
  • 25