Category: Sys Admin/Net Admin
Author/Contact Info Joe Callis aka birdbrane
Description: This script scans through a subnetted class B network and looks for *NIX hosts. I have set this script up to report if rsh (port 514) is open (for my own admin purposes). For a quicker scan, remove the nmap and just do the rpcinfo. For NT, change the ports you are looking for and reverse the logic on rpcinfo (or remove it). The script uses nmap and rpcinfo. For an subnetted class B network, the script takes 4-6 hours to complete.
#! /usr/local/bin/perl -w

# Written by Joe Callis aka birdbrane, April 2001.
#
# Determine which machines are UNIX servers by doing a port scan
# on port 514 and 2049 and a udp and/or icmp ping, if this 
# returns successful, do an rpcinfo -p. If this succeeds it is
# a UNIX host (not a f/w, or gw).

# The script can be easily tailored to find nt machines, gateways, 
# firewalls etc. Just change the ports and dependency on rpcinfo.

use strict;
use Net::Ping;

my $Scanner = "/usr/local/bin/nmap";
my $ScanArgs = "-sS -PB -T 5 -p 514,2049";
my $RPCProbe = "/usr/bin/rpcinfo -p";
my $FirstOctets = "172.16";

my $Hostname;
my $IPBlk;
my $RPCScan;
my $ThirdOctet;
my $FourthOctet;

# Cycles through third octet, pinging either the .0 or .255 address, l
+ooking
# to see if the subnet is alive. If not, then skip.

THIRD: for ($ThirdOctet = 1; $ThirdOctet <= 254; $ThirdOctet++) {
    $IPBlk = "$FirstOctets." . "$ThirdOctet";
    my $sbnt = "$IPBlk" . ".255";
    CHECK: foreach my $cmdline (`/usr/sbin/ping $sbnt 1`) {
        if ( ! ($cmdline =~ /alive/)) {
            $sbnt = "$IPBlk" . ".0";
            foreach my $cmdline (`/usr/sbin/ping $sbnt 1`) {
                next THIRD unless ($cmdline =~ /alive/);
            }        
        }
    }

# Cycles thru fourth octet, running  nmap (w/ "insane" timing policy) 
+against
# each IP. The script then looks for lines w/ 2049 and/or 514. If foun
+d,
# it then will try an rpcinfo on the IP. If this fails, it goes to the
# next IP, otherwise, it will record the IP along w/ port open.

    my $Output = "/cinnabar/hostlist_$IPBlk";
    open(HOST,">$Output") || die "can't open $Output: $!\n";
    FOURTH: for ($FourthOctet = 1; $FourthOctet <= 254; $FourthOctet++
+) {
        my $NFS = "";
        my $Shell = "";
        my $IP = "$FirstOctets." . "$ThirdOctet." . $FourthOctet;
        my @Info = qx($Scanner $ScanArgs $IP);
        foreach my $line (@Info) {
            chomp $line;
            next unless ($line =~ /^(\d+)\/\w{3}\s+(\w+)\s+(\w+)/);
            if ($1 =~ /2049/) {
                $NFS = $line;
            } elsif ($1 =~ /514/) {
                $Shell = $line;
            }
            foreach $RPCScan (`$RPCProbe $IP 2>&1`) {
                if ($RPCScan =~ /tcp/) {
                    last;
                } elsif ($RPCScan =~ /failure/) {
                    next FOURTH;
                }
            }
        }
        if ($NFS && $Shell) {
            print HOST "$IP\t$Shell\n";
        } elsif ($NFS) {
            print HOST "$IP\t$NFS\trsh not available\n";
        } elsif ($Shell) {
            print HOST "$IP\t$Shell\n";
        }

    }
}