Add direct gateway forwarding when VPN is off
This commit is contained in:
@@ -15,6 +15,7 @@ export const settings = {
|
||||
port: parsePort(process.env.PORT, 3456),
|
||||
proxyPort,
|
||||
tproxyPort: parsePort(process.env.TPROXY_PORT, 7895),
|
||||
tproxyChain: process.env.TPROXY_CHAIN || "VPN_PROXY_TPROXY",
|
||||
bindIp: process.env.PROXY_BIND_IP || "0.0.0.0",
|
||||
dataDir,
|
||||
distDir: process.env.DIST_DIR || "/app/dist",
|
||||
|
||||
23
src/server/gatewayRouting.js
Normal file
23
src/server/gatewayRouting.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
const options = { encoding: 'utf8' };
|
||||
|
||||
export function setGatewayInterception(enabled, chain, run = spawnSync) {
|
||||
const rule = ['-w', '-t', 'mangle', 'PREROUTING', '-j', chain];
|
||||
const exists = run('iptables', [...rule.slice(0, 3), '-C', ...rule.slice(3)], options).status === 0;
|
||||
|
||||
if (!enabled) {
|
||||
if (exists) run('iptables', [...rule.slice(0, 3), '-D', ...rule.slice(3)], options);
|
||||
return;
|
||||
}
|
||||
if (exists) return;
|
||||
|
||||
const result = run(
|
||||
'iptables',
|
||||
[...rule.slice(0, 3), '-I', 'PREROUTING', '1', '-j', chain],
|
||||
options,
|
||||
);
|
||||
if (result.status !== 0) {
|
||||
throw new Error((result.stderr || 'Не удалось включить Gateway VPN').trim());
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import http from 'node:http';
|
||||
import path from 'node:path';
|
||||
import { spawn, spawnSync } from 'node:child_process';
|
||||
import { settings } from './config.js';
|
||||
import { setGatewayInterception } from './gatewayRouting.js';
|
||||
import { tcpPing } from './ping.js';
|
||||
import { buildSharedProxyInfo } from './sharedProxy.js';
|
||||
import {
|
||||
@@ -90,6 +91,9 @@ function checkSingboxConfig() {
|
||||
|
||||
function stopSingbox() {
|
||||
return new Promise((resolve) => {
|
||||
if (settings.appMode === 'gateway') {
|
||||
setGatewayInterception(false, settings.tproxyChain);
|
||||
}
|
||||
if (!singboxProcess) {
|
||||
singboxStartedAt = null;
|
||||
return resolve();
|
||||
@@ -112,7 +116,12 @@ function stopSingbox() {
|
||||
}
|
||||
|
||||
async function startSingbox() {
|
||||
if (!fs.existsSync(settings.configPath)) return false;
|
||||
if (!fs.existsSync(settings.configPath)) {
|
||||
if (settings.appMode === 'gateway') {
|
||||
setGatewayInterception(false, settings.tproxyChain);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
checkSingboxConfig();
|
||||
await stopSingbox();
|
||||
|
||||
@@ -121,10 +130,23 @@ async function startSingbox() {
|
||||
});
|
||||
singboxProcess = child;
|
||||
singboxStartedAt = new Date().toISOString();
|
||||
try {
|
||||
if (settings.appMode === 'gateway') {
|
||||
setGatewayInterception(true, settings.tproxyChain);
|
||||
}
|
||||
} catch (error) {
|
||||
child.kill('SIGTERM');
|
||||
singboxProcess = null;
|
||||
singboxStartedAt = null;
|
||||
throw error;
|
||||
}
|
||||
child.once('exit', () => {
|
||||
if (singboxProcess === child) {
|
||||
singboxProcess = null;
|
||||
singboxStartedAt = null;
|
||||
if (settings.appMode === 'gateway') {
|
||||
setGatewayInterception(false, settings.tproxyChain);
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user