web-dev-qa-db-fra.com

Script Bash pour lister toutes les IP par préfixe

J'essaie de créer un script permettant de saisir un ensemble de préfixes, qui répertoriera ensuite toutes les adresses IP contenues dans les préfixes (y compris réseau/hôte/diffusion). 

Un exemple serait:

./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

Certains scripts python/Perl peuvent le faire, mais j'espère avoir un script bash simple, car il peut être utilisé sur des systèmes sans Perl/python (oui… je sais…)

13
user2463938

Voici ce que j'utilise pour générer toutes les adresses IP dans un bloc CIDR donné

nmap -sL 10.10.64.0/27 | grep "Nmap scan report" | awk '{print $NF}'

Aussi simple que cela

La commande ci-dessus affiche cette

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
22
John Vossler

Moi aussi, je cherchais cette solution et j'ai constaté que le script @scherand fonctionnait très bien. J'ai également ajouté à ce script pour vous donner plus d'options. Fichier d'aide ci-dessous.

CET ÉCRIT DÉVELOPPEMENT UNECIDRADDRESS.

SYNOPSIS

./cidr-to-ip.sh [OPTION(only one)] [STRING/FILENAME]

LA DESCRIPTION

-h Affiche cet écran d'aide

-f Force une vérification des limites du réseau quand on leur donne une ou plusieurs chaînes.

-i lit un fichier d'entrée (le fichier doit contenir un CIDR par ligne) (pas de vérification des limites du réseau)

-b Fera la même chose que –i mais avec vérification des limites du réseau

EXEMPLES

./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 fichier_entrée.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
14
Kyoungs

Ce court script imprimera toutes les adresses IP d'une plage CIDR en quelques lignes de Bash. (Je l'ai nommée prips après la commande Ubuntu du même nom . Évidemment, si cette commande est disponible, utilisez-la.)

prips() {
  cidr=$1

  # range is bounded by network (-n) & broadcast (-b) addresses.
  lo=$(ipcalc -n $cidr | cut -f2 -d=)
  hi=$(ipcalc -b $cidr | cut -f2 -d=)

  read a b c d <<< $(echo $lo | tr . ' ')
  read e f g h <<< $(echo $hi | tr . ' ')

  eval "echo {$a..$e}.{$b..$f}.{$c..$g}.{$d..$h}"
}

Notez que je suppose que la version de ipcalc sous RedHat Linux (Erik Troan, Preston Brown) est différente de celle de Krischan Jodies installée sur certaines plates-formes (Mac OS X, par exemple).

Exemples:

$ 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

Calcule le nombre correct d'adresses dans un réseau/23:

$ prips 10.0.0.0/23 |wc -w 
512

Inspecter quelques-unes de ces adresses en utilisant 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

Et peut-être trop lentement, mais génère également correctement les 16 millions d'adresses dans un réseau/8:

$ 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
4
Alex Harvey

J'ai récemment écrit une fonction pour générer toutes les adresses IP à partir d'une adresse réseau donnée. La fonction prend l'adresse réseau en argument et accepte les masques CIDR et de sous-réseau. Le script stocke ensuite toutes les adresses IP dans la variable de tableau $ ips.

Code

function network_address_to_ips() {
  # define empty array to hold the ip addresses
  ips=()
  # create array containing network address and subnet
  network=(${1//\// })
  # split network address by dot
  iparr=(${network[0]//./ })
  # check for subnet mask or create subnet mask from CIDR notation
  if [[ ${network[1]} =~ '.' ]]; then
    netmaskarr=(${network[1]//./ })
  else
    if [[ $((8-${network[1]})) -gt 0 ]]; then
      netmaskarr=($((256-2**(8-${network[1]}))) 0 0 0)
    Elif  [[ $((16-${network[1]})) -gt 0 ]]; then
      netmaskarr=(255 $((256-2**(16-${network[1]}))) 0 0)
    Elif  [[ $((24-${network[1]})) -gt 0 ]]; then
      netmaskarr=(255 255 $((256-2**(24-${network[1]}))) 0)
    Elif [[ $((32-${network[1]})) -gt 0 ]]; then 
      netmaskarr=(255 255 255 $((256-2**(32-${network[1]}))))
    fi
  fi
  # correct wrong subnet masks (e.g. 240.192.255.0 to 255.255.255.0)
  [[ ${netmaskarr[2]} == 255 ]] && netmaskarr[1]=255
  [[ ${netmaskarr[1]} == 255 ]] && netmaskarr[0]=255
  # generate list of ip addresses
  for i in $(seq 0 $((255-${netmaskarr[0]}))); do
    for j in $(seq 0 $((255-${netmaskarr[1]}))); do
      for k in $(seq 0 $((255-${netmaskarr[2]}))); do
        for l in $(seq 1 $((255-${netmaskarr[3]}))); do
          ips+=( $(( $i+$(( ${iparr[0]}  & ${netmaskarr[0]})) ))"."$(( $j+$(( ${iparr[1]} & ${netmaskarr[1]})) ))"."$(($k+$(( ${iparr[2]} & ${netmaskarr[2]})) ))"."$(($l+$((${iparr[3]} & ${netmaskarr[3]})) )) )
        done
      done
    done
  done
}

Exemple

network_address_to_ips 10.0.1.0/255.255.255.240
echo ${ips[@]}
network_address_to_ips 10.1.0.0/24
echo ${ips[@]}
3
Florian Feldhaus

nmap est utile, mais excessif.

Vous pouvez utiliser prips à la place. Vous évite d'avoir à extraire la sortie supplémentaire de nmap et à utiliser awk.

Appeler prips 192.168.0.0/23 imprimera ce dont vous avez besoin. 

J'utilise les éléments suivants pour ignorer l'adresse réseau et la diffusion: prips "$subnet" | sed -e '1d; $d'

Les prips offrent également des options utiles, par exemple être en mesure de goûter chaque n-ème IP.

2
Jakub Bochenski

Je pense que ce petit script que j'ai piraté fait l'affaire. Sinon, c'est définitivement un point de départ! Bonne chance.

#!/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
2
rberg

Je voulais commenter une réponse ci-dessus mais je n'ai pas encore le représentant. 

En utilisant la solution supérieure avec NMAP, j'ai ajouté ceci à mon .bashrc

expand-ip() {
nmap -sL -n -iL "$1" | grep "Nmap scan report" | awk '{print $NF}'
}

Maintenant, je peux l'utiliser avec seulement expand-ip targs

2
Trevor Steen

J'ai prolongé un peu le script @Rberg.

  • vérifiez si le "réseau" que vous fournissez est vraiment un réseau (utilisez -f pour ignorer la vérification)
  • gérer les masques réseau supérieurs à /24

Peut-être que cela est utile pour quelqu'un.

#!/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 "f" force;
shift $(( OPTIND-1 ));

for ip in $@; 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 ]; 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 ' ' '\012'
    fi

done
1
scherand
fping -Aaqgr 1 10.1.1.0/24

La simplicité fonctionne mieux

0
George

Vous pouvez utiliser ce script 
(vous devez avoir "bc" installé sur votre système): 

for ip in $@ ;do
        net=$(echo $ip | cut -d '/' -f 1);
        prefix=$(echo $ip | cut -d '/' -f 2);
        o1=$(echo $net | cut -d '.' -f4);
        o2=$(echo $net | cut -d '.' -f3);
        o3=$(echo $net | cut -d '.' -f2);
        o4=$(echo $net | cut -d '.' -f1);
        len=$(echo "2^(32 - $prefix)"|bc);
        for i in `seq $len`;do
                echo "$o4.$o3.$o2.$o1";
                o1=$(echo "$o1+1"|bc);
                if [ $o1 -eq 256 ]; then
                        o1=0;
                        o2=$(echo "$o2+1"|bc);
                        if [ $o2 -eq 256 ]; then
                                o2=0;
                                o3=$(echo "$o3+1"|bc);
                                if [ $o3 -eq 256 ]; then
                                        o3=0;
                                        o4=$(echo "$o4+1"|bc);
                                fi
                        fi
                fi
        done
done
0
Alireza