Friday 7 August 2015

Web Scanning for Devices on your network using Nmap and Perl

Introduction

I wanted a way of keeping tabs on how much the kid's computer was being used during the day while we were out. I can look on the router to see what devices are connected to the network, but this only works while I'm at home.

As I run a web server at my home, I decided to put together a quick webpage that scans for devices and shows the result on a smartphone.




Scanning the Network

After a few web searches I found the best tool to use on my Linux server was nmap, so I installed it and started playing around scanning my network. Results were initially pretty patchy, either the scan took too long (in excess of a minute) or finished quickly but didn't pick everything up.

The results depend on what sort of scan you want to do, it will scan ports and even attempt to detect the device's operating system.

In it's simplest form just enter:-

  nmap 192.168.1.*

Which will scan for range of addresses using a wildcard, or you could just do the following for a smaller range (192.168.1.1 - 192.168.1.20):-

  nmap 192.168.1.1-20

You can perform a fast scan by using the F flag:-

  nmap -F 192.168.1.*

Or include a range of ports (say 80 to 200):-

  nmap -p 80-200 192.168.1.*

Anyway, it does loads of good stuff, and also generated a lot of errors like this..


  RTTVAR has grown to over 2.3 seconds, decreasing to 2.0

I couldn't find much help about this warning message, but it seems to be related to the scan taking longer than expected. Be patient.

Eventually, I settled on the following command which gave a rapid reply and a reasonable degree of accuracy. (The T5 flag sets the timing template so it times-out sooner.)

  nmap -F -T5 192.168.1.*


Building it into a Webpage

My main aim was to show the data in a webpage which could be viewed from anywhere. I chose to use Perl and the CGI library to do this, although I could have used PHP instead. (I'm just more familiar with Perl)

Here's the code I came up with, it also uses the Nmap_Parser library to make handling the nmap data easy.

#!/usr/bin/perl
use strict;
use Nmap::Parser;
use CGI ":all";

my $q = CGI->new();
print $q->header();
print $q->start_html(-title => 'Scan Network',
                     -head  => meta({-name    => 'viewport',
                                     -content => 'width=device-width, initial-scale=1'}));

my %known = ('Unknown-f0-b4-79-19-a8-ff.home'             => "Rick's Laptop",
                         'android-16f4d57ae478ea5.home'   => "Saul's Phone",
                         'Unknown-84-38-35-41-0d-56.home' => "Ruth's Laptop");

print "<h1>Devices on Network</h1>";
print "<FORM><INPUT TYPE='button' onClick='history.go(0)' VALUE='Refresh'></FORM></h1>";

my $np = new Nmap::Parser;
$np->parsescan('/usr/bin/nmap','-F -T5',"192.168.1.*");

for my $host ($np->all_hosts()){
   if ($host->hostname){
       my $hostname = $host->hostname;
       if (exists($known{$hostname})){ $hostname = $known{$hostname}; }     
       print "<p><span style='display:inline-block;width:7em'>".$host->addr."</span>: ".$hostname."</p>";
   }
}
print $q->end_html();

You may also notice I added a way of remapping 'Unknown' devices to something more helpful. It goes without saying that you should add your own devices to the '%known' hash array, if you find them being displayed with unhelpful names.

I also set the meta tag in the html head so that it behaves better on mobile devices.

Performance

In use it takes between 5 and 10 seconds to perform a scan. Sometimes devices aren't detected on the first scan (especially mobile devices), so refresh the page a few times to get a more accurate idea.

It picks up most devices including my Bluray player and Humax PVR, but for some reason it wouldn't detect the Nintendo Wii earlier. (not sure why)

Anyway, hope some of you find it useful.

1 comment:

  1. I don't know Perl enough but your idea to use nmap in connection with a dynamic webpage is great.
    Thanks for the post.

    ReplyDelete