加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

bash – 在两个IPv4地址之间以CIDR表示法查找IPv4网络的算法

发布时间:2020-12-15 21:43:56 所属栏目:安全 来源:网络整理
导读:我想找出这两个网络之间CIDR表示法中的所有IPv4网络: 10.11.3.64-10.11.3.12710.11.52.0-10.11.52.255 IPv4网络应具有尽可能短的子网掩码. 将10.11.3.127转换为二进制,添加1并转换回十进制以获得网络的第一个地址相当容易.然后将10.11.52.0转换为二进制,减
我想找出这两个网络之间CIDR表示法中的所有IPv4网络:

10.11.3.64-10.11.3.127
10.11.52.0-10.11.52.255

IPv4网络应具有尽可能短的子网掩码.

将10.11.3.127转换为二进制,添加1并转换回十进制以获得网络的第一个地址相当容易.然后将10.11.52.0转换为二进制,减去1并转换回十进制,以获得网络的最后一个地址.但是,为了找出10.11.3.128-10.11.51.255范围内的CIDR块,有哪些建议哪些算法很聪明?只是一个建议,我认为哪个方向应该足够:)

解决方法

我真的很喜欢这个问题,我昨晚看了一眼并决定试一试.在这一点上,我有一个概念证明shell脚本工作.

免责声明:

>这只是一个概念证明
>我在这里重新发明了轮子,因为我没有使用任何TCP / IP库
>我没有实现输入验证
>如果用编程语言而不是bash编写,这段代码可能会快得多,尽管对于这种特定的网络范围并不是那么慢

值得一提的另一件事是我的理解:

IPv4网络应具有尽可能短的子网掩码.

我们应该尝试从保留的8位网络到提供的最大cidr,在这种情况下为25.

好的,让我们看看脚本在运行:

[root@TIAGO-TEST2 tmp]# time bash  ip.sh   10.11.3.64/25 10.11.52.0/24 
10.11.3.128/25
10.11.4.0/22
10.11.8.0/21
10.11.16.0/20
10.11.32.0/20
10.11.48.0/22

real    0m48.376s
user    0m6.174s
sys     0m34.644s

代码下方:

#! /bin/bash

function split_octet {
    sed -re "s/./ /g" <<< "$1"
}

function dec2bin {
    perl -e 'printf "%0'"$1"'bn",'"$2"';'
}

function bin2dec {
    perl -le 'print 0b'"$1"';'
}

function ip2bin {
    str=""
    for octet in $(split_octet $1); do
        str="${str}$(dec2bin 8 $octet)"
    done
    echo "$str"
}

function bin2ip {
    str=""
    for octet in $(grep -Eo '.{8}' <<< $1); do
        dec=$(bin2dec $octet)
        str="${str}.${dec}"
    done
    echo "$str" | sed -re 's/^.|.$//g'
}

function ip2dec {
    ip=$1
    bin2dec $(ip2bin $ip )
}

function dec2ip  {
    dec=$1
    bin2ip $(dec2bin 32 $dec )
}

function AND {
    perl -e '   $a=0b'"$1"' & 0b'"$2"';
                        printf "%032bn",$a
                    '
}

function OR {
    perl -e '   $a=0b'"$1"' | 0b'"$2"';
                        printf "%032bn",$a
                    '
}

function NOT {
    perl -le '  $a= (~ 0b'"$1"') & 0xFFFFFFFF; 
                            printf "%032bn",$a
                     '
}

function get_network {
    ip=$1; mask=$2;

    if [ -n "$ip" -a -n "$mask" ];then
    echo $(bin2ip $(AND $(ip2bin $ip) $(ip2bin $mask)))
        return
    fi

    grep -qP "d+.d+.d+.d+/d+" <<< "$ip"
    if [ "$?" == 0 ];then
        ip=$(get_ip_from_cidr $1 )
        mask=$(get_mask_from_cidr $1)
        echo $( bin2ip $(AND $(ip2bin $ip) $(ip2bin $mask)))
    fi
}

function get_broadcast {
    ip=$1; mask=$2;

    if [ -n "$ip" -a -n "$mask" ];then
        echo $( bin2ip $(OR $(ip2bin $ip) $(NOT $(ip2bin $mask) ) ))
        return
    fi

    grep -qP "d+.d+.d+.d+/d+" <<< "$ip"
    if [ "$?" == 0 ];then
        ip=$(get_ip_from_cidr $1 )
        mask=$(get_mask_from_cidr $1)
        echo $( bin2ip $(OR $(ip2bin $ip) $(NOT $(ip2bin $mask) ) ))
    fi

}

function get_ip_from_cidr {
    awk -F/ '{print $1}' <<< "$1"
}

function get_mask_from_cidr {
    mask=$(awk -F/ '{print $2}' <<< "$1")
    mask=$(cidr $mask)
    mask=$(bin2ip $mask)
    echo $mask
}

function cidr {
    perl -e '
                        $n='"$1"';
                        $diff=32-$n;
                        print "1"x$n . "0"x$diff;
                    '
}


snet_cidr=$1
enet_cidr=$2

largest_cidr=$(echo -e "$snet_cidrn$enet_cidr"| awk -F/ '{print $2}' | sort -rn | head -1 )

snet_dec=$( ip2dec $(get_ip_from_cidr $snet_cidr))
enet_dec=$( ip2dec $(get_ip_from_cidr $enet_cidr))

sbc_ip=$(get_broadcast $snet_cidr)
ebc_ip=$(get_broadcast $enet_cidr)

sbc_dec=$(ip2dec $sbc_ip)
ebc_dec=$(ip2dec $ebc_ip)

counter=$sbc_dec

while [ $counter -lt $enet_dec ];do
    tip=$(dec2ip $counter)
    for cidr in $(seq 8 $largest_cidr) ; do 
        tnet_ip=$(get_network $tip/$cidr)
        tnet_cidr=$tnet_ip/$cidr
        tbc_ip=$(get_broadcast $tnet_cidr)
        tnet_dec=$( ip2dec $(get_ip_from_cidr $tnet_cidr))
        tbc_dec=$(ip2dec $tbc_ip)
        if [ $sbc_dec -lt $tnet_dec -a $enet_dec -gt $tbc_dec ];then
            echo $tnet_cidr 
            counter=$tbc_dec
            break
        fi  
    done
    let counter++
done

编辑解释这些变量是什么可能是一个好主意:

> snet_cidr:以cidr表示法启动net
> enet_cidr:cidr中的结束网
> snet_dec:以十进制开始网
> enet_dec:以十进制表示的结束网
> sbc_ip:启动广播ip
> ebc_ip:end broadcast ip
> sbc_dec:启动广播ip
> ebc_dec:结束广播ip

无论你在哪里看到tnet或tbc都是temp net,temp broadcast,temp,因为它在循环内部.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读