IP がホワイトリスト配列の範囲内にあることを確認します。

IP がホワイトリスト配列の範囲内にあることを確認します。
#!/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

grepcidrDebianを含む複数のディストリビューション用に事前にパッケージ化することができます。

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/

そうでない場合は、上記のリンクからソースを使用できます。


もう1つの選択肢は、perlこれらの言語を使用してIPv4アドレスを操作および検査するために、多くのライブラリ/モジュールのいずれかを使用して作成またはスクリプトを作成することです。python

たとえば、perlモジュールには非常に似た方法がData::Validate::IPあり、機能があります。is_innet_ipv4($ip, $network)Net::CIDR::Lite$cidr->find($ip);Net::IPv4Addripv4_in_network()

pythonipy、、、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

関連情報