日本に割り当てられたIPアドレス以外は拒否する

あるサーバーで海外からの不正アクセスが多い為、WEB管理画面へのアクセスを日本以外からの
アクセスを全て拒否して欲しいという依頼があり、とりあえずIPアドレスの国別割り当てを
以下5つの組織から取得。

IPアドレス割り当て範囲取得URL
‘APNIC’ => ‘ftp://ftp.apnic.net/pub/stats/apnic/delegated-apnic-latest’,
‘ARIN’ => ‘ftp://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest’,
‘RIPE’ => ‘ftp://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-latest’,
‘LACNIC’ => ‘ftp://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-latest’,
‘AFRINIC’ => ‘ftp://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-latest’

LINUXサーバーなので、httpサーバーアプリケーションではなくその手前でiptablesを
使ってコネクションを拒否する設定を組み込んだ。
iptables の更新は一日一回行う。【root権限】

なお、今回の設定はIPv4でIPv6には対応しない。

iptables の設定ファイルは,CIDR表記で記述するので取得したJPのIPアドレス範囲を
CIDR表記に変換する。

例えば以下のようなレコードがあり、
———————————————————
apnic|JP|ipv4|61.192.0.0|524288|20010531|allocated
———————————————————
61.192.0.0 から 524288個のIPアドレスという情報になっている。

これをPHPで、変換してみる。

$ipstart = ip2long('61.192.0.0');
$num = 524288;

/*
* 以下は無駄な計算ですが念の為
* (単に$numをデクリメントすれば良いけど)
*/
$ipend = $ipstart + $num - 1;
$num = $ipend - $ipstart;
//で、$num が 524287 になる。

/*
* 2進数表記に変換
* (2進数の最上位桁数が何桁目なのかを得る為)
*/
$num_decbin_str = decbin($num);

/*
* 32bitから桁数分を引いた値が、CIDRになる。
*/
$cidr_num = 32 - strlen($num_decbin_str);
$cidr_format = long2ip((float)$ipstart) . '/' . $cidr_num;

//結果を出力してみる。
echo $cidr_format;
echo "\n";
exit(0);

この計算方法が一番良いのかは検証していないが、
サイダー表記にしようとした場合に、だらだらと書き出したソースである。

なんか、もう少しスマートな良い計算方法がある気がするけど、
まあ、とりあえず間違ってはいないので、これで処理。