APNICのIPアドレス一覧から日本のIPv4アドレスを抜き出してtcprules形式で出力するphpスクリプト

以前はAPNICのIPアドレス一覧から日本のIPv4アドレスを抜き出して、tcprules形式に整形したものを公開していた方がいらしたのですが、気が付いたらサイトにアクセスできなくなっていました(他人の褌で相撲を取っていた訳です)。
以下のリストは、CIDR形式やサブネットマスク形式でのデータ整形方法が載っているサイトになります。
- 世界の国別 IPv4 アドレス割り当てリスト
- 自前の国別IPv6、IPv4アドレス割当リストを作成しよう | OXY NOTES
- wiki/listup-ip-cidr.md at master · hfm/wiki · GitHub
- 日本国内限定IPv4アクセス制限の仕込み方 - てくにかるむ // multix.jp
自分が欲しいのはtcpserverで使えるtcprules形式ですが、探してもマイナー過ぎて見つかりません。「無いものは作るしかない」ということで、同じようなデータを出力するphpスクリプトを作成してみました。
<?php
define("URL", "http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-extended-latest");
if (($handle = fopen(URL, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 100, "|")) !== FALSE) {
if ($data[ 0 ] == 'apnic' && $data[ 1 ] == 'JP' && $data[ 2 ] == 'ipv4') {
$ip_s = $data[ 3 ];
$count = $data[ 4 ] - 1;
$long = ip2long($ip_s);
if ($long == -1 || $long === FALSE) continue;
$long += $count;
$ip_e = long2ip($long);
$array_ip_s = explode(".", $ip_s);
$array_ip_e = explode(".", $ip_e);
$cdb = array();
for ($i = 0; $i <= 3; $i++) {
if ($array_ip_s[ $i ] == $array_ip_e[ $i ]) {
$cdb[ $i ] = $array_ip_s[ $i ];
} elseif ($array_ip_s[ $i ] == 0 && $array_ip_e[ $i ] == 255) {
break;
} else {
$cdb[ $i ] = sprintf("%s-%s", $array_ip_s[ $i ], $array_ip_e[ $i ]);
}
}
$cdb = implode(".", $cdb);
echo $cdb . ".:allow" . "\n";
}
}
fclose($handle);
}
?>
開始IPアドレスをip2long関数で数値化し、それにIPアドレスの数-1したものを足し、その数値をlong2ip関数を使って終了IPアドレスを求め、各オクテット毎に開始と終了の数値を比較してリストを作成する...ということをやっています。もうちょっとスマートなコードを書ける方法があるとは思うのですが...。
インターネットに接続できる環境で、スクリプトを実行すると以下のようなデータを出力します。
1.0.16-31.:allow
1.0.64-127.:allow
1.1.64-127.:allow
1.5.:allow
1.21.:allow
1.33.:allow
1.66-67.:allow
...
出力されるリストの行末にある"allow"を"deny"に変えると、拒否リストを作成することが出来ます。日本からの接続を拒否するケースはあまり考えられませんが...。
とりあえずCentOS Linux release 7.7.1908上のPHP 7.3.13 (cli) (built: Dec 17 2019 10:29:15) ( NTS )の環境下で実行した限りでは意図したとおりに動作しました。エラー処理は最小限しか入っていないので、適宜組み込んでください。