Skip to content

Commit

Permalink
move mitmproxy launching into separate file
Browse files Browse the repository at this point in the history
TODO incorporate
  • Loading branch information
lawrence-forooghian committed Jul 18, 2024
1 parent cce0442 commit ac51627
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 78 deletions.
84 changes: 6 additions & 78 deletions test/interception-proxy/InterceptionContext.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ChildProcessWithoutNullStreams, spawn } from 'child_process';
import {
ClientMethods,
createTransformInterceptedMessageParamsDTO,
Expand All @@ -19,6 +18,7 @@ import { ProxyMessage } from './Proxy';
import { ProxyServer } from './ProxyServer';
import { webSocketMessageDataLoggingDescription } from './WebSocketMessageData';
import { TypedJSONRPCServerAndClient, JSONRPCClient, JSONRPCServer, JSONRPCServerAndClient } from 'json-rpc-2.0';
import { MitmproxyLauncher } from './MitmproxyLauncher';

type ServerParams = {
controlServerConnection: ControlServerConnection;
Expand All @@ -29,7 +29,7 @@ export class InterceptionContext {
proxyServer: ProxyServer | null = null;
private jsonRPC: TypedJSONRPCServerAndClient<ServerMethods, ClientMethods, ServerParams>;
private interceptedMessagesQueue = new InterceptedMessagesQueue();
private onMitmproxyReady: (() => void) | null = null;
private mitmproxyLauncher: MitmproxyLauncher | null = null;

constructor() {
this.jsonRPC = new JSONRPCServerAndClient(
Expand All @@ -42,7 +42,7 @@ export class InterceptionContext {
this.jsonRPC.addMethod('startInterception', (params, serverParams) =>
this.startInterception(params, serverParams.controlServerConnection),
);
this.jsonRPC.addMethod('mitmproxyReady', () => this.onMitmproxyReady?.());
this.jsonRPC.addMethod('mitmproxyReady', () => this.mitmproxyLauncher?.onMitmproxyReady());
}

onControlWebSocketMessage(data: string, controlServerConnection: ControlServerConnection) {
Expand All @@ -52,81 +52,9 @@ export class InterceptionContext {

async startInterception(params: InterceptionModeDTO, controlServerConnection: ControlServerConnection): Promise<{}> {
this.controlServer!.setActiveConnection(controlServerConnection);

console.log('starting mitmdump, mode', params.mode);

let mitmdumpBinary: string;
let mitmdumpMode: string | null;

// TODO this is currently written on the assumption that darwin means running locally and linux means running in GitHub action; sort out so that you can run (locally or on CI) on (macOS or Linux)
switch (process.platform) {
case 'darwin':
mitmdumpBinary = 'mitmdump';
switch (params.mode) {
case 'local':
mitmdumpMode = `local:${params.pid}`;
break;
case 'proxy':
mitmdumpMode = null;
break;
}
break;
case 'linux':
// Currently we expect that you set up the iptables rules externally
mitmdumpBinary = '/opt/pipx_bin/mitmdump';
switch (params.mode) {
case 'local':
mitmdumpMode = 'transparent';
break;
case 'proxy':
mitmdumpMode = null;
break;
}
break;
default:
throw new Error(`Don’t know how to set up mitmdump interception for platform ${process.platform}`);
}

// sounds like we don’t need to explicitly stop this when we stop the current process: https://nodejs.org/api/child_process.html#optionsdetached
const mitmdump = spawn(mitmdumpBinary, [
'--set',
'stream_large_bodies=1',
...(mitmdumpMode === null ? [] : ['--mode', mitmdumpMode]),
'-s',
'test/mitmproxy_addon_2.py',
'--set',
// "full request URL with response status code and HTTP headers" (the default truncates the URL)
'flow_detail=2',
]);

const formatMitmdumpOutput = (source: string, data: Buffer) => {
const text = data.toString('utf-8');
const lines = text.split('\n');
return lines.map((line) => `mitmdump ${source}: ${line}`).join('\n');
};

mitmdump.stdout.on('data', (data) => {
console.log(formatMitmdumpOutput('stdout', data));
});

mitmdump.stderr.on('data', (data) => {
console.log(formatMitmdumpOutput('stderr', data));
});

console.log(`Waiting for mitmdump to start`);

let resolveResult: () => void;
const result = new Promise<{}>((resolve) => {
resolveResult = () => resolve({});
});

this.onMitmproxyReady = () => {
this.onMitmproxyReady = null;
console.log(`mitmdump has started`);
resolveResult();
};

return result;
this.mitmproxyLauncher = new MitmproxyLauncher();
await this.mitmproxyLauncher.launch(params);
return {};
}

private handleTransformInterceptedMessageResponse(
Expand Down
87 changes: 87 additions & 0 deletions test/interception-proxy/MitmproxyLauncher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { spawn } from 'child_process';
import { InterceptionModeDTO } from './ControlRPC';

export class MitmproxyLauncher {
private _onMitmproxyReady: (() => void) | null = null;

async launch(mode: InterceptionModeDTO) {
console.log('starting mitmdump, mode', mode);

let mitmdumpBinary: string;
let mitmdumpMode: string | null;

// TODO this is currently written on the assumption that darwin means running locally and linux means running in GitHub action; sort out so that you can run (locally or on CI) on (macOS or Linux)
switch (process.platform) {
case 'darwin':
mitmdumpBinary = 'mitmdump';
switch (mode.mode) {
case 'local':
mitmdumpMode = `local:${mode.pid}`;
break;
case 'proxy':
mitmdumpMode = null;
break;
}
break;
case 'linux':
// Currently we expect that you set up the iptables rules externally
mitmdumpBinary = '/opt/pipx_bin/mitmdump';
switch (mode.mode) {
case 'local':
mitmdumpMode = 'transparent';
break;
case 'proxy':
mitmdumpMode = null;
break;
}
break;
default:
throw new Error(`Don’t know how to set up mitmdump interception for platform ${process.platform}`);
}

// sounds like we don’t need to explicitly stop this when we stop the current process: https://nodejs.org/api/child_process.html#optionsdetached
const mitmdump = spawn(mitmdumpBinary, [
'--set',
'stream_large_bodies=1',
...(mitmdumpMode === null ? [] : ['--mode', mitmdumpMode]),
'-s',
'test/mitmproxy_addon_2.py',
'--set',
// "full request URL with response status code and HTTP headers" (the default truncates the URL)
'flow_detail=2',
]);

const formatMitmdumpOutput = (source: string, data: Buffer) => {
const text = data.toString('utf-8');
const lines = text.split('\n');
return lines.map((line) => `mitmdump ${source}: ${line}`).join('\n');
};

mitmdump.stdout.on('data', (data) => {
console.log(formatMitmdumpOutput('stdout', data));
});

mitmdump.stderr.on('data', (data) => {
console.log(formatMitmdumpOutput('stderr', data));
});

console.log(`Waiting for mitmdump to start`);

let resolveResult: () => void;
const result = new Promise<{}>((resolve) => {
resolveResult = () => resolve({});
});

this._onMitmproxyReady = () => {
this._onMitmproxyReady = null;
console.log(`mitmdump has started`);
resolveResult();
};

return result;
}

onMitmproxyReady() {
this._onMitmproxyReady?.();
}
}

0 comments on commit ac51627

Please sign in to comment.