detect recursive self-connects and stop them (attempt 2)

This commit is contained in:
Maximilian Hils 2021-03-30 09:02:12 +02:00
parent d0e54bc32c
commit 945e4e3ef5
3 changed files with 26 additions and 26 deletions

View File

@ -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 import command, controller, ctx, flow, http, log, master, options, platform, tcp, websocket
from mitmproxy.flow import Error, Flow 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 import server
from mitmproxy.proxy.layers.tcp import TcpMessageInjected from mitmproxy.proxy.layers.tcp import TcpMessageInjected
from mitmproxy.proxy.layers.websocket import WebSocketMessageInjected from mitmproxy.proxy.layers.websocket import WebSocketMessageInjected
@ -180,3 +180,13 @@ class Proxyserver:
self.inject_event(event) self.inject_event(event)
except ValueError as e: except ValueError as e:
ctx.log.warn(str(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."

View File

@ -142,9 +142,9 @@ class ConnectionHandler(metaclass=abc.ABCMeta):
server=command.connection server=command.connection
) )
await self.handle_hook(server_hooks.ServerConnectHook(hook_data)) await self.handle_hook(server_hooks.ServerConnectHook(hook_data))
if command.connection.error: if err := command.connection.error:
self.log(f"server connection to {human.format_address(command.connection.address)} killed before connect.") self.log(f"server connection to {human.format_address(command.connection.address)} killed before connect: {err}")
self.server_event(events.OpenConnectionCompleted(command, "Connection killed.")) self.server_event(events.OpenConnectionCompleted(command, f"Connection killed: {err}"))
return return
async with self.max_conns[command.connection.address]: async with self.max_conns[command.connection.address]:

View File

@ -5,9 +5,10 @@ import pytest
from mitmproxy.addons.proxyserver import Proxyserver from mitmproxy.addons.proxyserver import Proxyserver
from mitmproxy.proxy.layers.http import HTTPMode 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.connection import Address
from mitmproxy.test import taddons, tflow from mitmproxy.test import taddons, tflow
from mitmproxy.test.tflow import tclient_conn, tserver_conn
class HelperAddon: class HelperAddon:
@ -162,26 +163,15 @@ async def test_warn_no_nextlayer():
await ps.shutdown_server() await ps.shutdown_server()
@pytest.mark.asyncio def test_self_connect():
async def test_self_connect(): server = tserver_conn()
client = tclient_conn()
server.address = ("localhost", 8080)
ps = Proxyserver() ps = Proxyserver()
with taddons.context(ps) as tctx: with taddons.context(ps) as tctx:
state = HelperAddon() # not calling .running() here to avoid unnecessary socket
state.layers = [ ps.options = tctx.options
lambda ctx: layers.modes.ReverseProxy(ctx), ps.server_connect(
lambda ctx: layers.HttpLayer(ctx, HTTPMode.transparent), server_hooks.ServerConnectionHookData(server, client)
lambda ctx: layers.modes.ReverseProxy(ctx), )
] assert server.error == "Stopped mitmproxy from recursively connecting to itself."
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"</html>")