#!/usr/bin/perl # Program: scan-subnet.pl # Description: Front-end to scan any given subnet and SMTP servers # Version: 1.1 # Last Update: 15 October 2003 # Written by: Dusan U. Baljevic # # Copyright 2003-2014 Dusan Baljevic # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Make the script very tight. # $ENV{'PATH'} = '/bin:/usr/bin:/usr/local/sbin'; $ENV{'SHELL'} = '/bin/sh' if $ENV{'SHELL'} ne ''; $ENV{'IFS'} = '' if $ENV{'IFS'} ne ''; use strict; no strict 'subs'; use Net::Ping; use POSIX 'uname'; use Getopt::Long qw(:config ignore_case_always require_order); use Socket; use vars qw($RecipientX @values $header $fh $msg $a $h $stop_time $addr $sockaddr @machines $machines $subnet @port @addrs $host $p $n $REMOTE $HostIP $Portproto $proto $port $SERVERNAME $defdomain $help $opt_n %Opts $Usage $IPnet $Defsubnet $addrs $rev_ip $ip); $Usage = "Usage: $0 [-n subnet] [-h] -n 192.168.5 (C-class subnet to scan, default is 192.168.33.0/24) -h (help command)\n"; # Only privileged user should execute LAN scanning. # if ( $> != 0 ) { print STDERR q[ERROR: You cannot run this as non-privileged user!]; print STDERR "\n"; exit(1); } # If no command line arguments, default subnet to # scan... # $Defsubnet = '192.168.33'; # Port to check and possibly figure out the SMTP server version. # @port = (25); $defdomain = "yourcompanyXXX.com"; ( undef, $SERVERNAME, undef, undef, undef ) = uname; # Any command line options? # my ($IPnet) = ''; GetOptions( 'n=s' => \$IPnet, 'h' => \$help ); die $Usage if $help; $subnet = $IPnet || $Defsubnet; #use Regexp::Common; #while() { # if(/$RE{net}{IPv4}{dec}{-keep}/) { # print "IP Address: $1\n"; # } #} $ip = "${subnet}.0"; # Is the IP address valid. For example, 300.201.33.12 is INVALID. # sub CheckIP { my $ip = shift; my ( $addrs, $rev_ip ); ( $addrs = inet_aton($ip) ) and ( $rev_ip = inet_ntoa($addrs) ); return ( defined($addrs) and defined($rev_ip) and $ip eq $rev_ip ); } if ( !CheckIP($ip) ) { die "Invalid or incomplete subnet: $ip\n"; } # Array of all valid hosts on a given subnet. # @machines = map { "$subnet\.$_" } ( 1 .. 254 ); # Subroutine to open a socket and talk to SMTP server. # sub sendemail { use Socket; $REMOTE = $_[0]; $port = $_[1]; if ( $REMOTE =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ ) { $addr = pack( 'C4', $1, $2, $3, $4 ); } else { die("Bad IP address: $!"); } $port = getservbyname( $port, 'tcp' ) if $port =~ /\D/; $proto = getprotobyname('tcp'); socket( S, PF_INET, SOCK_STREAM, $proto ) or die("Socket failed: $!"); $sockaddr = 'S n a4 x8'; if ( connect( S, pack( $sockaddr, AF_INET, $port, $addr ) ) ) { select(S); $| = 1; select(STDOUT); $a = ; print $a; print S "quit"; close(S); } else { "Unable to connect: $!"; } } # Resolve hostname (find its IP address). # print "Testing Subnet $subnet on port @port\n"; print "=====================================\n"; foreach $host (@machines) { my $PING = 0; print "\nChecking $host...\n"; ( undef, undef, undef, undef, @addrs ) = gethostbyname($host); foreach my $a (@addrs) { $HostIP = join( '.', unpack( 'C4', $a ) ); } if ( !defined($HostIP) ) { print "Check hostname resolution for server \"$host\".\n"; exit(1); } # First check if the server is responding to ICMP... # $h = Net::Ping->new(); if ( !$h->ping($host) ) { print "WARN: $host is NOT reachable (first type ICMP).\n"; $PING++; } $h->close(); # Second type of ping test. # $h = Net::Ping->new("icmp"); if ( !$h->ping( $host, 2 ) ) { print "WARN: $host is NOT reachable (second type ICMP).\n"; $PING++; } $h->close(); # Third type of ping test. # $h = Net::Ping->new( "tcp", 2 ); while ( $stop_time > time() ) { print "WARN: $host is NOT not reachable (TCP ping)", scalar( localtime() ), "\n" unless $h->ping($host); $PING++; } undef($h); # Now, check the ports. # if ( $PING < 3 ) { foreach my $n (@port) { my $p = Net::Ping->new("tcp"); $Portproto = getservbyport( $n, 'tcp' ); $p->{port_num} = $n if $n; if ( $p->ping($host) ) { print " Port $n\@$host is ACTIVE\n"; &sendemail( $host, $n ); } else { print " Port $n\@$host is INACTIVE or FILTERED\n"; } print; } } } # Exit gracefully. # exit(0);