NODEJS: Can I scan my local network for specific open ports QUICKLY?

I would like to know if there's a way to scan through my local network's IP range for open ports of a specific number.

Essentially I'm looking for NODE to find clients of a specific type without knowing their IP addresses. In this case, RFID readers which listen on port 14150.

I'd like this scan to be quick, so I don't want a long timeout between each IP address. They should all happen rather quickly, perhaps within a few seconds MAX for an entire local IP range of up to 255 clients, excluding my own IP.

UPDATE:::: I wrote code that does what I want but it's painfully slow... I would like to see how I can make this faster by blazing through the connections and getting out if a connection cannot be made to a given IP within 20ms. I want to capture the actual connections in an array that I can then use for another purpose.

/************* DEPENDENCIES ***********/
var net = require('net'); // Required to create socket connections

var ip = 254; //IP address to start with on a C class network

function checkConnect(){
    ip--;
    var thisIP = '192.168.1.'+ip; //concatenate to a real IP address

    var S = new net.Socket();
    S.connect(80, thisIP);

    if(ip>0){ checkConnect(); }

    S.on('connect',function(){console.log("port 80 found on "+thisIP);});
    S.on('error',function(){console.log("no such port on "+thisIP)});
    S.end();
}

checkConnect();

i'm the evil ;)

I've made it for you https://github.com/eviltik/evilscan. (just released v0.0.3 today)

Install:

    npm install -g evilscan

Usage (port list + port range) :

    root@debian:~# evilscan --target=192.168.0.0/24 --port=21-446,5900 --concurrency=100 --progress
    192.168.0.3:5900|open
    192.168.0.26:53|open
    192.168.0.26:111|open
    192.168.0.26:81|open
    192.168.0.26:23|open
    Scanned 192.168.0.253:446 (100%)

Tips :

For very fast scanning, you can play with "concurrency" parameter, more than 1000, but you have to update ulimit parameter of your linux first :

    ulimit -u unlimited

Hope this help.

You can use arp command to get a list of devices that are alive first. Think outside the box ;) You don't have to scan all the devices blindly.

var child = require("child_process"); 
var async = require("async"); 
var net = require("net"); 
var os = require("os"); 

function scan(port, cb){
    var hosts = {}; 
    var result = []; 
    async.series([
        function scan(next, c){
            if(c == 1){
                next(); return; 
            }
            // scan twice because arp sometimes does not list all hosts on first time
            child.exec("arp -n | awk '{print $1}' | tail -n+2", function(err, res){
                if(err) cb(err); 
                else {
                    var list = res.split("\n").filter(function(x){return x !== "";}); 
                    list.map(function(x){
                        hosts[x] = x; 
                    }); 
                }
                scan(next, 1); 
            }); 
        },
        function(next){
            // if you want to scan local addresses as well 
            var ifs = os.networkInterfaces(); 
            Object.keys(ifs).map(function(x){
                hosts[((ifs[x][0])||{}).address] = true; 
            }); 
            // do the scan
            async.each(Object.keys(hosts), function(x, next){
                var s = new net.Socket(); 
                s.setTimeout(1500, function(){s.destroy(); next();}); 
                s.on("error", function(){
                    s.destroy(); 
                    next(); 
                }); 
                s.connect(port, x, function(){
                    result.push(x); 
                    s.destroy(); 
                    next(); 
                }); 
            }, function(){
                next();
            });
        }
    ], function(){
        cb(null, result); 
    }); 
} 

scan(80, function(err, hosts){
    if(err){
        console.error(err); 
    } else {
        console.log("Found hosts: "+hosts);
    } 
}); 

You can also use arp-scan utility it is more reliable. But arp-scan needs root access to work, so it's better to just use arp. It's available on pretty much every linux box.

None of the previous answers really worked how I needed. I found a much lighter weight alternative. With this solution I get my solution quickly. My next upgrade will be to specify a range of hosts based on the current subnet. I imagine I'll want to limit this to the first 254 clients so it's not overkill. Here is the code:

//LLRP DEVICE SCANNER
var net    = require('net'), Socket = net.Socket;

var checkPort = function(port, host, callback) {
    var socket = new Socket(), status = null;

    // Socket connection established, port is open
    socket.on('connect', function() {status = 'open';socket.end();});
    socket.setTimeout(1500);// If no response, assume port is not listening
    socket.on('timeout', function() {status = 'closed';socket.destroy();});
    socket.on('error', function(exception) {status = 'closed';});
    socket.on('close', function(exception) {callback(null, status,host,port);});

    socket.connect(port, host);
}

var LAN = '192.168.1'; //Local area network to scan (this is rough)
var LLRP = 5084; //globally recognized LLRP port for RFID readers

//scan over a range of IP addresses and execute a function each time the LLRP port is shown to be open.
for(var i=1; i <=255; i++){
    checkPort(LLRP, LAN+'.'+i, function(error, status, host, port){
        if(status == "open"){
            console.log("Reader found: ", host, port, status);
        }
    });
}

Instead of just posting the link (the link might go dead at one moment), i'll post the tutorial code here from the site:

var net = require('net');

// the machine to scan
var host = 'localhost';
// starting from port number
var start = 1;
// to port number
var end = 10000;
// sockets should timeout asap to ensure no resources are wasted
// but too low a timeout value increases the likelyhood of missing open sockets, so be careful
var timeout = 2000;

// the port scanning loop 
while (start <= end) {

    // it is always good to give meaningful names to your variables
    // since the context is changing, we use `port` to refer to current port to scan 
    var port = start;

    // we create an anonynous function, pass the current port, and operate on it
    // the reason we encapsulate the socket creation process is because we want to preseve the value of `port` for the callbacks 
    (function(port) {
        // console.log('CHECK: ' + port);
        var s = new net.Socket();

        s.setTimeout(timeout, function() { s.destroy(); });
        s.connect(port, host, function() {
            console.log('OPEN: ' + port);
            // we don't destroy the socket cos we want to listen to data event
            // the socket will self-destruct in 2 secs cos of the timeout we set, so no worries
        });

        // if any data is written to the client on connection, show it
        s.on('data', function(data) {
            console.log(port +': '+ data);
            s.destroy();
        });

        s.on('error', function(e) {
            // silently catch all errors - assume the port is closed
            s.destroy();
        });
    })(port);

    start++;
}