mirror of
https://github.com/Lissy93/web-check.git
synced 2026-05-13 06:01:02 -04:00
- Sitemap endpoint now recursively expands sitemap-index files - Fixes #165 - Strips :port from target URLs in get-ip, dns, dns-server, ports, mail-config - Fixes #203 - Configurable trust proxy (TRUST_PROXY env) so app works behind Traefik/nginx - Fixes #157 - Tranco rank now correctly says "top 1 million" (was "100 million") - Fixes #257 - Adds engines.node ">=20" so Vercel picks a supported runtime - Re #212 - Raises Vercel maxDuration from 10s to 60s, cutting most 504 timeouts - Re #251 - Re #287 - Bumps axios 1.4.8 to 1.16, closing 4 high-severity SSRF/DoS CVEs - Re #289 - Fixes mail-config crash where dns module was awaited as if promise-based - Adds reusable structured logging util for the API - Bumps a whole bunch of deps, and resolves lots of open npm CVEs
95 lines
2.7 KiB
JavaScript
95 lines
2.7 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;
|