Check if an IP is in a subnet

At some point I counted my DROP rules in my firewall and the result was kinda frightening. A lot of subnets and even more IPs...
What was really annoying was that there where a lot of IP address which they belonged to an already blocked subnet, so I needed a script to check this for me.

It has to be a script to do this already out there in the wild. Also a machine is faster than a human. Having this in mind, why should I reinvent the wheel? So after searching a little bit on web, I found this nice perl script.

#!/usr/bin/perl
 
use strict;
 
use Socket qw( inet_aton );
 
sub ip2long($);
sub in_subnet($$);
 
my $ip = $ARGV[0];
my $subnet = $ARGV[1];
 
if( in_subnet( $ip, $subnet ) )
{
	print "It's in the subnet\n";
}
else
{
	print "It's NOT in the subnet\n";
}
 
sub ip2long($)
{
	return( unpack( 'N', inet_aton(shift) ) );
}
 
sub in_subnet($$)
{
	my $ip = shift;
	my $subnet = shift;
 
	my $ip_long = ip2long( $ip );
 
	if( $subnet=~m|(^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$| )
	{
		my $subnet = ip2long( $1 );
		my $mask = ip2long( $2 );
 
		if( ($ip_long & $mask)==$subnet )
		{
			return( 1 );
		}
	}
	elsif( $subnet=~m|(^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/(\d{1,2})$| )
	{
		my $subnet = ip2long( $1 );
		my $bits = $2;
		my $mask = -1<<(32-$bits);
 
		$subnet&= $mask;
 
		if( ($ip_long & $mask)==$subnet )
		{
			return( 1 );
		}
	}
	elsif( $subnet=~m|(^\d{1,3}\.\d{1,3}\.\d{1,3}\.)(\d{1,3})-(\d{1,3})$| )
	{
		my $start_ip = ip2long( $1.$2 );
		my $end_ip = ip2long( $1.$3 );
 
		if( $start_ip<=$ip_long and $end_ip>=$ip_long )
		{
			return( 1 );
		}
	}
	elsif( $subnet=~m|^[\d\*]{1,3}\.[\d\*]{1,3}\.[\d\*]{1,3}\.[\d\*]{1,3}$| )
	{
		my $search_string = $subnet;
 
		$search_string=~s/\./\\\./g;
		$search_string=~s/\*/\.\*/g;
 
		if( $ip=~/^$search_string$/ )
		{
			return( 1 );
		}
	}
 
	return( 0 );
}

Source: http://www.mikealeonetti.com/wiki/index.php?title=Check_if_an_IP_is_in_a_subnet_in_Perl

Leave a Reply

Your email address will not be published. Required fields are marked *