def test_invalid_certificate(self): opts = options.Options() opts.certs = [tutils.test_data.path("mitmproxy/data/dumpfile-011")] with pytest.raises(exceptions.OptionsError, match="Invalid certificate format"): ProxyConfig(opts)
def run(master_cls: typing.Type[master.Master], make_parser: typing.Callable[[options.Options], argparse.ArgumentParser], arguments: typing.Sequence[str], extra: typing.Callable[[typing.Any], dict] = None): # pragma: no cover """ extra: Extra argument processing callable which returns a dict of options. """ debug.register_info_dumpers() opts = options.Options() master = master_cls(opts) parser = make_parser(opts) # To make migration from 2.x to 3.0 bearable. if "-R" in sys.argv and sys.argv[sys.argv.index("-R") + 1].startswith("http"): print( "-R is used for specifying replacements.\n" "To use mitmproxy in reverse mode please use --mode reverse:SPEC instead" ) try: args = parser.parse_args(arguments) except SystemExit: arg_check.check() sys.exit(1) try: unknown = optmanager.load_paths(opts, args.conf) pconf = process_options(parser, opts, args) server = None # type: typing.Any if pconf.options.server: try: server = proxy.server.ProxyServer(pconf) except exceptions.ServerException as v: print(str(v), file=sys.stderr) sys.exit(1) else: server = proxy.server.DummyServer(pconf) master.server = server master.addons.trigger("configure", opts.keys()) master.addons.trigger("tick") remaining = opts.update_known(**unknown) if remaining and log.log_tier(opts.verbosity) > 1: print("Ignored options: %s" % remaining) if args.options: print(optmanager.dump_defaults(opts)) sys.exit(0) if args.commands: master.commands.dump() sys.exit(0) opts.set(*args.setoptions) if extra: opts.update(**extra(args)) def cleankill(*args, **kwargs): master.shutdown() signal.signal(signal.SIGTERM, cleankill) master.run() except exceptions.OptionsError as e: print("%s: %s" % (sys.argv[0], e), file=sys.stderr) sys.exit(1) except (KeyboardInterrupt, RuntimeError) as e: pass return master
def test_err(self): conf = ProxyConfig( options.Options(listen_port=1), ) tutils.raises("error starting proxy server", ProxyServer, conf)
def test_serialize_defaults(): o = options.Options() assert optmanager.serialize(o, None, defaults=True)
class MyMaster(master.Master): def run(self): try: master.Master.run(self) except KeyboardInterrupt: self.shutdown() @controller.handler def request(self, f): print("request", f) @controller.handler def response(self, f): print("response", f) @controller.handler def error(self, f): print("error", f) @controller.handler def log(self, l): print("log", l.msg) opts = options.Options(cadir="~/.mitmproxy/") config = ProxyConfig(opts) server = ProxyServer(config) m = MyMaster(opts, server) m.run()
def mkmaster(self, **opts): o = options.Options(**opts) m = console.master.ConsoleMaster(o) m.addons.trigger("configure", o.keys()) return m
def test_dump_dicts(): o = options.Options() assert optmanager.dump_dicts(o) assert optmanager.dump_dicts(o, ['http2', 'listen_port'])
def test_shorten_message(message, ready_message): o = options.Options() m = master.ConsoleMaster(o) ab = statusbar.ActionBar(m) assert ab.shorten_message(message, max_width=30) == ready_message
def test_shorten_message_narrow(): o = options.Options() m = master.ConsoleMaster(o) ab = statusbar.ActionBar(m) shorten_msg = ab.shorten_message("error", max_width=4) assert shorten_msg == [(None, "\u2026"), ("warn", "(more in eventlog)")]
def test_options(): assert options.Options(replay_kill_extra=True)
def mkmaster(self, **opts): if "verbosity" not in opts: opts["verbosity"] = 1 o = options.Options(**opts) return console.master.ConsoleMaster(o, proxy.DummyServer())
def test_configure(self): sh = setheaders.SetHeaders() o = options.Options(setheaders=[("~b", "one", "two")]) tutils.raises("invalid setheader filter pattern", sh.configure, o, o.keys())
def test_dump(): o = options.Options() assert optmanager.dump(o)
def test_invalid_cadir(self): opts = options.Options() opts.cadir = "foo" with pytest.raises(exceptions.OptionsError, match="parent directory does not exist"): ProxyConfig(opts)
def test_secure_by_default(self): """ Certificate verification should be turned on by default. """ default_opts = options.Options() assert not default_opts.ssl_insecure
def test_configure(self): cp = clientplayback.ClientPlayback() cp.configure(options.Options(), [])
def run( master_cls: typing.Type[master.Master], make_parser: typing.Callable[[options.Options], argparse.ArgumentParser], arguments: typing.Sequence[str], extra: typing.Callable[[typing.Any], dict] = None ) -> master.Master: # pragma: no cover """ extra: Extra argument processing callable which returns a dict of options. """ debug.register_info_dumpers() opts = options.Options() master = master_cls(opts) parser = make_parser(opts) # To make migration from 2.x to 3.0 bearable. if "-R" in sys.argv and sys.argv[sys.argv.index("-R") + 1].startswith("http"): print( "To use mitmproxy in reverse mode please use --mode reverse:SPEC instead" ) try: args = parser.parse_args(arguments) except SystemExit: arg_check.check() sys.exit(1) try: opts.set(*args.setoptions, defer=True) optmanager.load_paths( opts, os.path.join(opts.confdir, "config.yaml"), os.path.join(opts.confdir, "config.yml"), ) process_options(parser, opts, args) if args.options: optmanager.dump_defaults(opts, sys.stdout) sys.exit(0) if args.commands: master.commands.dump() sys.exit(0) if extra: if args.filter_args: master.log.info( f"Only processing flows that match \"{' & '.join(args.filter_args)}\"" ) opts.update(**extra(args)) loop = asyncio.get_event_loop() try: loop.add_signal_handler( signal.SIGINT, getattr(master, "prompt_for_exit", master.shutdown)) loop.add_signal_handler(signal.SIGTERM, master.shutdown) except NotImplementedError: # Not supported on Windows pass # Make sure that we catch KeyboardInterrupts on Windows. # https://stackoverflow.com/a/36925722/934719 if os.name == "nt": async def wakeup(): while True: await asyncio.sleep(0.2) asyncio.ensure_future(wakeup()) master.run() except exceptions.OptionsError as e: print("{}: {}".format(sys.argv[0], e), file=sys.stderr) sys.exit(1) except (KeyboardInterrupt, RuntimeError): pass return master
def test_serialize_defaults(): o = options.Options() assert o.serialize(None, defaults=True)
def test_serialize_defaults(): o = options.Options() buf = io.StringIO() optmanager.serialize(o, buf, "", defaults=True) assert buf.getvalue()
def get_options(cls): opts = options.Options(listen_port=0, upstream_cert=True, ssl_insecure=True) opts.confdir = os.path.join(tempfile.gettempdir(), "mitmproxy") return opts
self.hook_handlers = hooks async def handle_hook(self, hook: commands.StartHook) -> None: if hook.name in self.hook_handlers: self.hook_handlers[hook.name](*hook.args()) def log(self, message: str, level: str = "info"): if "Hook" not in message: pass # print(message, file=sys.stderr if level in ("error", "warn") else sys.stdout) if __name__ == "__main__": # pragma: no cover # simple standalone implementation for testing. loop = asyncio.get_event_loop() opts = moptions.Options() # options duplicated here to simplify testing setup opts.add_option("connection_strategy", str, "lazy", "Determine when server connections should be established.", choices=("eager", "lazy")) opts.add_option( "keep_host_header", bool, False, """ Reverse Proxy: Keep the original host header instead of rewriting it to the reverse proxy target. """) opts.mode = "reverse:http://127.0.0.1:3000/" async def handle(reader, writer): layer_stack = [
from hypothesis import given from hypothesis.strategies import binary from mitmproxy import options from mitmproxy.connection import Client from mitmproxy.proxy.context import Context from mitmproxy.proxy.events import DataReceived from mitmproxy.proxy.layers.modes import Socks5Proxy opts = options.Options() tctx = Context(Client(("client", 1234), ("127.0.0.1", 8080), 1605699329), opts) @given(binary()) def test_socks5_fuzz(data): layer = Socks5Proxy(tctx) list(layer.handle_event(DataReceived(tctx.client, data)))
def test_dump_defaults(): o = options.Options() assert optmanager.dump_defaults(o)
def mockctx(): state = flow.State() o = options.Options(refresh_server_playback=True, keepserving=False) m = RecordingMaster(o, proxy.DummyServer(o), state) with m.handlecontext(): yield
def test_load(): v = view.View() with taddons.context(options=options.Options()) as tctx: tctx.master.addons.add(v)
def test_err(self): # binding to 0.0.0.0:1 works without special permissions on Windows and macOS Mojave+ conf = ProxyConfig(options.Options(listen_port=1)) with pytest.raises(Exception, match="Error starting proxy server"): ProxyServer(conf)
def run( master_cls: typing.Type[master.Master], make_parser: typing.Callable[[options.Options], argparse.ArgumentParser], arguments: typing.Sequence[str], extra: typing.Callable[[typing.Any], dict] = None ) -> master.Master: # pragma: no cover """ extra: Extra argument processing callable which returns a dict of options. """ debug.register_info_dumpers() opts = options.Options() master = master_cls(opts) parser = make_parser(opts) # To make migration from 2.x to 3.0 bearable. if "-R" in sys.argv and sys.argv[sys.argv.index("-R") + 1].startswith("http"): print("-R is used for specifying replacements.\n" "To use mitmproxy in reverse mode please use --mode reverse:SPEC instead") try: args = parser.parse_args(arguments) except SystemExit: arg_check.check() sys.exit(1) try: opts.confdir = args.confdir optmanager.load_paths( opts, os.path.join(opts.confdir, OPTIONS_FILE_NAME), ) pconf = process_options(parser, opts, args) server: typing.Any = None if pconf.options.server: try: server = proxy.server.ProxyServer(pconf) except exceptions.ServerException as v: print(str(v), file=sys.stderr) sys.exit(1) else: server = proxy.server.DummyServer(pconf) master.server = server if args.options: print(optmanager.dump_defaults(opts)) sys.exit(0) if args.commands: master.commands.dump() sys.exit(0) opts.set(*args.setoptions, defer=True) if extra: opts.update(**extra(args)) ''' Comments: 此处注释原因是,mitmproxy signal handler 和 Lyrebird 的信号冲突 ''' # loop = asyncio.get_event_loop() # for signame in ('SIGINT', 'SIGTERM'): # try: # loop.add_signal_handler(getattr(signal, signame), master.shutdown) # except NotImplementedError: # # Not supported on Windows # pass # Make sure that we catch KeyboardInterrupts on Windows. # https://stackoverflow.com/a/36925722/934719 if os.name == "nt": async def wakeup(): while True: await asyncio.sleep(0.2) asyncio.ensure_future(wakeup()) master.run() except exceptions.OptionsError as e: print("%s: %s" % (sys.argv[0], e), file=sys.stderr) sys.exit(1) except (KeyboardInterrupt, RuntimeError) as e: pass return master
def test_err_2(self): conf = ProxyConfig(options.Options(listen_host="256.256.256.256")) with pytest.raises(Exception, match="Error starting proxy server"): ProxyServer(conf)
def test_err_2(self): conf = ProxyConfig( options.Options(listen_host="invalidhost"), ) tutils.raises("error starting proxy server", ProxyServer, conf)
def test_simple(): sio = io.StringIO() d = dumper.Dumper(sio) with taddons.context(options=options.Options()) as ctx: ctx.configure(d, flow_detail=0) d.response(tflow.tflow(resp=True)) assert not sio.getvalue() sio.truncate(0) ctx.configure(d, flow_detail=1) d.response(tflow.tflow(resp=True)) assert sio.getvalue() sio.truncate(0) ctx.configure(d, flow_detail=1) d.error(tflow.tflow(err=True)) assert sio.getvalue() sio.truncate(0) ctx.configure(d, flow_detail=4) d.response(tflow.tflow(resp=True)) assert sio.getvalue() sio.truncate(0) ctx.configure(d, flow_detail=4) d.response(tflow.tflow(resp=True)) assert "<<" in sio.getvalue() sio.truncate(0) ctx.configure(d, flow_detail=4) d.response(tflow.tflow(err=True)) assert "<<" in sio.getvalue() sio.truncate(0) ctx.configure(d, flow_detail=4) flow = tflow.tflow() flow.request = tutils.treq() flow.request.stickycookie = True flow.client_conn = mock.MagicMock() flow.client_conn.address[0] = "foo" flow.response = tutils.tresp(content=None) flow.response.is_replay = True flow.response.status_code = 300 d.response(flow) assert sio.getvalue() sio.truncate(0) ctx.configure(d, flow_detail=4) flow = tflow.tflow(resp=tutils.tresp(content=b"{")) flow.response.headers["content-type"] = "application/json" flow.response.status_code = 400 d.response(flow) assert sio.getvalue() sio.truncate(0) ctx.configure(d, flow_detail=4) flow = tflow.tflow() flow.request.content = None flow.response = http.HTTPResponse.wrap(tutils.tresp()) flow.response.content = None d.response(flow) assert "content missing" in sio.getvalue() sio.truncate(0)