2025-05-15 14:35:01 +00:00
|
|
|
import { SmartProxy } from '../ts/proxies/smart-proxy/index.js';
|
2025-05-19 12:04:26 +00:00
|
|
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
2025-05-15 14:35:01 +00:00
|
|
|
import * as child_process from 'child_process';
|
|
|
|
|
import { promisify } from 'util';
|
|
|
|
|
|
2026-03-26 20:45:41 +00:00
|
|
|
import type { IRouteConfig } from '../ts/proxies/smart-proxy/models/route-types.js';
|
|
|
|
|
|
2025-05-15 14:35:01 +00:00
|
|
|
const exec = promisify(child_process.exec);
|
|
|
|
|
|
|
|
|
|
async function checkRootPrivileges(): Promise<boolean> {
|
|
|
|
|
try {
|
|
|
|
|
const { stdout } = await exec('id -u');
|
|
|
|
|
return stdout.trim() === '0';
|
|
|
|
|
} catch (err) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isRoot = await checkRootPrivileges();
|
|
|
|
|
|
|
|
|
|
if (!isRoot) {
|
|
|
|
|
console.log('');
|
|
|
|
|
console.log('========================================');
|
|
|
|
|
console.log('NFTables tests require root privileges');
|
|
|
|
|
console.log('Skipping NFTables integration tests');
|
|
|
|
|
console.log('========================================');
|
|
|
|
|
console.log('');
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-29 14:06:47 +00:00
|
|
|
const testFn = isRoot ? tap.test : tap.skip.test;
|
|
|
|
|
|
|
|
|
|
testFn('NFTables integration tests', async () => {
|
2026-03-26 20:45:41 +00:00
|
|
|
|
2025-05-15 14:35:01 +00:00
|
|
|
console.log('Running NFTables tests with root privileges');
|
2026-03-26 20:45:41 +00:00
|
|
|
|
|
|
|
|
const routes: IRouteConfig[] = [
|
|
|
|
|
{
|
|
|
|
|
match: { ports: 9080 },
|
|
|
|
|
action: {
|
|
|
|
|
type: 'forward',
|
|
|
|
|
forwardingEngine: 'nftables',
|
|
|
|
|
targets: [{ host: 'localhost', port: 8080 }],
|
|
|
|
|
nftables: { protocol: 'tcp' }
|
|
|
|
|
},
|
|
|
|
|
name: 'tcp-forward'
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
match: { ports: 5354 },
|
|
|
|
|
action: {
|
|
|
|
|
type: 'forward',
|
|
|
|
|
forwardingEngine: 'nftables',
|
|
|
|
|
targets: [{ host: 'localhost', port: 5353 }],
|
|
|
|
|
nftables: { protocol: 'udp' }
|
|
|
|
|
},
|
|
|
|
|
name: 'udp-forward'
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
match: { ports: [{ from: 9000, to: 9100 }] },
|
|
|
|
|
action: {
|
|
|
|
|
type: 'forward',
|
|
|
|
|
forwardingEngine: 'nftables',
|
|
|
|
|
targets: [{ host: 'localhost', port: 8080 }],
|
|
|
|
|
nftables: { protocol: 'tcp' }
|
|
|
|
|
},
|
|
|
|
|
name: 'port-range'
|
|
|
|
|
}
|
2025-05-15 14:35:01 +00:00
|
|
|
];
|
2026-03-26 20:45:41 +00:00
|
|
|
|
2025-05-15 14:35:01 +00:00
|
|
|
const smartProxy = new SmartProxy({
|
|
|
|
|
enableDetailedLogging: true,
|
|
|
|
|
routes
|
|
|
|
|
});
|
2026-03-26 20:45:41 +00:00
|
|
|
|
2025-05-15 14:35:01 +00:00
|
|
|
await smartProxy.start();
|
|
|
|
|
console.log('SmartProxy started with NFTables routes');
|
2026-03-26 20:45:41 +00:00
|
|
|
|
2025-05-15 14:35:01 +00:00
|
|
|
const status = await smartProxy.getNfTablesStatus();
|
|
|
|
|
console.log('NFTables status:', JSON.stringify(status, null, 2));
|
2026-03-26 20:45:41 +00:00
|
|
|
|
2025-05-15 14:35:01 +00:00
|
|
|
expect(Object.keys(status).length).toEqual(routes.length);
|
2026-03-26 20:45:41 +00:00
|
|
|
|
2025-05-15 14:35:01 +00:00
|
|
|
for (const routeStatus of Object.values(status)) {
|
|
|
|
|
expect(routeStatus.active).toBeTrue();
|
|
|
|
|
expect(routeStatus.ruleCount.total).toBeGreaterThan(0);
|
|
|
|
|
}
|
2026-03-26 20:45:41 +00:00
|
|
|
|
2025-05-15 14:35:01 +00:00
|
|
|
await smartProxy.stop();
|
|
|
|
|
console.log('SmartProxy stopped');
|
2026-03-26 20:45:41 +00:00
|
|
|
|
2025-05-15 14:35:01 +00:00
|
|
|
const finalStatus = await smartProxy.getNfTablesStatus();
|
|
|
|
|
expect(Object.keys(finalStatus).length).toEqual(0);
|
|
|
|
|
});
|
|
|
|
|
|
2026-03-26 20:45:41 +00:00
|
|
|
export default tap.start();
|