我试图创建脚本,我可以输入一组前缀,然后将列出的前缀(包括网络/主机/广播)内的所有IP地址.
一个例子是:
./convert-prefix-to-IPs.sh 192.168.0.0/23 203.20.0.0/16
192.168.0.0
192.168.0.1
...
192.168.0.255
192.168.1.0
..
192.168.1.255
203.20.0.0
..
203.20.255.255
Run Code Online (Sandbox Code Playgroud)
有一些Python/Perl脚本可以做到这一点,但我希望能有一个简单的bash脚本,因为它可能会在没有的Perl/Python的系统中使用(是的..我知道..)
小智 25
这是我用来生成给定CIDR块中的所有IP地址的内容
nmap -sL 10.10.64.0/27 | awk '/Nmap scan report/{print $NF}'
Run Code Online (Sandbox Code Playgroud)
就这么简单
上面的命令输出这个
10.10.64.0
10.10.64.1
10.10.64.2
10.10.64.3
10.10.64.4
10.10.64.5
10.10.64.6
10.10.64.7
10.10.64.8
10.10.64.9
10.10.64.10
10.10.64.11
10.10.64.12
10.10.64.13
10.10.64.14
10.10.64.15
10.10.64.16
10.10.64.17
10.10.64.18
10.10.64.19
10.10.64.20
10.10.64.21
10.10.64.22
10.10.64.23
10.10.64.24
10.10.64.25
10.10.64.26
10.10.64.27
10.10.64.28
10.10.64.29
10.10.64.30
10.10.64.31
Run Code Online (Sandbox Code Playgroud)
小智 17
我也在寻找这个解决方案,发现@scherand脚本效果很好.我也添加了这个脚本,为您提供更多选择.帮助文件如下.
这篇文章将扩大CIDR地址.
./cidr-to-ip.sh [OPTION(only one)] [STRING/FILENAME]
Run Code Online (Sandbox Code Playgroud)
-h显示此帮助屏幕
-f在给定STRING(s)时强制检查网络边界
-i将从输入文件中读取(文件每行应包含一个CIDR)(无网络边界检查)
-b将与-i相同但使用网络边界检查
./cidr-to-ip.sh 192.168.0.1/24
./cidr-to-ip.sh 192.168.0.1/24 10.10.0.0/28
./cidr-to-ip.sh -f 192.168.0.0/16
./cidr-to-ip.sh -i inputfile.txt
./cidr-to-ip.sh -b inputfile.txt
#!/bin/bash
############################
## Methods
############################
prefix_to_bit_netmask() {
prefix=$1;
shift=$(( 32 - prefix ));
bitmask=""
for (( i=0; i < 32; i++ )); do
num=0
if [ $i -lt $prefix ]; then
num=1
fi
space=
if [ $(( i % 8 )) -eq 0 ]; then
space=" ";
fi
bitmask="${bitmask}${space}${num}"
done
echo $bitmask
}
bit_netmask_to_wildcard_netmask() {
bitmask=$1;
wildcard_mask=
for octet in $bitmask; do
wildcard_mask="${wildcard_mask} $(( 255 - 2#$octet ))"
done
echo $wildcard_mask;
}
check_net_boundary() {
net=$1;
wildcard_mask=$2;
is_correct=1;
for (( i = 1; i <= 4; i++ )); do
net_octet=$(echo $net | cut -d '.' -f $i)
mask_octet=$(echo $wildcard_mask | cut -d ' ' -f $i)
if [ $mask_octet -gt 0 ]; then
if [ $(( $net_octet&$mask_octet )) -ne 0 ]; then
is_correct=0;
fi
fi
done
echo $is_correct;
}
#######################
## MAIN
#######################
OPTIND=1;
getopts "fibh" force;
shift $((OPTIND-1))
if [ $force = 'h' ]; then
echo ""
echo -e "THIS SCRIPT WILL EXPAND A CIDR ADDRESS.\n\nSYNOPSIS\n ./cidr-to-ip.sh [OPTION(only one)] [STRING/FILENAME]\nDESCRIPTION\n -h Displays this help screen\n -f Forces a check for network boundary when given a STRING(s)\n -i Will read from an Input file (no network boundary check)\n -b Will do the same as –i but with network boundary check\n\nEXAMPLES\n ./cidr-to-ip.sh 192.168.0.1/24\n ./cidr-to-ip.sh 192.168.0.1/24 10.10.0.0/28\n ./cidr-to-ip.sh -f 192.168.0.0/16\n ./cidr-to-ip.sh -i inputfile.txt\n ./cidr-to-ip.sh -b inputfile.txt\n"
exit
fi
if [ $force = 'i' ] || [ $force = 'b' ]; then
old_IPS=$IPS
IPS=$'\n'
lines=($(cat $1)) # array
IPS=$old_IPS
else
lines=$@
fi
for ip in ${lines[@]}; do
net=$(echo $ip | cut -d '/' -f 1);
prefix=$(echo $ip | cut -d '/' -f 2);
do_processing=1;
bit_netmask=$(prefix_to_bit_netmask $prefix);
wildcard_mask=$(bit_netmask_to_wildcard_netmask "$bit_netmask");
is_net_boundary=$(check_net_boundary $net "$wildcard_mask");
if [ $force = 'f' ] && [ $is_net_boundary -ne 1 ] || [ $force = 'b' ] && [ $is_net_boundary -ne 1 ] ; then
read -p "Not a network boundary! Continue anyway (y/N)? " -n 1 -r
echo ## move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]; then
do_processing=1;
else
do_processing=0;
fi
fi
if [ $do_processing -eq 1 ]; then
str=
for (( i = 1; i <= 4; i++ )); do
range=$(echo $net | cut -d '.' -f $i)
mask_octet=$(echo $wildcard_mask | cut -d ' ' -f $i)
if [ $mask_octet -gt 0 ]; then
range="{$range..$(( $range | $mask_octet ))}";
fi
str="${str} $range"
done
ips=$(echo $str | sed "s, ,\\.,g"); ## replace spaces with periods, a join...
eval echo $ips | tr ' ' '\n'
else
exit
fi
done
Run Code Online (Sandbox Code Playgroud)
我最近编写了一个函数来从给定的网络地址生成所有 IP 地址。该函数将网络地址作为参数并接受 CIDR 和子网掩码。然后脚本将所有 IP 存储在数组变量 $ips 中。
network_address_to_ips() {
# create array containing network address and subnet
local network=(${1//\// })
# split network address by dot
local iparr=(${network[0]//./ })
# if no mask given it's the same as /32
local mask=32
[[ $((${#network[@]})) -gt 1 ]] && mask=${network[1]}
# convert dot-notation subnet mask or convert CIDR to an array like (255 255 255 0)
local maskarr
if [[ ${mask} =~ '.' ]]; then # already mask format like 255.255.255.0
maskarr=(${mask//./ })
else # assume CIDR like /24, convert to mask
if [[ $((mask)) -lt 8 ]]; then
maskarr=($((256-2**(8-mask))) 0 0 0)
elif [[ $((mask)) -lt 16 ]]; then
maskarr=(255 $((256-2**(16-mask))) 0 0)
elif [[ $((mask)) -lt 24 ]]; then
maskarr=(255 255 $((256-2**(24-mask))) 0)
elif [[ $((mask)) -lt 32 ]]; then
maskarr=(255 255 255 $((256-2**(32-mask))))
elif [[ ${mask} == 32 ]]; then
maskarr=(255 255 255 255)
fi
fi
# correct wrong subnet masks (e.g. 240.192.255.0 to 255.255.255.0)
[[ ${maskarr[2]} == 255 ]] && maskarr[1]=255
[[ ${maskarr[1]} == 255 ]] && maskarr[0]=255
# generate list of ip addresses
local bytes=(0 0 0 0)
for i in $(seq 0 $((255-maskarr[0]))); do
bytes[0]="$(( i+(iparr[0] & maskarr[0]) ))"
for j in $(seq 0 $((255-maskarr[1]))); do
bytes[1]="$(( j+(iparr[1] & maskarr[1]) ))"
for k in $(seq 0 $((255-maskarr[2]))); do
bytes[2]="$(( k+(iparr[2] & maskarr[2]) ))"
for l in $(seq 1 $((255-maskarr[3]))); do
bytes[3]="$(( l+(iparr[3] & maskarr[3]) ))"
printf "%d.%d.%d.%d\n" "${bytes[@]}"
done
done
done
done
}
Run Code Online (Sandbox Code Playgroud)
network_address_to_ips 10.0.1.0/255.255.255.240
network_address_to_ips 10.1.0.0/24
Run Code Online (Sandbox Code Playgroud)
此简短脚本将在几行Bash中打印CIDR范围内的所有IP地址。(我以相同名称prips的Ubuntu命令命名。显然,如果该命令可用,请使用该命令。)
prips() {
local cidr=$1 ; local lo hi a b c d e f g h
# range is bounded by network (-n) & broadcast (-b) addresses.
lo=$(ipcalc -n "$cidr" | cut -f2 -d=)
hi=$(ipcalc -b "$cidr" | cut -f2 -d=)
IFS=. read -r a b c d <<< "$lo"
IFS=. read -r e f g h <<< "$hi"
eval "echo {$a..$e}.{$b..$f}.{$c..$g}.{$d..$h}"
}
Run Code Online (Sandbox Code Playgroud)
请注意,我假设使用RedHat Linux(Erik Troan,Preston Brown)版本ipcalc,而不是某些平台(例如Mac OS X)上安装的Krischan Jodies版本。
例子:
$ prips 10.0.0.128/27
10.0.0.128 10.0.0.129 10.0.0.130 10.0.0.131 10.0.0.132 10.0.0.133 10.0.0.134 10.0.0.135 10.0.0.136 10.0.0.137 10.0.0.138 10.0.0.139 10.0.0.140 10.0.0.141 10.0.0.142 10.0.0.143 10.0.0.144 10.0.0.145 10.0.0.146 10.0.0.147 10.0.0.148 10.0.0.149 10.0.0.150 10.0.0.151 10.0.0.152 10.0.0.153 10.0.0.154 10.0.0.155 10.0.0.156 10.0.0.157 10.0.0.158 10.0.0.159
Run Code Online (Sandbox Code Playgroud)
计算/ 23网络中的正确地址数:
$ prips 10.0.0.0/23 | wc -w
512
Run Code Online (Sandbox Code Playgroud)
使用cut检查其中一些地址:
$ prips 10.0.0.0/23 | cut -f1-10,256-266 -d' '
10.0.0.0 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4 10.0.0.5 10.0.0.6 10.0.0.7 10.0.0.8 10.0.0.9 10.0.0.255 10.0.1.0 10.0.1.1 10.0.1.2 10.0.1.3 10.0.1.4 10.0.1.5 10.0.1.6 10.0.1.7 10.0.1.8 10.0.1.9
Run Code Online (Sandbox Code Playgroud)
可能速度太慢,但也无法在/ 8网络中正确生成1600万个地址:
$ date ; prips 10.0.0.0/8 | wc -w ; date
Sat May 20 18:06:00 AEST 2017
16777216
Sat May 20 18:06:41 AEST 2017
Run Code Online (Sandbox Code Playgroud)
小智 7
这个脚本应该可以。它(几乎)是纯粹的 Bash。seq如果需要完全纯粹的 bash,可以更换该部分。
由于 Bash 显然使用带符号的二补码 4 字节整数,因此该脚本限制为 /8 掩码最大值。我发现大于 /16 的范围无论如何都是不切实际的,所以这根本不会困扰我。如果有人知道克服这个问题的简单方法,请分享:)
#!/usr/bin/env bash
BASE_IP=${1%/*}
IP_CIDR=${1#*/}
if [ ${IP_CIDR} -lt 8 ]; then
echo "Max range is /8."
exit
fi
IP_MASK=$((0xFFFFFFFF << (32 - ${IP_CIDR})))
IFS=. read a b c d <<<${BASE_IP}
ip=$((($b << 16) + ($c << 8) + $d))
ipstart=$((${ip} & ${IP_MASK}))
ipend=$(((${ipstart} | ~${IP_MASK}) & 0x7FFFFFFF))
seq ${ipstart} ${ipend} | while read i; do
echo $a.$((($i & 0xFF0000) >> 16)).$((($i & 0xFF00) >> 8)).$(($i & 0x00FF))
done
Run Code Online (Sandbox Code Playgroud)
用法:
./script.sh 192.168.13.55/22
Run Code Online (Sandbox Code Playgroud)
使用 Bash 版本 4.4.23 进行测试。YMMV。
小智 2
我认为我编写的这个小脚本可以达到目的。如果没有,这绝对是一个起点!祝你好运。
#!/bin/bash
############################
## Methods
############################
prefix_to_bit_netmask() {
prefix=$1;
shift=$(( 32 - prefix ));
bitmask=""
for (( i=0; i < 32; i++ )); do
num=0
if [ $i -lt $prefix ]; then
num=1
fi
space=
if [ $(( i % 8 )) -eq 0 ]; then
space=" ";
fi
bitmask="${bitmask}${space}${num}"
done
echo $bitmask
}
bit_netmask_to_wildcard_netmask() {
bitmask=$1;
wildcard_mask=
for octet in $bitmask; do
wildcard_mask="${wildcard_mask} $(( 255 - 2#$octet ))"
done
echo $wildcard_mask;
}
#######################
## MAIN
#######################
for ip in $@; do
net=$(echo $ip | cut -d '/' -f 1);
prefix=$(echo $ip | cut -d '/' -f 2);
bit_netmask=$(prefix_to_bit_netmask $prefix);
wildcard_mask=$(bit_netmask_to_wildcard_netmask "$bit_netmask");
str=
for (( i = 1; i <= 4; i++ )); do
range=$(echo $net | cut -d '.' -f $i)
mask_octet=$(echo $wildcard_mask | cut -d ' ' -f $i)
if [ $mask_octet -gt 0 ]; then
range="{0..$mask_octet}";
fi
str="${str} $range"
done
ips=$(echo $str | sed "s, ,\\.,g"); ## replace spaces with periods, a join...
eval echo $ips | tr ' ' '\012'
done
Run Code Online (Sandbox Code Playgroud)