Files
web-check/api/ports.js
Alicia Sykes 01d0cf1a0d chore: Format
2026-05-07 16:22:22 +01:00

100 lines
2.6 KiB
JavaScript

import net from 'net';
import middleware from './_common/middleware.js';
import { parseTarget } from './_common/parse-target.js';
// A list of commonly used ports.
const DEFAULT_PORTS_TO_CHECK = [
20, 21, 22, 23, 25, 53, 80, 67, 68, 69, 110, 119, 123, 143, 156, 161, 162, 179, 194, 389, 443,
587, 993, 995, 3000, 3306, 3389, 5060, 5900, 8000, 8080, 8888,
];
/*
* Checks if the env PORTS_TO_CHECK is set, if so the string is split via "," to get an array of ports to check.
* If the env is not set, return the default commonly used ports.
*/
const PORTS = process.env.PORTS_TO_CHECK
? process.env.PORTS_TO_CHECK.split(',')
: DEFAULT_PORTS_TO_CHECK;
async function checkPort(port, domain) {
return new Promise((resolve, reject) => {
const socket = new net.Socket();
socket.setTimeout(1500);
socket.once('connect', () => {
socket.destroy();
resolve(port);
});
socket.once('timeout', () => {
socket.destroy();
reject(new Error(`Timeout at port: ${port}`));
});
socket.once('error', (e) => {
socket.destroy();
reject(e);
});
socket.connect(port, domain);
});
}
const portsHandler = async (url, event, context) => {
const { hostname: domain } = parseTarget(url);
const delay = (ms) => new Promise((res) => setTimeout(res, ms));
const timeout = delay(9000);
const openPorts = [];
const failedPorts = [];
const promises = PORTS.map((port) =>
checkPort(port, domain)
.then(() => {
openPorts.push(port);
return { status: 'fulfilled', port };
})
.catch(() => {
failedPorts.push(port);
return { status: 'rejected', port };
}),
);
let timeoutReached = false;
for (const promise of promises) {
const result = await Promise.race([
promise,
timeout.then(() => ({ status: 'timeout', timeout: true })),
]);
if (result.status === 'timeout') {
timeoutReached = true;
if (result.timeout) {
// Add the ports not checked yet to the failedPorts array
const checkedPorts = [...openPorts, ...failedPorts];
const portsNotChecked = PORTS.filter((port) => !checkedPorts.includes(port));
failedPorts.push(...portsNotChecked);
}
break;
}
}
if (timeoutReached) {
return errorResponse('The function timed out before completing.');
}
// Sort openPorts and failedPorts before returning
openPorts.sort((a, b) => a - b);
failedPorts.sort((a, b) => a - b);
return { openPorts, failedPorts };
};
const errorResponse = (message, statusCode = 444) => {
return { error: message };
};
export const handler = middleware(portsHandler);
export default handler;