Created
October 3, 2019 22:53
-
-
Save ancms2600/fc1fb4110592ffec7b0dfeeab274c6a7 to your computer and use it in GitHub Desktop.
Simple TCP Port Scanner in Node.JS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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