Skip to content

Instantly share code, notes, and snippets.

@ancms2600
Created October 3, 2019 22:53
Show Gist options
  • Save ancms2600/fc1fb4110592ffec7b0dfeeab274c6a7 to your computer and use it in GitHub Desktop.
Save ancms2600/fc1fb4110592ffec7b0dfeeab274c6a7 to your computer and use it in GitHub Desktop.
Simple TCP Port Scanner in Node.JS
(async () => {
const net = require('net');
const dns = require('dns');
const fs = require('fs');
const [,,host,portmin,portmax] = process.argv;
let a = Date.now();
const ipv4 = await new Promise((ok,fail) =>
dns.lookup(host, { family: 4, verbatim: true }, (err, address, family) =>
err ? fail(err) : ok(address)));
let elapsed = Date.now() - a;
if (ipv4 !== host) {
console.log(`Resolved hostname ${host} to ${ipv4} in ${elapsed} ms.`);
}
const TIMEOUT = 3*1000;
function probe(host, port, cb) {
let connect, timeout, hangup, error, data, end, emitted;
const client = net.createConnection({
port,
host: ipv4,
timeout: TIMEOUT,
family: 4,
lookup: () => {},
}, () => {
connect = true;
});
client.setNoDelay(true);
client.setKeepAlive(false);
client.setEncoding('utf8');
const done = () => {
if (emitted) return;
emitted = true;
clearTimeout(timer);
cb({ port, connect, timeout, hangup, error, data, end });
};
const timer = setTimeout(()=>{
hangup = true;
client.end();
done();
}, TIMEOUT+1000);
client.on('timeout', () => { timeout = true; done(); });
client.on('error', (e) => { error = e; });
client.on('data', (d) => { null == data ? data = d : data += d; });
client.on('end', () => { end=true; done(); });
// other events: close, connect, drain, lookup, ready
}
const CONCURRENCY = 100;
let running = 0;
let port = portmin;
const ports = [];
for (let i=portmin; i<=portmax; i++) ports.push(i);
ports.sort(()=>.5-Math.random());
const next = () => {
running--;
if (ports.length > 0) {
const port = ports.pop();
probe(host, port, (outcome) => {
render(outcome);
process.nextTick(next);
});
running++;
}
else if (running < 1) {
console.log('\n\ndone.');
process.exit(0);
}
};
for (let i=0; i<CONCURRENCY; i++) {
running++;
next();
}
let lastRenderedDot = false;
const render = (outcome) => {
let out;
if (outcome.timeout) {
out = (lastRenderedDot ? '' : '\n') + '.';
lastRenderedDot = true;
}
else {
out = '\n'+JSON.stringify(outcome);
lastRenderedDot = false;
}
fs.appendFileSync('./out.log', out);
process.stdout.write(out);
};
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment