「アクセス解析」や「掲示板の投稿ログ」など、アクセスしてきた回線つまりIPアドレスを保存するという処理があります。


単に環境変数「REMOTE_HOST」等を保存するだけではプロクシ経由の場合意味がありません。(多分)


掲示板が特定の人物に荒らされた場合には保存してあるログを参考にすることで、うまくいけばアクセス制限できることもあります。


インターネット経由でアクセスしてくる機器には必ずグローバルなIPアドレスが必要になります。
そのIPアドレスは固定のものもあれば、ネット接続時に動的に割り振られるもの、アクセスする度に変わるものなどいろいろあります。
ホスト名は人間が覚えやすいようにIPアドレスに対応づけしてるだけのものなのでホスト名がなくてもIPアドレスだけでアクセスはできます。


つまりホスト名とIPアドレスではIPアドレスのほうがより重要な情報という風になりそうですが、人間ですから認識しやすいホスト名の方に注目する場合が多いように思います。



ということでここからはリアルなIPアドレス(生IP)をできるだけ取得する方法を書いていきたいと思います。



■IPアドレスを取得する
<?php

function realaddr()
{
    $ip= array();
    if (isset($_SERVER['HTTP_SP_HOST']) && preg_match('/^\d+(?:\.\d+){3}$/D', $_SERVER['HTTP_SP_HOST']))
        $ip[]= $_SERVER['HTTP_SP_HOST'];
    if (isset($_SERVER['HTTP_VIA']) && preg_match('/.*\s(\d+(?:\.\d+){3})/', $_SERVER['HTTP_VIA'], $match))
        $ip[]= $match[1];
    if (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^\d+(?:\.\d+){3}/', $_SERVER['HTTP_CLIENT_IP'], $match))
        $ip[]= $match[0];
    if (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})/i', $_SERVER['HTTP_CLIENT_IP'], $match))
        $ip[]= implode('.', array(hexdec($match[1]), hexdec($match[2]), hexdec($match[3]), hexdec($match[4])));
    if (isset($_SERVER['HTTP_FORWARDED']) && preg_match('/.*\s(\d+(?:\.\d+){3})/', $_SERVER['HTTP_FORWARDED'], $match))
        $ip[]= $match[1];
    if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match('/^\d+(?:\.\d+){3}/', $_SERVER['HTTP_X_FORWARDED_FOR'], $match))
        $ip[]= $match[0];
    if (isset($_SERVER['HTTP_FROM']) && preg_match('/^\d+(?:\.\d+){3}$/D', $_SERVER['HTTP_FROM']))
        $ip[]= $_SERVER['HTTP_FROM'];


    $addr= '';
    foreach ($ip as $value)
        if (!preg_match('/^(?:10|172\.16|192\.168|127\.0|0\.|169\.254)\./', $value) and $addr=$value) break;


    return($addr ? $addr : $_SERVER['REMOTE_ADDR']);
}
?>


プロクシ経由特有の環境変数を見ていき、生IPの形跡があればそれを取得していきます。
できれば信頼度の高いものから順にセットしていき、条件に見合っているかどうかチェックするようにします。
プロクシの残す環境変数から取得できない場合にはREMOTE_ADDR値をIPアドレスとしています。


IPアドレスを取得したら次はこれをホスト名に変換(いわゆる逆引き)します。
PHPではgethostbyaddr()関数にIPアドレスをそのまま渡すだけでこれができます。



■逆引き関数
<?php

function realhost($addr="")
{
    if ($addr === "") return '';
    $host= gethostbyaddr($addr);
    if (empty($host)) $host= $_SERVER['REMOTE_HOST'];


    return($host ? $host : $addr);
}
?>


先に書いたrealaddr()を引数として渡せばホスト名を返してくれることになります。
echo realhost(realaddr());



こうやって取得した、IPアドレスも絶対ではありません。あくまでもできるだけ取得できるように頑張ってみたまでです。


では簡易的なプロクシ判定関数も書いておきます。



■プロクシ判定関数
<?php

function is_proxy()
{
    return(
    isset($_SERVER['HTTP_SP_HOST']) or
    isset($_SERVER['HTTP_VIA']) or
    isset($_SERVER['HTTP_CLIENT_IP']) or
    isset($_SERVER['HTTP_FORWARDED']) or
    isset($_SERVER['HTTP_X_FORWARDED_FOR']) or
    isset($_SERVER['HTTP_FROM']) or
    preg_match('/via|squid|gate|httpd|proxy|cache|gateway|www|anonymous|keeper/i', $_SERVER['HTTP_USER_AGENT']) or
    preg_match('/prox|squid|gate|cache|news|web|www|secure|cgi|ftp|pop|dummy|keep|mail|mx\d*\b|smtp|dns|ns\d*\b|^gw|^fw|firewall/i', realhost())
    );
}
?>


realhost()関数を内部で使用してホスト名を簡易チェックしています。
とまぁ、、合法的に取得するのはこんなところかと・・・