diff --git a/.coveragerc b/.coveragerc index 09170dc..9243873 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,5 +1,6 @@ [run] omit = +concurrency = multiprocessing [report] exclude_lines = pragma: no cover diff --git a/hippolyzer/apps/proxy.py b/hippolyzer/apps/proxy.py index 260322e..8048cdc 100644 --- a/hippolyzer/apps/proxy.py +++ b/hippolyzer/apps/proxy.py @@ -89,6 +89,7 @@ def run_http_proxy_process(proxy_host, http_proxy_port, flow_context: HTTPFlowCo mitmproxy_master = create_http_proxy(proxy_host, http_proxy_port, flow_context) mitmproxy_master.start_server() gc.freeze() + flow_context.mitmproxy_ready.set() mitm_loop.run_forever() diff --git a/hippolyzer/lib/proxy/http_proxy.py b/hippolyzer/lib/proxy/http_proxy.py index a58f488..78aadd0 100644 --- a/hippolyzer/lib/proxy/http_proxy.py +++ b/hippolyzer/lib/proxy/http_proxy.py @@ -82,6 +82,7 @@ class HTTPFlowContext: self.from_proxy_queue = multiprocessing.Queue() self.to_proxy_queue = multiprocessing.Queue() self.shutdown_signal = multiprocessing.Event() + self.mitmproxy_ready = multiprocessing.Event() class IPCInterceptionAddon: diff --git a/tests/proxy/integration/test_http.py b/tests/proxy/integration/test_http.py index 77fe1a9..4774a3d 100644 --- a/tests/proxy/integration/test_http.py +++ b/tests/proxy/integration/test_http.py @@ -2,6 +2,7 @@ from __future__ import annotations import asyncio import math +import multiprocessing import aioresponses from mitmproxy.net import http @@ -9,6 +10,7 @@ from mitmproxy.test import tflow, tutils from mitmproxy.http import HTTPFlow from yarl import URL +from hippolyzer.apps.proxy import run_http_proxy_process from hippolyzer.lib.base.datatypes import Vector3 from hippolyzer.lib.proxy.addon_utils import BaseAddon from hippolyzer.lib.proxy.addons import AddonManager @@ -105,7 +107,6 @@ class TestCapsClient(BaseProxyTest): def setUp(self) -> None: super().setUp() self._setup_default_circuit() - self.caps = {} self.caps_client = self.session.main_region.caps_client async def test_requests_proxied_by_default(self): @@ -117,3 +118,37 @@ class TestCapsClient(BaseProxyTest): # Request should have been proxied, with a header marking it self.assertEqual(kwargs['headers']["X-Hippo-Injected"], "1") self.assertEqual(kwargs['proxy'], "http://127.0.0.1:9062") + + +class TestMITMProxy(BaseProxyTest): + def setUp(self) -> None: + super().setUp() + self._setup_default_circuit() + self.caps_client = self.session.main_region.caps_client + + def test_mitmproxy_works(self): + proxy_port = 9905 + self.session_manager.settings.HTTP_PROXY_PORT = proxy_port + + http_proc = multiprocessing.Process( + target=run_http_proxy_process, + args=("127.0.0.1", proxy_port, self.session_manager.flow_context), + daemon=True, + ) + http_proc.start() + + self.session_manager.flow_context.mitmproxy_ready.wait(1.0) + + http_event_manager = MITMProxyEventManager(self.session_manager, self.session_manager.flow_context) + + async def _request_example_com(): + # Pump callbacks from mitmproxy + asyncio.create_task(http_event_manager.run()) + try: + async with self.caps_client.get("http://example.com/", timeout=0.3) as resp: + self.assertIn(b"Example Domain", await resp.read()) + finally: + # Tell the event pump and mitmproxy they need to shut down + self.session_manager.flow_context.shutdown_signal.set() + asyncio.run(_request_example_com()) + http_proc.join()