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

以前はAPNICのIPアドレス一覧から日本のIPv4アドレスを抜き出して、tcprules形式に整形したものを公開していた方がいらしたのですが、気が付いたらサイトにアクセスできなくなっていました(他人の褌で相撲を取っていた訳です)。

以下のリストは、CIDR形式やサブネットマスク形式でのデータ整形方法が載っているサイトになります。

自分が欲しいのは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 )の環境下で実行した限りでは意図したとおりに動作しました。エラー処理は最小限しか入っていないので、適宜組み込んでください。