58 lines
2.5 KiB
JavaScript
58 lines
2.5 KiB
JavaScript
const util = require('node:util');
|
|
const exec = util.promisify(require('node:child_process').exec);
|
|
const process = require('node:process');
|
|
const parameters = require('../core/parameters.js');
|
|
|
|
// Hostname of BBB server that we're going to break connections to
|
|
|
|
const hostname = new URL(parameters.server).hostname;
|
|
|
|
// Parse a line of output from the 'ss' program into an object
|
|
// with fields local (local IP address and TCP port), remote
|
|
// (remote address and port) and pid (localhost process ID)
|
|
|
|
function parseline(line) {
|
|
const fields = line.split(/\s+/);
|
|
// These two are like '192.168.8.1:59164'
|
|
const local = fields[3].split(/:/);
|
|
const remote = fields[4].split(/:/);
|
|
// This one is like 'users:(("chrome",pid=3346964,fd=118))'
|
|
const process = fields[5];
|
|
const pid = parseInt(process.match(/pid=([0-9]+),/)[1]);
|
|
return { local: { ip: local[0], port: parseInt(local[1]) },
|
|
remote: { ip: remote[0], port: parseInt(remote[1]) },
|
|
pid: pid };
|
|
}
|
|
|
|
// return an array of such structures for the current process
|
|
// and all of its subprocesses that connect to a given host
|
|
|
|
async function getCurrentTCPSessions() {
|
|
// First, get the process IDs of all of our subprocesses, which include the test browser(s).
|
|
// The process IDs will appear in parenthesis after the command names in stdout.
|
|
const { stdout } = await exec("pstree -pn " + process.pid);
|
|
const processIDs = stdout.matchAll(/\(([0-9]+)\)/g);
|
|
|
|
// Next, form a regular expression that matches all of those process IDs in ss's output format.
|
|
//
|
|
// The string matchAll method returned an iterator, which doesn't have a map method,
|
|
// so we convert the iterator to a list, then map it to a expression which matches the pid
|
|
// field in the output of ss, then join all the expressions together to form a regex.
|
|
const foundRE = new RegExp([...processIDs].map(x => 'pid=' + x[1]).join('|'));
|
|
|
|
// Now get all TCP sessions going to the target host
|
|
const { stdout: stdout2 } = await exec("ss -tpnH dst " + hostname);
|
|
|
|
// Extract those TCP sessions attached to our subprocesses, parse and and return them in an array.
|
|
return stdout2.split('\n').filter(x => foundRE.test(x)).map(x => parseline(x));
|
|
}
|
|
|
|
// takes an array of such structures and kills those TCP sessions
|
|
|
|
async function killTCPSessions(sessions) {
|
|
await exec('sudo ss -K dst ' + hostname + ' ' + sessions.map(x => 'sport = ' + x.local.port).join(' or '));
|
|
}
|
|
|
|
exports.getCurrentTCPSessions = getCurrentTCPSessions;
|
|
exports.killTCPSessions = killTCPSessions;
|