![IP 목록을 고정 CIDR 형식으로 변환](https://linux55.com/image/196624/IP%20%EB%AA%A9%EB%A1%9D%EC%9D%84%20%EA%B3%A0%EC%A0%95%20CIDR%20%ED%98%95%EC%8B%9D%EC%9C%BC%EB%A1%9C%20%EB%B3%80%ED%99%98.png)
IP 목록을 고정 네트워크 CIDR 형식으로 변환할 수 있는 도구가 있습니까 x.x.x.0/24
? x.x.0.0/16
예를 들어 이를 입증하기 위해 다음과 같이 고정된 형식으로 변환될 수 있는 IP 목록이 있습니다.
먼저, 다음 IP 목록을 가능한 CIDR 24로 변환하고 싶지만 고정된 형식으로 변환하려는 경우 x.x.x.0/24
:
./list2cidr 24 iplist.txt
1.22.3.4
1.28.3.5
1.211.3.7
1.211.3.2
1.211.3.1
Output:
1.22.3.4
1.28.3.5
1.211.3.0/24
어떻게 작동하나요?
먼저, 동일한 네트워크에 있는 IP 목록을 스캔하고, 동일한 네트워크에 있는 경우 세 번째 옥텟을 살펴보고 이를 결합하여 x.x.x.0/24
. 이 예에서는 세 번째 옥텟에 동일한 네트워크를 가진 3개의 IP가 있습니다.
1.211.3.7
1.211.3.2
1.211.3.1
그래서 이것은 다음과 같습니다:1.211.3.0/24
또 다른 예를 들어, 다음 IP 목록을 가능한 CIDR 16으로 변환하려는 경우 고정 형식은 다음과 같습니다 x.x.0.0/16
.
./list2cidr 16 iplist.txt
1.1.4.1
1.1.4.2
1.22.44.1
1.22.3.2
1.22.1.9
Output:
1.1.0.0/16
1.22.0.0/16
이를 포함하는 매개변수를 전달하면 16
두 번째 옥텟이 동일한 네트워크에 있는지 확인하므로 이를 결합하여x.x.0.0/16
이에 대한 스크립트 작성을 시작해야 합니까? 아니면 이 목적을 위한 도구가 있나요?
편집하다:
CIDR 양식을 다음 중 하나와 같이 만들고 싶습니다. 1.1.1.0/24
및 1.1.0.0/16
. 그래서 1.1.0.0/24
아직은 1.1.1.0/16
내가 원하는 게 아니다.
이는 전달된 경우 list2cidr 24 iplist.txt
다음 출력을 형성해야 함 을 의미합니다.
x.x.x.0/24
통과하면 list2cidr 16 iplist.txt
다음 출력이 형성되어야 합니다.
x.x.0.0/16
현재 bash 스크립트를 사용하여 출력의 첫 번째 부분을 수행했지만 아직 완전히 테스트하지는 않았습니다.
답변1
저는 몰랐기 때문에 (Perl로) 하나 썼습니다. 나는 또한 당신의 도구 디자인이 불완전하다고 생각합니다.
- 주소가 하나만 있는 경우에도 요청된 수준의 CIDR 블록만 제공해야 합니다.
- 또한 목표 수준 없이도 작동해야 합니다.
그러므로:
$ cat sample
1.22.3.4
1.28.3.5
1.211.3.7
1.211.3.2
1.211.3.1
$ list2cidr 24 sample
1.22.3.0/24
1.28.3.0/24
1.211.3.0/24
$ list2cidr 16 sample
1.22.0.0/16
1.28.0.0/16
1.211.0.0/16
$ list2cidr sample
1.0.0.0/8
1.16.0.0/12
1.22.3.4
1.28.3.5
1.211.3.0/29
1.211.3.0/30
1.211.3.1
1.211.3.2
1.211.3.7
$
현재 구현에서는 IPv4만 지원합니다. 코드는 다음과 같습니다
#!/usr/bin/perl -w
use strict;
my $target;
if ($ARGV[0] =~ m{^\d+}) {
$target = + shift @ARGV;
}
my $map = [];
sub record($)
{
my $v = shift;
my $m = $map;
for my $i ( 0 .. 31 ) {
my $k = $v & (1 << (31-$i));
$m = $m->[!!$k] ||= (($i == 31) ? $v : []);
}
}
while (<>) {
chomp;
if (m{^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)\s*\z}) {
if (($1 < 256) && ($2 < 256) && ($3 < 256) && ($4 < 256)) {
record(($1<<24) | ($2<<16) | ($3 << 8) | $4);
next;
}
}
printf("Invalid: %s\n", $_);
}
sub output($$$) {
my ($addr, $bits, $indent) = @_;
printf "%*s%d.%d.%d.%d",
$indent*4, '',
0xff & ($addr >> 24),
0xff & ($addr >> 16),
0xff & ($addr >> 8),
0xff & ($addr );
printf("/%d", $bits) if $bits < 32;
print "\n";
}
sub walk($$$$);
sub walk($$$$) {
my ($prefix, $bits, $indent, $m) = @_;
#printf ("%d %d %d ...\n", $prefix, $bits, $indent);
if ($bits == ($target//-1)) {
output $prefix<<(32-$bits), $bits, 0;
} elsif ($bits == 32) {
warn 'mismatch '.$prefix.' != '.$m unless $prefix == $m;
output $prefix, $bits, $indent unless defined $target;
} elsif (defined $m->[0]) {
if (defined $m->[1]) {
output $prefix<<(32-$bits), $bits, $indent unless defined $target;
walk($prefix*2, $bits+1, $indent+1, $m->[0]);
walk($prefix*2+1, $bits+1, $indent+1, $m->[1]);
} else {
walk($prefix*2, $bits+1, $indent, $m->[0]);
}
} else {
if (defined $m->[1]) {
walk($prefix*2+1, $bits+1, $indent, $m->[1]);
} else {
warn sprintf('Empty node at prefix=%x bits=%d indent=%d', $prefix, $bits, $indent);
}
}
}
walk (0, 0, 0, $map);
답변2
다음은 명령줄 유틸리티를 사용합니다 ipcalc
(https://github.com/pyr/ipcalcfile
) 는 주어진 네트워크 마스크 라고 불리는 파일에 주어진 각 주소에 대한 네트워크 주소를 계산합니다 $mask
.
xargs -I {} ipcalc {} / "$mask" <file |
awk -F: '$1 ~ /^network/ && !seen[$2]++ { gsub(" ","",$2); print $2 }'
마지막으로 출력을 awk
구문 분석 하고 고유한 네트워크 주소를 추출합니다.ipcalc
예제 데이터가 주어지면 이것을 실행하면 mask=24
다음과 같습니다.
1.22.3.0/24
1.28.3.0/24
1.211.3.0/24
그리고 mask=12
:
1.16.0.0/12
1.208.0.0/12
약간의 수정을 통해 Ubuntu에서 ipcalc
이 패키지를 사용할 수 있습니다.ipcalc
xargs -I {} ipcalc -b {}/"$mask" <file |
awk -F: '$1 ~ /^Network/ && !seen[$2]++ { gsub(" ","",$2); print $2 }'