Skip to content

Commit 0f8ec20

Browse files
committed
Add a timeout and improve errors around proxy IP detection
1 parent e2eeff1 commit 0f8ec20

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

src/interceptors/frida/frida-integration.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { CustomError } from '@httptoolkit/util';
33

44
import { getReachableInterfaces } from '../../util/network';
55
import { buildIpTestScript } from './frida-scripts';
6+
import { withTimeout } from '../../util/promise';
67

78
/**
89
* Terminology:
@@ -34,6 +35,15 @@ export const FRIDA_ALTERNATE_PORT = 24072; // Reversed to mildly inconvenience d
3435

3536
export const FRIDA_BINARY_NAME = `adirf-server`; // Reversed to mildly inconvenience detection
3637

38+
class FridaProxyError extends CustomError {
39+
constructor(message: string, options: { cause?: Error } = {}) {
40+
super(message, {
41+
cause: options.cause,
42+
code: 'unreachable-proxy'
43+
});
44+
}
45+
}
46+
3747
export async function testAndSelectProxyAddress(
3848
session: FridaJs.FridaAgentSession,
3949
proxyPort: number,
@@ -47,25 +57,23 @@ export async function testAndSelectProxyAddress(
4757
}
4858

4959
if (ips.length === 0) {
50-
throw new CustomError("Couldn't detect proxy external IP", {
51-
code: 'unreachable-proxy'
52-
});
60+
throw new FridaProxyError("No local IPs detected for proxy connection");
5361
}
5462

5563
const ipTestScript = await buildIpTestScript(ips, proxyPort);
5664

57-
return await new Promise<string>(async (resolve, reject) => {
65+
return await withTimeout(2000, new Promise<string>(async (resolve, reject) => {
5866
try {
5967
session.onMessage((message) => {
6068
if (message.type === 'send') {
6169
if (message.payload.type === 'connected') {
6270
resolve(message.payload.ip as string);
6371
} else if (message.payload.type === 'connection-failed') {
64-
reject(new CustomError(`Could not connect to proxy on port ${proxyPort} at ${
72+
reject(new Error(`Could not connect to proxy on port ${proxyPort} at ${
6573
ips.length > 1
6674
? `any of: ${ips.join(', ')}`
6775
: ips[0]
68-
}`, { code: 'unreachable-proxy' }));
76+
}`));
6977
} else {
7078
reject(new Error(`Unexpected message type: ${message.payload.type}`));
7179
}
@@ -80,5 +88,7 @@ export async function testAndSelectProxyAddress(
8088
} catch (e) {
8189
reject(e);
8290
}
91+
})).catch((e) => {
92+
throw new FridaProxyError("No proxy IPs were reachable from the target", e);
8393
});
8494
}

src/util/promise.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { delay } from '@httptoolkit/util';
1+
import { CustomError, delay } from '@httptoolkit/util';
22

33
export async function waitUntil<T extends unknown>(
44
delayMs: number,
@@ -16,3 +16,20 @@ export async function waitUntil<T extends unknown>(
1616
if (!result) throw new Error(`Wait loop failed`);
1717
else return result as Exclude<T, false>;
1818
}
19+
20+
export class TimeoutError extends CustomError {
21+
constructor() {
22+
super('Timeout', { code: 'timeout' });
23+
}
24+
}
25+
26+
export async function withTimeout<T>(
27+
timeoutMs: number,
28+
promise: Promise<T>
29+
) {
30+
return Promise.race([
31+
promise,
32+
delay(timeoutMs, { unref: true })
33+
.then(() => { throw new TimeoutError(); })
34+
]);
35+
}

0 commit comments

Comments
 (0)