2013/10/02
国別フィルタの自動生成ツール
bsdhack.org ドメインは FreeBSD でサーバを構築しているのだが、
特定の国からのアタックや迷惑メイルが非常に多いので
ipfw (8) によるフィルタリングを利用して
指定した国からのパケットを拒否する設定を自動生成するツールを作成した。
APNIC から IPアドレスの割当リストを取得して、
IPアドレスを CIDR 型式に修正した上で
ipfw (8) のコマンドラインパラメタを自動生成している。
スクリプトは FreeBSD の ipfw (8) 向けだが、
出力部分を適宜修正する事で Linux の iptables (8) 向けの
設定も出力可能だと思う。
1#!/usr/bin/perl 2use Socket; 3 4# IP アドレス割当リスト取得 URL 5$url = "http://ftp.apnic.net/stats/apnic/delegated-apnic-latest"; 6 7# FreeBSD の ipfw (8) のルール番号 8if(@ARGV < 1){ 9 $rule = 2000; 10} 11else{ 12 $rule = $ARGV[0]; 13} 14 15# 拒否対象の国コード 16@country = ('KR', 'CN'); 17 18foreach $i (@country){ 19 $country{$i} = 1; 20} 21 22if(open(IN, "fetch -q -o - $url|")){ 23 # 拒否対象の国の場合は IP アドレスを保存 24 while(<IN>){ 25 if(/^apnic\|(..)\|ipv4\|(\d+.\d+.\d+.\d)\|(\d+)/){ 26 if($country{$1}){ 27 $table{inet_aton($2)} = $3; 28 } 29 } 30 } 31 close(IN); 32 33 # 取得した IP 割当リストから開始アドレスと個数を取得 34 foreach $net (sort keys %table){ 35 $addr = unpack('N', $net); 36 $num = $table{$net}; 37 while($num == $num[0] && ($addr ^ $addr[0]) == $num){ 38 shift @addr; 39 shift @num; 40 $addr &= ~$num; 41 $num <<= 1; 42 } 43 unshift(@addr, $addr); 44 unshift(@num, $num); 45 } 46 47 # IP アドレスと個数を CIDR 型式に変換して出力 48 while (@addr){ 49 for($num = pop(@num), $mask = 32; $num > 1; $num >>= 1, $mask--){} 50 $filt = inet_ntoa(pack('N', pop(@addr))) . "/$mask"; 51 # FreeBSD の ipfw(8) 向け出力 52 print "\${fwcmd} add $rule deny ip from $filt to any in recv \${wan}\n"; 53 # Linux の iptables(8) 向け出力 54 # print "\${iptables} -A INPUT -s $filt -j DROP\n"; 55 $rule++; 56 } 57} 58 590;
FreeBSD の場合は WAN 側のインタフェイス名が '${wan}' 変数に、 iptables コマンドの実行ファイル名が '${ipfw}' 変数に それぞれ格納されている事を前提としたスクリプトになっているので、 利用する際は適宜変更しながら使って下さい。