~ To be, or not to be, or to run away far away! ~ 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でフィルタするか)は |
|