REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR

5951 ワード

ecshopのlibを見てbase.phpのときにクライアントの実際のipの関数(real_ip)を取得すると、主にクライアントがエージェントを使用するかどうかを判断する場合が多く、判断順序に注意して、まずクライアントがエージェントHTTP_を使用するかどうかを判断するX_FORWARDED_FOR
やはりソースを添付しましょう
/**

 *        IP  

 *

 * @access  public

 * @return  string

 */

function real_ip()

{

    static $realip = NULL;



    if ($realip !== NULL)

    {

        return $realip;

    }



    if (isset($_SERVER))

    {

        if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))

        {

            $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);



            /*  X-Forwarded-For     unknown   IP    */

            foreach ($arr AS $ip)

            {

                $ip = trim($ip);



                if ($ip != 'unknown')

                {

                    $realip = $ip;



                    break;

                }

            }

        }

        elseif (isset($_SERVER['HTTP_CLIENT_IP']))

        {

            $realip = $_SERVER['HTTP_CLIENT_IP'];

        }

        else

        {

            if (isset($_SERVER['REMOTE_ADDR']))

            {

                $realip = $_SERVER['REMOTE_ADDR'];

            }

            else

            {

                $realip = '0.0.0.0';

            }

        }

    }

    else

    {

        if (getenv('HTTP_X_FORWARDED_FOR'))

        {

            $realip = getenv('HTTP_X_FORWARDED_FOR');

        }

        elseif (getenv('HTTP_CLIENT_IP'))

        {

            $realip = getenv('HTTP_CLIENT_IP');

        }

        else

        {

            $realip = getenv('REMOTE_ADDR');

        }

    }



    preg_match("/[\d\.]{7,15}/", $realip, $onlineip);

    $realip = !empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0';



    return $realip;

}


ちなみに$SERVERとgetenvの違い、getenvはIISのisapi方式で実行されるphpをサポートしていません
一、プロキシサーバーを使用していない場合:
 
      REMOTE_ADDR=IP      HTTP_VIA=数値なしまたは非表示      HTTP_X_FORWARDED_FOR=数値なしまたは非表示
二、透明プロキシサーバーを使用する場合:Transparent Proxies
      REMOTE_ADDR=最後のプロキシサーバIP      HTTP_VIA=プロキシサーバIP      HTTP_X_FORWARDED_FOR=実際のIPは、複数のプロキシサーバを通過した場合、この値は次のようになります.203.98.182.163、203.98.182.163、203.129.72.215です.
  このようなエージェント・サーバは、アクセス・オブジェクトに情報を転送しても、実際のアイデンティティを隠すことはできません.
三、一般匿名プロキシサーバーを使用する場合:Anonymous Proxies
      REMOTE_ADDR=最後のプロキシサーバIP      HTTP_VIA=プロキシサーバIP      HTTP_X_FORWARDED_FOR=プロキシサーバIPであり、複数のプロキシサーバを通過した場合、この値は、203.98.182.163、203.98.182.163、203.129.72.215と同様である.
  実際のIPは非表示ですが、プロキシ・サーバを使用してアクセスしていることがアクセス・オブジェクトに明らかになりました.
四、欺瞞エージェントサーバーを使用する場合:Distorting Proxies
      REMOTE_ADDR=プロキシサーバIP      HTTP_VIA=プロキシサーバIP      HTTP_X_FORWARDED_FOR=ランダムなIPであり、複数のプロキシサーバを通過した場合、この値は、203.98.182.163、203.98.182.163、203.129.72.215と同様である.
  アクセス先にエージェントサーバを使用していることを伝えましたが、実際のIPの代わりに虚偽のランダムIPを作成しました.
五、高匿名エージェントサーバーを使用する場合:High Anonymity Proxies(Elite proxies)
      REMOTE_ADDR=プロキシサーバIP      HTTP_VIA=数値なしまたは非表示      HTTP_X_FORWARDED_FOR=数値がない、または表示されない場合、複数のプロキシサーバを通過した場合、この値は次のようになります:203.98.182.163、203.98.182.163、203.129.72.215.
  すべての情報をプロキシサーバの情報に置き換え、そのプロキシサーバを完全に使用してオブジェクトに直接アクセスするようにします.
REMOTE_ADDRはあなたのクライアントがあなたのサーバーと「握手」したときのIPです.「匿名エージェント」を使用している場合、REMOTE_ADDRには、プロキシサーバのIPが表示されます.HTTP_CLIENT_IPはプロキシサーバが送信するHTTPヘッダである.スーパー匿名エージェントの場合はnone値を返します.同様に、REMOTE_ADDRもこのプロキシサーバのIPに置き換えられます.$SERVER['REMOTE_ADDR'];//アクセス側IP$SERVER['HTTP_CLIENT_IP']; //エージェント側(存在可能、偽造可能)$SERVER['HTTP_X_FORWARDED_FOR'];//ユーザがどのIPで使用するエージェントであるか(存在する可能性もあり偽造も可能)
 
----------------------------------------------------------------------------------------------------
WEB開発では.クライアントのIPアドレス:C#コードを取得するために次のコードを使用することに慣れているかもしれません.
 
   
// IP
string IP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(IP)) {
// IP IP
IP = Request.ServerVariables["REMOTE_ADDR"];
}

上のコードは正常に见えます.残念ながらここには隠れた危険が隠されています!!「HTTP_X_FORWARDED_FOR」という値は、HTTPヘッダの「X_FORWARDED_FOR」属性を取得することによって取得されるので、ここでは悪意のある破壊者にIPアドレスを偽造することができる方法を提供する!!次はテストコードです.
 
   
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://localhost/ip.aspx");
request.Headers.Add("X_FORWARDED_FOR", "0.0.0.0");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader stream = new StreamReader(response.GetResponseStream());
string IP = stream.ReadToEnd();
stream.Close();
response.Close();
request = null;

「ip.aspx」ファイルコード:
 
   
Response.Clear();
// IP
string IP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(IP))
{
// IP IP
IP = Request.ServerVariables["REMOTE_ADDR"];
}
Response.Write(IP);
Response.End();

このように.テストコードの中でip.aspxファイルにアクセスする时.“string IP=stream.ReadToEnd();”このコードの取ったIPデータは“0.0.0.0”!!!(ふふ.実际に.このようなIPアドレスは私たちが望んだ结果ではないに违いない.ある投票システムでは1つのIPに1回しか投票できないことを制限している场合もあるが,同じコードで相手のIPを取得して判断すると.ふふ.制限は失効するだろう).
 
あるいは、上のコードでIPアドレスを取得してからデータ判断をしないと、さらにデータ破壊を行うことができるかもしれません!!例えば、上記のようなコードでIPアドレスを取得すると、string sql=「INSERT INTO(IP)VALUE('++IP+')」;では、破壊者はSQL注入でデータ破壊もできるかもしれません!!
このように「HTTP_X_FOrWARDED_FOR」という属性を利用してクライアントIPを取得する方法はもはや望ましくない.しかし、この方法を使わないと、本当にプロキシサーバーを使用している人たちは、彼らの実際のIPアドレスを取得することはできません(一部のプロキシサーバーは「X_FOrWARDED_FOR」というHTTPヘッダにアクセスユーザーの本当のIPアドレスを加えるからです).ああ、現実的には、あるものには必ず損失があります...
------------------------------------------------------------------------------------------------------
この2つの投稿を見て、やっとipを取得した後にその正則を検証しなければならない理由が分かりました.私の以前のように直接REMOTEを通過しました.ADDRはクライアントipを取得し、検証を一斉に行わないという考えは馬鹿で無邪気で、厳しく打撃を与えなければならない.