diff --git a/mitmproxy/addons/proxyserver.py b/mitmproxy/addons/proxyserver.py index 549d05739..ff7e3426a 100644 --- a/mitmproxy/addons/proxyserver.py +++ b/mitmproxy/addons/proxyserver.py @@ -4,7 +4,7 @@ from typing import Dict, Optional, Tuple from mitmproxy import command, controller, ctx, flow, http, log, master, options, platform, tcp, websocket from mitmproxy.flow import Error, Flow -from mitmproxy.proxy import commands, events +from mitmproxy.proxy import commands, events, server_hooks from mitmproxy.proxy import server from mitmproxy.proxy.layers.tcp import TcpMessageInjected from mitmproxy.proxy.layers.websocket import WebSocketMessageInjected @@ -180,3 +180,13 @@ class Proxyserver: self.inject_event(event) except ValueError as e: ctx.log.warn(str(e)) + + def server_connect(self, ctx: server_hooks.ServerConnectionHookData): + assert ctx.server.address + self_connect = ( + ctx.server.address[1] == self.options.listen_port + and + ctx.server.address[0] in ("localhost", "127.0.0.1", "::1", self.options.listen_host) + ) + if self_connect: + ctx.server.error = "Stopped mitmproxy from recursively connecting to itself." diff --git a/mitmproxy/proxy/server.py b/mitmproxy/proxy/server.py index a57071274..865340dba 100644 --- a/mitmproxy/proxy/server.py +++ b/mitmproxy/proxy/server.py @@ -142,9 +142,9 @@ class ConnectionHandler(metaclass=abc.ABCMeta): server=command.connection ) await self.handle_hook(server_hooks.ServerConnectHook(hook_data)) - if command.connection.error: - self.log(f"server connection to {human.format_address(command.connection.address)} killed before connect.") - self.server_event(events.OpenConnectionCompleted(command, "Connection killed.")) + if err := command.connection.error: + self.log(f"server connection to {human.format_address(command.connection.address)} killed before connect: {err}") + self.server_event(events.OpenConnectionCompleted(command, f"Connection killed: {err}")) return async with self.max_conns[command.connection.address]: diff --git a/test/mitmproxy/addons/test_proxyserver.py b/test/mitmproxy/addons/test_proxyserver.py index ada0f787e..6fcf9cac3 100644 --- a/test/mitmproxy/addons/test_proxyserver.py +++ b/test/mitmproxy/addons/test_proxyserver.py @@ -5,9 +5,10 @@ import pytest from mitmproxy.addons.proxyserver import Proxyserver from mitmproxy.proxy.layers.http import HTTPMode -from mitmproxy.proxy import layers +from mitmproxy.proxy import layers, server_hooks from mitmproxy.connection import Address from mitmproxy.test import taddons, tflow +from mitmproxy.test.tflow import tclient_conn, tserver_conn class HelperAddon: @@ -162,26 +163,15 @@ async def test_warn_no_nextlayer(): await ps.shutdown_server() -@pytest.mark.asyncio -async def test_self_connect(): +def test_self_connect(): + server = tserver_conn() + client = tclient_conn() + server.address = ("localhost", 8080) ps = Proxyserver() with taddons.context(ps) as tctx: - state = HelperAddon() - state.layers = [ - lambda ctx: layers.modes.ReverseProxy(ctx), - lambda ctx: layers.HttpLayer(ctx, HTTPMode.transparent), - lambda ctx: layers.modes.ReverseProxy(ctx), - ] - tctx.master.addons.add(state) - - tctx.configure(ps, listen_host="127.0.0.1", listen_port=0) - ps.running() - await tctx.master.await_log("Proxy server listening", level="info") - assert ps.server - proxy_addr = ps.server.sockets[0].getsockname()[:2] - - tctx.options.mode = f"reverse:{':'.join(str(x) for x in proxy_addr)}" - reader, writer = await asyncio.open_connection(*proxy_addr) - writer.write(b"GET / HTTP/1.1\r\n\r\n") - assert b"502 Bad Gateway" in await reader.readuntil(b"\r\n\r\n") - assert b"Stopped mitmproxy from recursively connecting" in await reader.readuntil(b"") + # not calling .running() here to avoid unnecessary socket + ps.options = tctx.options + ps.server_connect( + server_hooks.ServerConnectionHookData(server, client) + ) + assert server.error == "Stopped mitmproxy from recursively connecting to itself."