BASH - Check IP is in range of ip pools
I have a list of IPs in MAXCDN_ARRAY to be used as whitelist. I want to check if a specific IP address is in range in this array. How can I structure the code so that it can compare all IPs in the array and say the specific IP in in range of this list or not?
GrepCIDR
You can use grepcidr to check if an IP address is in a list of CIDR networks.
You have to install grepcidr package:
~] apt-get install grepcidr
Bash script to find ip address in range of ip addresses using grepcidr:
#! /bin/bash
MAXCDN_ARRAY="192.168.0.0/24 192.168.0.0/16 192.168.1.0/24 172.16.32.0/16"
IP=192.168.0.5
echo "we use a grepcdir for ip in ip range"
for subnet in $MAXCDN_ARRAY
do
# grepcidr 192.168.1.0/24 <(echo "192.168.1.1")
output_grepcidr=$( grepcidr ${subnet} <(echo ${IP}) )
if [[ ${output_grepcidr} = ${IP} ]]
then
echo "${IP} is in ${subnet}"
else
echo "${IP} is not in ${subnet}"
fi
done
./ip_in_subnet-grepcidr.sh
we use a grepcdir for ip in ip range
192.168.0.5 is in 192.168.0.0/24
192.168.0.5 is in 192.168.0.0/16
192.168.0.5 is not in 192.168.1.0/24
192.168.0.5 is not in 172.16.32.0/16
Note: grepcidr
expects the IP address(es) it is matching to be in a file, not just an argument on the command line. That's why I had to use
<(echo ${IP}
above.
own bash function
I realize that this is older and already has an accepted answer, but this solution utilizes a function I wrote for portability across multiple servers in an environment where grepcidr wasn't a standard package across all servers.
The comments should clarify just what it's doing.
#! /bin/bash
# Set DEBUG=1, in order to see it iterate through the calculations.
# DEBUG=1
MAXCDN_ARRAY="192.168.0.0/24 192.168.0.0/16 192.168.1.0/24 172.16.32.0/16"
IP=192.168.0.5
function in_subnet {
# Determine whether IP address is in the specified subnet.
#
# Args:
# sub: Subnet, in CIDR notation.
# ip: IP address to check.
#
# Returns:
# 1|0
#
local ip ip_a mask netmask sub sub_ip rval start end
# Define bitmask.
local readonly BITMASK=0xFFFFFFFF
# Set DEBUG status if not already defined in the script.
[[ "${DEBUG}" == "" ]] && DEBUG=0
# Read arguments.
IFS=/ read sub mask <<< "${1}"
IFS=. read -a sub_ip <<< "${sub}"
IFS=. read -a ip_a <<< "${2}"
# Calculate netmask.
netmask=$(($BITMASK<<$((32-$mask)) & $BITMASK))
# Determine address range.
start=0
for o in "${sub_ip[@]}"
do
start=$(($start<<8 | $o))
done
start=$(($start & $netmask))
end=$(($start | ~$netmask & $BITMASK))
# Convert IP address to 32-bit number.
ip=0
for o in "${ip_a[@]}"
do
ip=$(($ip<<8 | $o))
done
# Determine if IP in range.
"ip_in_subnet-bash-function.sh" 87 lines, 1981 bytes
echo "we use a grepcdir for ip in ip range"
for subnet in $MAXCDN_ARRAY
do
# grepcidr 192.168.1.0/24 <(echo "192.168.1.1")
output_grepcidr=$( grepcidr ${subnet} <(echo ${IP}) )
if [[ ${output_grepcidr} = ${IP} ]]
then
echo "${IP} is in ${subnet}"
else
echo "${IP} is not in ${subnet}"
fi
done
# Determine if IP in range.
(( $ip >= $start )) && (( $ip <= $end )) && rval=1 || rval=0
(( $DEBUG )) &&
printf "ip=0x%08X; start=0x%08X; end=0x%08X; in_subnet=%u\n" $ip $start $end $rval 1>&2
echo "${rval}"
}
echo "We use own function for ip in ip range"
for subnet in $MAXCDN_ARRAY
do
if [[ $(in_subnet $subnet $IP) -eq 1 ]]
then
echo "${IP} is in ${subnet}"
else
echo "${IP} is not in ${subnet}"
fi
done
~] ./ip_in_subnet-bash-function.sh
We use own function for ip in ip range
192.168.0.5 is in 192.168.0.0/24
192.168.0.5 is in 192.168.0.0/16
192.168.0.5 is not in 192.168.1.0/24
192.168.0.5 is not in 172.16.32.0/16