PHPでIPv6プレフィックス付きの正規表現を作成する

まずはじめに伝えたいことは、IPv6アドレスの正規表現を独自作成とかQiitaの内容をコピペとかはやめた方がいいです。
必ず、バグが混在してしまいます。
今回の投稿では、IPv6アドレスの正規表現に加え、/1〜/128を末尾につけた状態のIPv6アドレスを許可するための正規表現をPHPで作成する方法についてまとめました。

  • IPv6の正規表現は作成せず、PHPのfirter_var関数を使用する
  • プレフィックスの正規表現を作成する

上記の流れになります。
Qiitaなどで上がっている正規表現に対し、テストデータをぶっこむと、弾かないといけないIP弾けていないというデータが大量にありましたので、基本的に使用しない方が良いと思われます。
ですので、IPv6アドレスの形式に沿っているかどうかについては、PHPのfilter_var関数を使用します。
filter_var関数は、PHPのフレームワークであるLaravelの”ip”、”ipv6″のバリデーションでも使用されているものですので、これを使用するのがベストでしょう。
ただ、プレフィックス付きのアドレスに関しては弾いてしまうので、こちらを今回対応できるようにします。

IPv6の正規表現は作成せず、PHPのfirter_var関数を使用する。

if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
    echo 'IPv6アドレスの形式です';
} else {
    echo 'IPv6アドレスの形式に沿っていません。';
}

上記でIPv6アドレスの形式かどうか確認ができます。FILTER_FLAG_IPV6をFILTER_FLAG_IPV4に変えればIPv4アドレスを確認できます。第3引数のフラグを渡さなかった場合はIPv4もしくはIPv6の形式かをチェックしてくれます。とても優秀です。
詳細はマニュアルを参考に。
http://php.net/manual/ja/filter.filters.flags.php
また、テストIPv6のテストデータは下記のサイトから取ってきました。Qiitaなどであがってる正規表現にこれをぶっこむと残念な結果になりますが、PHPの関数使えばちゃんと想定通りの結果が返ってきます。当たり前ですが。
http://home.deds.nl/~aeron/regex/
こちらで用意されている正規表現ならテストもしてますし信頼できそうな気もしますが、PHPはありませんでした。

IPv6のプレフィックスの正規表現を作成する

function isIpv6PrefixAddress($ip) {
    // /1 ~ /128 であることを確認
    $prefixRegex = '/^(\/[1-9]|\/[1-9][0-9]|\/1[0-1][0-9]|\/12[0-8])?$/';

    $prefix = mb_strstr($ip, '/') !== false ? mb_strstr($ip, '/') : '';
    $ip = mb_strstr($ip, '/', true) !== false ? mb_strstr($ip, '/', true) : $ip;

    return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false && preg_match($prefixRegex, $prefix) === 1;
}⏎

僕の場合はこんな感じで関数を作りました。スラッシュがあった場合、スラッシュ以降の文字列が1〜128であることを確認する正規表現です。IPv6アドレス形式のチェックはfilter_var関数を使用して、プレフィックス部分だけ正規表現で確認をするというやり方です。これであればIPv6の正規表現の信頼性を確保しつつ、IPv6のプレフィックスにも対応ができます。

最後に

検証はしていますが、最終的には自分で検証をお願いします。責任は取れないのであくまで参考に。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

ABOUTこの記事をかいた人

山中 雅彦

大分でWebシステム受託開発会社のバックエンドエンジニアとして働いてます。 Laravel5でのシステム開発を中心に仕事してます。 高校卒業後に鉄鋼会社で電気整備の仕事をする傍ら、HTML、CSS、JS、PHP、MySQL、サーバ関連技術を独学で勉強。 2017年9月にWebシステム開発会社に入社し、システム開発をしています。 Web技術全般が好きなPHPerです。