tohokuaikiのチラシの裏

技術的ネタとか。

PHPでアクセスしてきたIPアドレスがプライベートアドレスかをチェックする

プライベートIPは以下の範囲で

10.0.0.0~10.255.255.255
172.16.0.0~172.31.255.255
192.168.0.0~192.168.255.255

PHPip2longをかませると

167772160~184549375
2886729728~2887778303
3232235520~3232301055

なので、こんな感じで。

<?php
function isPrivateAddress($ip = null)
{
    is_null($ip) and $ip = $_SERVER['REMOTE_ADDR'];
    
    $iplong = ip2long($ip);
    $iplong = sprintf('%u', $iplong); // for 32bit architecture
    
    return ($iplong >= 167772160 && $iplong <=184549375) ||
           ($iplong >= 2886729728 && $iplong <=2887778303) ||
           ($iplong >= 3232235520 && $iplong <=3232301055) ;
}

テスト

<?php
$testips=<<<EOF
10.0.0.0
10.0.0.1
10.0.1.1
10.255.255.254
10.255.255.255
11.0.0.1
172.15.234.1
172.16.0.0
172.16.0.1
172.31.255.254
172.31.255.255
172.32.0.1
191.255.255.255
192.168.0.0
192.168.0.1
192.168.255.254
192.168.255.255
193.0.0.1
EOF;

foreach (explode("\n", $testips) as $ip){
    $ip = trim($ip);
    $long = ip2long($ip);
    printf("%s\t(%u)\t=>\t%s\n",
           $ip, $long,
           isPrivateAddress($ip) ? 'private' : 'global');
}

10.0.0.0        (167772160)     =>      private
10.0.0.1        (167772161)     =>      private
10.0.1.1        (167772417)     =>      private
10.255.255.254  (184549374)     =>      private
10.255.255.255  (184549375)     =>      private
11.0.0.1        (184549377)     =>      global
172.15.234.1    (2886724097)    =>      global
172.16.0.0      (2886729728)    =>      private
172.16.0.1      (2886729729)    =>      private
172.31.255.254  (2887778302)    =>      private
172.31.255.255  (2887778303)    =>      private
172.32.0.1      (2887778305)    =>      global
191.255.255.255 (3221225471)    =>      global
192.168.0.0     (3232235520)    =>      private
192.168.0.1     (3232235521)    =>      private
192.168.255.254 (3232301054)    =>      private
192.168.255.255 (3232301055)    =>      private
193.0.0.1       (3238002689)    =>      global