inject -> inject.tcp/inject.websocket
This commit is contained in:
parent
b767b82c86
commit
fe6f0d368b
|
@ -14,15 +14,16 @@ def websocket_message(flow):
|
||||||
last_message = flow.websocket.messages[-1]
|
last_message = flow.websocket.messages[-1]
|
||||||
if b"secret" in last_message.content:
|
if b"secret" in last_message.content:
|
||||||
last_message.kill()
|
last_message.kill()
|
||||||
ctx.master.commands.call("inject", [flow], not last_message.from_client, "ssssssh")
|
ctx.master.commands.call("inject.websocket", flow, last_message.from_client, "ssssssh")
|
||||||
|
|
||||||
|
|
||||||
# Complex example: Schedule a periodic timer
|
# Complex example: Schedule a periodic timer
|
||||||
|
|
||||||
async def inject_async(flow: http.HTTPFlow):
|
async def inject_async(flow: http.HTTPFlow):
|
||||||
msg = "hello from mitmproxy! "
|
msg = "hello from mitmproxy! "
|
||||||
|
assert flow.websocket # make type checker happy
|
||||||
while flow.websocket.timestamp_end is None:
|
while flow.websocket.timestamp_end is None:
|
||||||
ctx.master.commands.call("inject", [flow], False, msg)
|
ctx.master.commands.call("inject.websocket", flow, True, msg)
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
msg = msg[1:] + msg[:1]
|
msg = msg[1:] + msg[:1]
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import warnings
|
import warnings
|
||||||
from typing import Dict, Optional, Sequence, Tuple
|
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
|
from mitmproxy.flow import Error, Flow
|
||||||
from mitmproxy.proxy import commands, events
|
from mitmproxy.proxy import commands, events
|
||||||
from mitmproxy.proxy import server
|
from mitmproxy.proxy import server
|
||||||
from mitmproxy.proxy.layers.tcp import TcpMessageInjected
|
from mitmproxy.proxy.layers.tcp import TcpMessageInjected
|
||||||
|
@ -147,30 +147,36 @@ class Proxyserver:
|
||||||
finally:
|
finally:
|
||||||
del self._connections[peername]
|
del self._connections[peername]
|
||||||
|
|
||||||
def inject_event(self, flow: flow.Flow, event: events.Event):
|
def inject_event(self, event: events.MessageInjected):
|
||||||
if flow.client_conn.peername not in self._connections:
|
if event.flow.client_conn.peername not in self._connections:
|
||||||
raise ValueError("Flow is not from a live connection.")
|
raise ValueError("Flow is not from a live connection.")
|
||||||
self._connections[flow.client_conn.peername].server_event(event)
|
self._connections[event.flow.client_conn.peername].server_event(event)
|
||||||
|
|
||||||
|
@command.command("inject.websocket")
|
||||||
|
def inject_websocket(self, flow: Flow, to_client: bool, message: str, is_text: bool = True):
|
||||||
|
if not isinstance(flow, http.HTTPFlow) or not flow.websocket:
|
||||||
|
ctx.log.warn("Cannot inject WebSocket messages into non-WebSocket flows.")
|
||||||
|
|
||||||
@command.command("inject")
|
|
||||||
def inject(self, flows: Sequence[flow.Flow], from_client: bool, message: str):
|
|
||||||
message_bytes = strutils.escaped_str_to_bytes(message)
|
message_bytes = strutils.escaped_str_to_bytes(message)
|
||||||
event: events.MessageInjected
|
msg = websocket.WebSocketMessage(
|
||||||
for f in flows:
|
Opcode.TEXT if is_text else Opcode.BINARY,
|
||||||
if isinstance(f, http.HTTPFlow):
|
not to_client,
|
||||||
if f.websocket:
|
message_bytes
|
||||||
msg = websocket.WebSocketMessage(Opcode.TEXT, from_client, message_bytes)
|
)
|
||||||
event = WebSocketMessageInjected(f, msg)
|
event = WebSocketMessageInjected(flow, msg)
|
||||||
else:
|
try:
|
||||||
ctx.log.warn("Cannot inject messages into HTTP connections.")
|
self.inject_event(event)
|
||||||
continue
|
except ValueError as e:
|
||||||
elif isinstance(f, tcp.TCPFlow):
|
ctx.log.warn(str(e))
|
||||||
event = TcpMessageInjected(f, tcp.TCPMessage(from_client, message_bytes))
|
|
||||||
else: # pragma: no cover
|
|
||||||
ctx.log.warn(f"Cannot inject message into {f.__class__.__name__}, skipping.")
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
@command.command("inject.tcp")
|
||||||
self.inject_event(f, event)
|
def inject_tcp(self, flow: Flow, to_client: bool, message: str):
|
||||||
except ValueError as e:
|
if not isinstance(flow, tcp.TCPFlow):
|
||||||
ctx.log.warn(str(e))
|
ctx.log.warn("Cannot inject TCP messages into non-TCP flows.")
|
||||||
|
|
||||||
|
message_bytes = strutils.escaped_str_to_bytes(message)
|
||||||
|
event = TcpMessageInjected(flow, tcp.TCPMessage(not to_client, message_bytes))
|
||||||
|
try:
|
||||||
|
self.inject_event(event)
|
||||||
|
except ValueError as e:
|
||||||
|
ctx.log.warn(str(e))
|
||||||
|
|
|
@ -110,9 +110,9 @@ async def test_inject():
|
||||||
|
|
||||||
writer.write(b"a")
|
writer.write(b"a")
|
||||||
assert await reader.read(1) == b"A"
|
assert await reader.read(1) == b"A"
|
||||||
ps.inject(state.flows, True, "b")
|
ps.inject_tcp(state.flows[0], False, "b")
|
||||||
assert await reader.read(1) == b"B"
|
assert await reader.read(1) == b"B"
|
||||||
ps.inject(state.flows, False, "c")
|
ps.inject_tcp(state.flows[0], True, "c")
|
||||||
assert await reader.read(1) == b"c"
|
assert await reader.read(1) == b"c"
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,16 +120,28 @@ async def test_inject():
|
||||||
async def test_inject_fail():
|
async def test_inject_fail():
|
||||||
ps = Proxyserver()
|
ps = Proxyserver()
|
||||||
with taddons.context(ps) as tctx:
|
with taddons.context(ps) as tctx:
|
||||||
ps.inject(
|
ps.inject_websocket(
|
||||||
[tflow.tflow()],
|
tflow.tflow(),
|
||||||
False,
|
True,
|
||||||
"test"
|
"test"
|
||||||
)
|
)
|
||||||
await tctx.master.await_log("Cannot inject messages into HTTP connections.", level="warn")
|
await tctx.master.await_log("Cannot inject WebSocket messages into non-WebSocket flows.", level="warn")
|
||||||
|
ps.inject_tcp(
|
||||||
|
tflow.tflow(),
|
||||||
|
True,
|
||||||
|
"test"
|
||||||
|
)
|
||||||
|
await tctx.master.await_log("Cannot inject TCP messages into non-TCP flows.", level="warn")
|
||||||
|
|
||||||
ps.inject(
|
ps.inject_websocket(
|
||||||
[tflow.twebsocketflow()],
|
tflow.twebsocketflow(),
|
||||||
False,
|
True,
|
||||||
|
"test"
|
||||||
|
)
|
||||||
|
await tctx.master.await_log("Flow is not from a live connection.", level="warn")
|
||||||
|
ps.inject_websocket(
|
||||||
|
tflow.ttcpflow(),
|
||||||
|
True,
|
||||||
"test"
|
"test"
|
||||||
)
|
)
|
||||||
await tctx.master.await_log("Flow is not from a live connection.", level="warn")
|
await tctx.master.await_log("Flow is not from a live connection.", level="warn")
|
||||||
|
|
Loading…
Reference in New Issue