Add native traffic inspection to Harbor Connect and Gateway
This commit is contained in:
@@ -84,6 +84,7 @@ import { createConnectivityDiagnosticsRoute } from './http/routes/connectivityDi
|
||||
import { createGatewayPresenceRoute } from './http/routes/gatewayPresenceRoute.js';
|
||||
import { createSharedProxyRoute } from './http/routes/sharedProxyRoute.js';
|
||||
import { createVersionRoute } from './http/routes/versionRoute.js';
|
||||
import { createLiveTrafficRoute } from './http/routes/liveTrafficRoute.js';
|
||||
import { createSingboxSelectorService } from './services/singboxSelectorService.js';
|
||||
import { createFailoverService } from './features/failover/failoverService.js';
|
||||
import { createFailoverRoute } from './http/routes/failoverRoute.js';
|
||||
@@ -260,6 +261,16 @@ function selectRuntime() {
|
||||
throw new Error('Harbor runtime is not configured');
|
||||
}
|
||||
const singboxRuntime = selectRuntime();
|
||||
const clientLiveTraffic = settings.appMode === 'client'
|
||||
? (await import('./services/liveTrafficService.js')).createLiveTrafficService({
|
||||
port: settings.singboxNativeApiPort,
|
||||
enabled: settings.singboxTrafficSource === 'native',
|
||||
isRuntimeRunning: () => Boolean(localRuntime?.running),
|
||||
})
|
||||
: null;
|
||||
const liveTraffic = clientLiveTraffic || (remoteDataplane ? {
|
||||
snapshot: () => requireRemoteRuntime().observeLiveTraffic(),
|
||||
} : null);
|
||||
|
||||
function requireRemoteRuntime() {
|
||||
if (!remoteRuntime) throw new Error('Harbor dataplane runtime is not configured');
|
||||
@@ -515,6 +526,10 @@ const versionRoute = createVersionRoute({
|
||||
? () => requireRemoteRuntime().refresh()
|
||||
: null,
|
||||
});
|
||||
const liveTrafficRoute = createLiveTrafficRoute({
|
||||
traffic: liveTraffic,
|
||||
deviceInventory: remoteDataplane ? deviceInventory : null,
|
||||
});
|
||||
const subscriptionValidationRoute = createSubscriptionValidationRoute({
|
||||
validateSubscription: createValidateSubscription(fetchSubscription),
|
||||
readBody,
|
||||
@@ -887,6 +902,19 @@ function currentConfigMatchesAppliedTarget(state: StoredState) {
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
if (settings.appMode === 'client' || settings.appMode === 'gateway') {
|
||||
const apiServices = (Array.isArray(config.services) ? config.services : [])
|
||||
.map(record)
|
||||
.filter(({ type }) => type === 'api');
|
||||
const nativeApiMatches = apiServices.length === 1
|
||||
&& apiServices[0].listen === '127.0.0.1'
|
||||
&& apiServices[0].listen_port === settings.singboxNativeApiPort
|
||||
&& apiServices[0].dashboard === false
|
||||
&& !Object.hasOwn(apiServices[0], 'secret');
|
||||
const nativeApiExpected = settings.singboxTrafficSource === 'native'
|
||||
|| settings.singboxTrafficSource === 'shadow';
|
||||
if (nativeApiExpected ? !nativeApiMatches : apiServices.length > 0) return false;
|
||||
}
|
||||
if (state.appliedFailoverPolicy) {
|
||||
const expectedRole = state.appliedProfileId === state.appliedFailoverPolicy.reserve.profileId
|
||||
&& state.appliedServerId === state.appliedFailoverPolicy.reserve.serverId
|
||||
@@ -955,6 +983,8 @@ async function handleApi(req: IncomingMessage, res: ServerResponse) {
|
||||
|
||||
if (await versionRoute.handle(req, res)) return;
|
||||
|
||||
if (await liveTrafficRoute.handle(req, res)) return;
|
||||
|
||||
if (await sharedProxyRoute.handle(req, res)) return;
|
||||
|
||||
if (await deviceInventoryRoute.handle(req, res)) return;
|
||||
@@ -1004,6 +1034,7 @@ async function shutdown() {
|
||||
gatewayAutoService.stopDiscovery();
|
||||
if (deviceDiscoveryTimer) clearInterval(deviceDiscoveryTimer);
|
||||
await gatewayFailover?.shutdown().catch((error) => console.warn(`[control] failover shutdown: ${errorMessage(error)}`));
|
||||
await clientLiveTraffic?.stop().catch((error) => console.warn(`[control] traffic shutdown: ${errorMessage(error)}`));
|
||||
await serializeControl(() => singboxRuntime.shutdown());
|
||||
process.exit(0);
|
||||
}
|
||||
@@ -1073,6 +1104,8 @@ if (deviceInventory) {
|
||||
.catch((error: unknown) => console.warn(`[control] device policy не применена: ${errorMessage(error)}`));
|
||||
}
|
||||
|
||||
clientLiveTraffic?.start();
|
||||
|
||||
server.listen(settings.port, '0.0.0.0', () => {
|
||||
console.log(`[control] ${settings.appMode} UI слушает :${settings.port}`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user