Add UI-controlled TProxy bypass for devices
This commit is contained in:
75
src/server/tproxySourceBypass.js
Normal file
75
src/server/tproxySourceBypass.js
Normal file
@@ -0,0 +1,75 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { settings } from "./config.js";
|
||||
import { deviceCidrs, normalizeCidr } from "./devices.js";
|
||||
|
||||
function splitCidrs(value) {
|
||||
return String(value || "")
|
||||
.split(/[\s,]+/)
|
||||
.map((item) => normalizeCidr(item))
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function unique(list) {
|
||||
return [...new Set(list)];
|
||||
}
|
||||
|
||||
export function sourceBypassCidrs(
|
||||
profiles,
|
||||
envCidrs = process.env.TPROXY_BYPASS_SOURCE_CIDRS || "",
|
||||
) {
|
||||
return unique([
|
||||
...splitCidrs(envCidrs),
|
||||
...deviceCidrs(profiles?.devices || [], "bypass"),
|
||||
]);
|
||||
}
|
||||
|
||||
export function buildSourceBypassIptablesCommands(
|
||||
cidrs,
|
||||
{ chain = settings.tproxySourceBypassChain } = {},
|
||||
) {
|
||||
return [
|
||||
["-w", "-t", "mangle", "-F", chain],
|
||||
...cidrs.map((cidr) => [
|
||||
"-w",
|
||||
"-t",
|
||||
"mangle",
|
||||
"-A",
|
||||
chain,
|
||||
"-s",
|
||||
cidr,
|
||||
"-j",
|
||||
"ACCEPT",
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
export function syncTproxySourceBypass(profiles, options = {}) {
|
||||
if (settings.appMode !== "gateway") {
|
||||
return { success: true, skipped: true, cidrs: [] };
|
||||
}
|
||||
|
||||
const chain = options.chain || settings.tproxySourceBypassChain;
|
||||
const cidrs = sourceBypassCidrs(
|
||||
profiles,
|
||||
options.envCidrs ?? process.env.TPROXY_BYPASS_SOURCE_CIDRS,
|
||||
);
|
||||
const commands = buildSourceBypassIptablesCommands(cidrs, { chain });
|
||||
|
||||
for (const args of commands) {
|
||||
const result = spawnSync("iptables", args, {
|
||||
encoding: "utf8",
|
||||
timeout: 1000,
|
||||
});
|
||||
if (result.error || result.status !== 0) {
|
||||
return {
|
||||
success: false,
|
||||
cidrs,
|
||||
error:
|
||||
result.error?.message ||
|
||||
(result.stderr || result.stdout || "iptables command failed").trim(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { success: true, cidrs };
|
||||
}
|
||||
Reference in New Issue
Block a user