|
~ To be, or not to be, or to ask someone to be. ~ null-i.net |
| Linux/複数IPを1サブネットにまとめる | |
|
複数のIPアドレスをサブネットへまとめる(2017-03-05) 不正アクセス元を調べると似たようなアドレスがあって # cat ip_list.txt xxx.185.200.218 xxx.185.200.215 xxx.185.200.254 (以下省略) 以下、ツールに渡すと1まとめにします。 # ./make_subnet.pl ip_list.txt | sort xxx.185.200.192/26 #xxx.185.200.218,xxx.185.200.215,xxx.185.200.254 xxx.13.32.185/32 #xxx.13.32.185 xxx.8.37.129/32 #xxx.8.37.129 一行目のように、3つのアドレスを1つのマスクで集約してます。 # cat make_subnet.pl
#!/usr/bin/perl -w
# デバッグ文、作成過程では入れまくってます。
sub dbg_printf{
return; # ここをコメントアウト
printf STDOUT "dbg:";
printf STDOUT @_ ;
$|=1;
}
# 現状はIPv4だけ、
# IPv6は必要になったら考えます
my @subnets = (0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff );
# 0000, 1000, 1100, 1110 という具合にマスクを増やしていく
# とりあえず、/26bit ~ /32bit の範囲でマスクする
my $file;
if($ARGV[0] eq '-') { $file = 'STDIN';}
else{ open($file, "< $ARGV[0]") or die "$! [$ARGV[0]]\n";}
my %sub_ip;
my %sub_mask;
while(<$file>){
if(/^(\d+\.\d+\.\d+\.\d+)/){
$ip=$1;
if($ip =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/){
$bin=$1*256*256*256
+$2*256*256
+$3*256
+$4; # IP表記から数値に戻す
$sub_ip{$bin} = $ip;
$sub_mask{$bin} = 0xffffffff;
}
}
}
my %aa;
my %bb;
my %new_ip;
my %new_mask;
my $is_loop=1;
# 重複するサブネットをさらに集約する
while($is_loop){
%aa = %bb = %sub_ip;
%new_ip=();
%new_mask=();
$is_loop=0;
foreach my $a (keys(%aa)){
my $is_merge=0;
foreach my $b (keys(%bb)){
if($a == $b)
{
next;
}
for($i=$#subnets; $i>=0; $i--){
my $mask = $subnets[$i];
if($sub_mask{$a} <= $mask){
next;
}
if(($a & $mask) == ($b & $mask)){
dbg_printf("%s and %s masked 0x%x\n", $sub_ip{$a}, $sub_ip{$b}, $mask);
my $n = $a & $mask;
# 内訳 IPリストを再構成する
my @hosts = (split(/,/, $sub_ip{$a}), split(/,/, $sub_ip{$b}));
if(defined $new_ip{$n}){
# 既存IPリスト, サブネットを上書きしないようにする
@hosts = (@hosts, split(/,/, $new_ip{$n}));
if($new_mask{$n} < $mask){ $mask = $new_mask{$n}; }
}
# perldoc -q duplicate より、重複排除
my %uniq = map { $_, 1 } @hosts;
$new_ip{$n} = join(",", keys %uniq);
$new_mask{$n} = $mask;
$is_loop++;
$is_merge++;
last;
}
}
}
if($is_merge==0){
$new_ip{$a} = $sub_ip{$a};
$new_mask{$a} = $sub_mask{$a};
}
}
%sub_ip = %new_ip;
%sub_mask = %new_mask;
}
foreach my $key (keys(%sub_ip)){
$key &= $sub_mask{$key};
my $ip = sprintf("%d.%d.%d.%d",
$key /(256*256*256),
$key /(256*256)%256,
$key /256%256,
$key %256
);
my $bip=0; # サブネット数。2の何乗かをビット演算。
for($p=$sub_mask{$key}; $p%2==0; $p>>=1){$bip++;}
printf("%16s/%d #%s\n", $ip, 32-$bip, $sub_ip{$key} );
}
・・・現時点ではこれが精いっぱい。長い。 複数アドレスをどこまで集約するか(何bitでフィルタするか)は |
|