Files
diegosouzapw--omniroute/tests/unit/tproxy-transparent-socket.test.ts
2026-07-13 13:39:12 +08:00

141 lines
5.0 KiB
TypeScript

/**
* Fase 3 / Epic A — TPROXY IP_TRANSPARENT socket wrapper.
*
* Node's net module can't setsockopt(IP_TRANSPARENT), so the TPROXY listener
* needs a tiny native addon (src/mitm/tproxy/native/transparent.c). Viability
* was proven on the VPS: the prebuilt .node loaded under a different Node
* version (N-API ABI-stable) and, as root, created the transparent socket which
* Node adopted via server.listen({fd}). This wrapper loads that prebuilt addon
* CONDITIONALLY — TPROXY mode is gated on its availability so a JS-only install
* (no toolchain, or non-Linux) keeps working. These tests pin the graceful
* fallback and the load logic (injected require/platform — deterministic).
*/
import test from "node:test";
import assert from "node:assert/strict";
const {
loadTransparentAddon,
isTransparentSocketAvailable,
createTransparentListenerFd,
setSocketMark,
} = await import("../../src/mitm/tproxy/transparentSocket.ts");
test("loadTransparentAddon returns null on non-Linux (IP_TRANSPARENT is Linux-only)", () => {
const addon = loadTransparentAddon(
() => ({ createTransparentListener: () => 3 }),
() => "darwin"
);
assert.equal(addon, null);
});
test("loadTransparentAddon returns null when the prebuilt addon is absent (require throws)", () => {
const addon = loadTransparentAddon(
() => {
throw new Error("Cannot find module");
},
() => "linux"
);
assert.equal(addon, null);
});
test("loadTransparentAddon returns the addon when present and well-shaped", () => {
const fake = {
createTransparentListener: () => 42,
setSocketMark: () => {},
connectMarked: () => 7,
};
const addon = loadTransparentAddon(
() => fake,
() => "linux"
);
assert.equal(addon, fake);
assert.equal(addon?.createTransparentListener("0.0.0.0", 1), 42);
});
test("loadTransparentAddon rejects a module missing createTransparentListener", () => {
const addon = loadTransparentAddon(
() => ({ setSocketMark: () => {}, connectMarked: () => 7 }),
() => "linux"
);
assert.equal(addon, null);
});
test("loadTransparentAddon rejects a module missing setSocketMark (anti-loop primitive)", () => {
const addon = loadTransparentAddon(
() => ({ createTransparentListener: () => 1, connectMarked: () => 7 }),
() => "linux"
);
assert.equal(addon, null);
});
test("loadTransparentAddon rejects a module missing connectMarked (forward anti-loop)", () => {
const addon = loadTransparentAddon(
() => ({ createTransparentListener: () => 1, setSocketMark: () => {} }),
() => "linux"
);
assert.equal(addon, null);
});
test("loadTransparentAddon also tries the cwd-relative standalone path", () => {
// In the standalone/Docker bundle this module is compiled into .next/server/...
// so the module-relative `./native/...` misses; the addon is copied to
// <cwd>/src/mitm/tproxy/native/... and the loader must try that absolute path.
const tried: string[] = [];
const addon = loadTransparentAddon(
(p) => {
tried.push(p);
throw new Error("not here");
},
() => "linux",
() => "/app"
);
assert.equal(addon, null);
assert.ok(
tried.some((p) => p === "/app/src/mitm/tproxy/native/build/Release/transparent.node"),
`expected a cwd-absolute candidate, got: ${tried.join(", ")}`
);
});
test("loadTransparentAddon loads the addon from the cwd-relative standalone path", () => {
const fake = {
createTransparentListener: () => 1,
setSocketMark: () => {},
connectMarked: () => 2,
};
const addon = loadTransparentAddon(
(p) => {
if (p.startsWith("/app/")) return fake; // standalone dest; module-relative misses
throw new Error("not here");
},
() => "linux",
() => "/app"
);
assert.equal(addon, fake);
});
// The native addon is built CONDITIONALLY (prebuilds — #4236), so its presence is
// environment-dependent: absent on a JS-only install, present on runners where the
// prebuilt .node loads (e.g. the Node-compat CI jobs). These tests must hold in both
// states: when absent, the helpers throw the actionable "not available" guard; when
// present, the call reaches the OS and throws a runtime error (no CAP_NET_ADMIN /
// TPROXY privileges in CI) — still throwing, just not the guard message.
test("isTransparentSocketAvailable returns a boolean (addon presence is environment-dependent)", () => {
assert.equal(typeof isTransparentSocketAvailable(), "boolean");
});
test("createTransparentListenerFd throws when unavailable (guard) or when present without privileges (OS error)", () => {
if (isTransparentSocketAvailable()) {
assert.throws(() => createTransparentListenerFd("0.0.0.0", 8443));
} else {
assert.throws(() => createTransparentListenerFd("0.0.0.0", 8443), /not available|Linux|build/i);
}
});
test("setSocketMark throws when unavailable (guard) or when present without privileges (OS error)", () => {
if (isTransparentSocketAvailable()) {
assert.throws(() => setSocketMark(7, 0x539));
} else {
assert.throws(() => setSocketMark(7, 0x539), /not available/i);
}
});