#!/bin/bash
MAXCDN_ARRAY="108.161.176.0/20 94.46.144.0/20 146.88.128.0/20 198.232.124.0/22 23.111.8.0/22 217.22.28.0/22 64.125.76.64/27 64.125.76.96/27 64.125.78.96/27 64.125.78.192/27 64.125.78.224/27 64.125.102.32/27 64.125.102.64/27 64.125.102.96/27 94.31.27.64/27 94.31.33.128/27 94.31.33.160/27 94.31.33.192/27 94.31.56.160/27 177.54.148.0/24 185.18.207.65/26 50.31.249.224/27 50.31.251.32/28 119.81.42.192/27 119.81.104.96/28 119.81.67.8/29 119.81.0.104/30 119.81.1.144/30 27.50.77.226/32 27.50.79.130/32 119.81.131.130/32 119.81.131.131/32 216.12.211.59/32 216.12.211.60/32 37.58.110.67/32 37.58.110.68/32 158.85.206.228/32 158.85.206.231/32 174.36.204.195/32 174.36.204.196/32"
$IP = 108.161.184.123
if [ $IP in $MAXCDN_ARRAY ];
then:
echo "$IP is in MAXCDN range"
else:
echo "$IP is not in MAXCDN range"
fi
MAXCDN_ARRAY
화이트리스트로 사용하는 IP 목록이 있습니다 . 특정 IP 주소가 이 배열 범위 내에 있는지 확인하고 싶습니다.
배열의 모든 IP를 비교하고 이 목록 범위 내의 특정 IP를 나타내도록 코드를 어떻게 구성할 수 있습니까?
답변1
당신은 그것을 사용할 수 있습니다grepcidrIP 주소가 CIDR 네트워크 목록에 있는지 확인하세요.
#! /bin/bash
NETWORKS="108.161.176.0/20 94.46.144.0/20 146.88.128.0/20 198.232.124.0/22
23.111.8.0/22 217.22.28.0/22 64.125.76.64/27 64.125.76.96/27
64.125.78.96/27 64.125.78.192/27 64.125.78.224/27 64.125.102.32/27
64.125.102.64/27 64.125.102.96/27 94.31.27.64/27 94.31.33.128/27
94.31.33.160/27 94.31.33.192/27 94.31.56.160/27 177.54.148.0/24
185.18.207.65/26 50.31.249.224/27 50.31.251.32/28 119.81.42.192/27
119.81.104.96/28 119.81.67.8/29 119.81.0.104/30 119.81.1.144/30
27.50.77.226/32 27.50.79.130/32 119.81.131.130/32 119.81.131.131/32
216.12.211.59/32 216.12.211.60/32 37.58.110.67/32 37.58.110.68/32
158.85.206.228/32 158.85.206.231/32 174.36.204.195/32
174.36.204.196/32"
for IP in 108.161.184.123 108.161.176.123 192.168.0.1 172.16.21.99; do
grepcidr "$NETWORKS" <(echo "$IP") >/dev/null && \
echo "$IP is in MAXCDN range" || \
echo "$IP is not in MAXCDN range"
done
참고: grepcidr
일치할 것으로 예상되는 IP 주소는 명령줄의 인수뿐만 아니라 파일에 있습니다. 그렇기 때문에 <(echo "$IP")
위의 방법을 사용해야 합니다 .
산출:
108.161.184.123 is in MAXCDN range
108.161.176.123 is in MAXCDN range
192.168.0.1 is not in MAXCDN range
172.16.21.99 is not in MAXCDN range
grepcidr
Debian을 포함한 여러 배포판에 대해 사전 패키징될 수 있습니다.
Package: grepcidr
Version: 2.0-1
Description-en: Filter IP addresses matching IPv4 CIDR/network specification
grepcidr can be used to filter a list of IP addresses against one or
more Classless Inter-Domain Routing (CIDR) specifications, or
arbitrary networks specified by an address range. As with grep, there
are options to invert matching and load patterns from a file.
grepcidr is capable of comparing thousands or even millions of IPs
to networks with little memory usage and in reasonable computation
time.
.
grepcidr has endless uses in network software, including: mail
filtering and processing, network security, log analysis, and many
custom applications.
Homepage: http://www.pc-tools.net/unix/grepcidr/
그렇지 않은 경우 위 링크를 통해 소스를 사용할 수 있습니다.
또 다른 대안은 perl
이러한 언어를 사용하여 IPv4 주소를 조작하고 검사하기 위해 많은 라이브러리/모듈 중 하나를 사용하여 작성하거나 스크립트를 작성하는 것입니다.python
예를 들어, perl
모듈에는 매우 유사한 방법이 Data::Validate::IP
있고 기능이 있습니다 .is_innet_ipv4($ip, $network)
Net::CIDR::Lite
$cidr->find($ip);
Net::IPv4Addr
ipv4_in_network()
python
ipy
, ipaddr
, 및 를 포함한 유사한 라이브러리가 있습니다 ipcalc
.
답변2
grepcidr
나는 이것이 오래되었고 이미 승인된 답변을 가지고 있다는 것을 알고 있지만 이 솔루션은 모든 서버에 걸쳐 표준 패키지가 아닌 환경에서 여러 서버에 이식 가능하도록 작성한 기능을 활용합니다 .
주석은 그것이 무엇을 하고 있는지 명확히 해야 합니다.
#! /bin/bash
# Set DEBUG=1, in order to see it iterate through the calculations.
#DEBUG=1
MAXCDN_ARRAY="108.161.176.0/20 94.46.144.0/20 146.88.128.0/20 198.232.124.0/22 23.111.8.0/22 217.22.28.0/22 64.125.76.64/27 64.125.76.96/27 64.125.78.96/27 64.125.78.192/27 64.125.78.224/27 64.125.102.32/27 64.125.102.64/27 64.125.102.96/27 94.31.27.64/27 94.31.33.128/27 94.31.33.160/27 94.31.33.192/27 94.31.56.160/27 177.54.148.0/24 185.18.207.65/26 50.31.249.224/27 50.31.251.32/28 119.81.42.192/27 119.81.104.96/28 119.81.67.8/29 119.81.0.104/30 119.81.1.144/30 27.50.77.226/32 27.50.79.130/32 119.81.131.130/32 119.81.131.131/32 216.12.211.59/32 216.12.211.60/32 37.58.110.67/32 37.58.110.68/32 158.85.206.228/32 158.85.206.231/32 174.36.204.195/32 174.36.204.196/32"
IP=108.161.184.123
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 >= $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}"
}
for subnet in $MAXCDN_ARRAY
do
(( $(in_subnet $subnet $IP) )) &&
echo "${IP} is in ${subnet}" && break
done
답변3
설치하지 않고 여러 호스트에서 실행하고 싶습니다 grepcidr
.스크립트통과부제하지만 작동하지 않아서 여기에 제가 쓴 내용이 있고 작동이 확인되었습니다. 누군가가 이것이 유용하다고 생각하기를 바랍니다.
function in_subnet {
# Determine whether IP address is in the specified subnet.
#
# Args:
# cidr_subnet: Subnet, in CIDR notation.
# ip_addr: IP address to check.
#
# Returns:
# 0|1
#
local readonly cidr_subnet="${1}"
local readonly ip_addr="${2}"
local subnet_ip cidr_mask netmask ip_addr_subnet subnet rval
subnet_ip=$(echo "${cidr_subnet}" | cut -d'/' -f1)
cidr_mask=$(echo "${cidr_subnet}" | cut -d'/' -f2)
netmask=$(( 0xFFFFFFFF << $(( 32 - ${cidr_mask} )) ))
# Apply netmask to both the subnet IP and the given IP address
ip_addr_subnet=$(( netmask & $(ip_to_int ${ip_addr}) ))
subnet=$(( netmask & $(ip_to_int ${subnet_ip}) ))
# Subnet IPs will match if given IP address is in CIDR subnet
[ "${ip_addr_subnet}" == "${subnet}" ] && rval=0 || rval=1
return $rval
}
function ip_to_int {
local readonly ip_addr="${1}"
local ip_1 ip_2 ip_3 ip_4
ip_1=$(echo "${ip_addr}" | cut -d'.' -f1)
ip_2=$(echo "${ip_addr}" | cut -d'.' -f2)
ip_3=$(echo "${ip_addr}" | cut -d'.' -f3)
ip_4=$(echo "${ip_addr}" | cut -d'.' -f4)
echo $(( ip_1 * 256**3 + ip_2 * 256**2 + ip_3 * 256 + ip_4 ))
}
답변4
grepcidr
일치하는 CIDR을 표시하기 위해 이를 기반으로 하는 향상된 스크립트는 다음과 같습니다 .
스크립트:
echo -e "Searching...\n"; cat cidr.txt | while read NETWORK; do grepcidr "$NETWORK" ip.txt && echo -e "=> found in $NETWORK\n"; done
결과의 예:
Searching...
172.17.1.1
172.18.1.1
=> found in 172.16.0.0/12
192.168.50.1
=> found in 192.168.50.0/24