【ASP.NET開発】クライアントIPアドレスvia Cを取得

12332 ワード

説明:本文の内容は私がブログ園の博文とMSDN討論区の資料を総合して、更に自分の実際のテストを通じて得て、自分のオリジナルの内容に属して正直に言うと少なくて、この1編を書くのは自分がプロジェクトの中でしたことを記録するためで、同時にレンガを投げて玉を引きたいです.参考にした博文とその著者は以下に言及する.自分の後でHTTP、TCP/IPなどの知識に対して深く学んで、きっとまたここに来てこの内容を深く討論します.
 
一、名詞
まず、次にお話しする名詞についてお話しします.
Web開発では、HTTPリクエストヘッダのいくつかの属性を使用してクライアントのIPアドレスを取得することに慣れています.一般的な属性はREMOTE_です.ADDR、HTTP_VIAとHTTP_X_FORWARDED_FOR.
この3つの属性の意味は、多分そうです:(ネットから抜粋して、指摘を歓迎します)
  REMOTE_ADDR:この属性の値は、クライアントがサーバと握手したときのIPです.「匿名エージェント」を使用している場合、REMOTE_ADDRには、プロキシサーバのIPが表示されます.
X-Forwarded-For:HTTPエージェントまたは負荷等化方式でWebサーバに接続されているクライアントの最も元のIPアドレスを識別するためのHTTP要求ヘッダフィールドである.
XFFの有効性は、プロキシサーバが提供する接続元のIPアドレスの真実性に依存するため、XFFの有効な使用は、プロキシサーバが信頼できることを保証すべきであり、例えば、信頼できるサーバのホワイトリストを確立することによってもよい.
このHTTPヘッダの一般的なフォーマットは以下の通りです.
  X-Forwarded-For: client1, proxy1, proxy2
その中の値はカンマ+スペースを通じて、複数のIPアドレスを区切って、一番左(client 1)は最も原始的なクライアントのIPアドレスで、エージェントサーバーは成功して1つの要求を受け取って、要求のソースのIPアドレスを右側に追加します.上記の例では、このリクエストはproxy 1、proxy 2、proxy 3の3つのエージェントサーバを正常に通過しました.リクエストはclient 1によって発行され、proxy 3に到達した(proxy 3はリクエストの終点である可能性がある).リクエストがクライアント1から送信されたばかりの場合、XFFは空であり、リクエストはproxy 1に送信される.Proxy 1を通過すると、client 1がXFFに追加され、その後proxy 2に要求が送られる.Proxy 2を通過すると、proxy 1がXFFに追加され、その後proxy 3に要求が送られる.Proxy 3を通過すると、proxy 2がXFFに追加され、その後のリクエストの行方が不明となり、proxy 3がリクエスト終点でなければリクエストは転送され続ける.
このフィールドの偽造は容易であるため、X-Forwarded-Forフィールドは慎重に使用するべきである.通常、XFFの最後のIPアドレスは最後のプロキシサーバのIPアドレスであり、これは通常、より信頼できる情報源である.
(別添ウィキペディアにおけるX-Forwarded-Forの完全な紹介:http://zh.wikipedia.org/wiki/X-Forwarded-For)
 
これらの属性を使用する場合、属性の値は何なのかについては、ネット上でユーザIPアドレスの3つの属性の違いを取得する(原作者不明)というブログが見つかった.
  
一方、ASP.NETでは、RequestオブジェクトのUserHostAddressプロパティを介してクライアントのIPアドレスを別の方法で取得することもできる.MSDN Libraryでは、この属性は、属性値がリモートクライアントのIPアドレスであると解釈される.
クライアントがプロキシサーバを使用している場合、Request.UserHostAddressプロパティはプロキシサーバのIPアドレスを取得します.
 
二、方法
では、そんなに多くの概念的なことを話して、実現の方法を話しましょう.
ネット上の多くの方法の構想は:もしエージェントIPがあるならば、優先的にエージェントIPを取得して、さもなくば接続クライアントのIPを取得します;あるいは、転送して、まず接続クライアントのIPを取得し、取得に失敗した場合、エージェントのIPを取得します.
以下の方法は、ブログasp.netクライアントIP取得を参照してください. (著者comeonfyz)
-----------------------------------------------------------------------------------------------------------
/// <summary>

///      IP  

/// </summary>

/// <returns>          </returns>

public static string GetIP()

{

    //             ,   HTTP_X_FORWARDED_FOR     IP  

    string userHostAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString().Split(',')[0].Trim();

    //      REMOTE_ADDR     IP  

    if (string.IsNullOrEmpty(userHostAddress))

    {

        userHostAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

    }

    //      ,   Request.UserHostAddress    IP  ,        IP    IP    IP

    if (string.IsNullOrEmpty(userHostAddress))

    {

        userHostAddress = HttpContext.Current.Request.UserHostAddress;

    }

    //          ,   IP     (         )

    if (!string.IsNullOrEmpty(userHostAddress) && IsIP(userHostAddress))

    {

        return userHostAddress;

    }

    return "127.0.0.1";

}



/// <summary>

///   IP    

/// </summary>

/// <param name="ip"></param>

/// <returns></returns>

public static bool IsIP(string ip)

{

    return System.Text.RegularExpressions.Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");

}

-----------------------------------------------------------------------------------------------------------
しかし、このようにするには深刻な欠陥があります.それは大牛Kingthyが博文しているようなものです.  HTTP_の使用X_FORWARDED_FORがクライアントIPを取得する重大な結果    で説明したように、「HTTP_X_FOrWARDED_FOR」という値は、HTTPヘッダの「X_FOrWARDED_FOR」属性を取得することによって取得され、悪意のある破壊者は簡単にIPアドレスを偽造することができる.さらに、上述したように、XFFの有効性は、プロキシサーバが提供する接続元のIPアドレスの真実性に依存するため、XFFの有効な使用はプロキシサーバが信頼できることを保証すべきである.しかし,開発者としては,ユーザのIPアドレスの真実性を知らないだけでなく,プロキシサーバの信頼性を見分けることも困難である.
だから、各方面の资料を総合して、私の个人的な考えは大牛Kingthyと同じです:代理を无视します.
-----------------------------------------------------------------------------------------------------------
 1     /// <summary>

 2     ///      IP  (    )  3     /// </summary>

 4     /// <returns>          </returns>

 5     public static string GetHostAddress()  6  {  7         string userHostAddress = HttpContext.Current.Request.UserHostAddress;  8 

 9         if (string.IsNullOrEmpty(userHostAddress)) 10  { 11             userHostAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; 12  } 13 

14         //          ,   IP     (         )

15         if (!string.IsNullOrEmpty(userHostAddress) && IsIP(userHostAddress)) 16  { 17             return userHostAddress; 18  } 19         return "127.0.0.1"; 20  } 21 

22     /// <summary>

23     ///   IP     24     /// </summary>

25     /// <param name="ip"></param>

26     /// <returns></returns>

27     public static bool IsIP(string ip) 28  { 29         return System.Text.RegularExpressions.Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$"); 30     }

-----------------------------------------------------------------------------------------------------------
三、まとめ
エージェントサーバを無視するのは最善の解決策ではありません.プロジェクトのニーズがクライアントの実際のアドレスを明確に言う場合は、エージェントサーバを無視することはできません.
また、私もArtech大牛にこの方面の問題を教えてもらったことがあります.彼はこれらについて深く研究していませんが、TCP/IPプロトコル自体が決定したので、IP取得方法は完全に信頼できるものではないと思っています.
Artech大牛からもらった資料を添付して、共有してください.http://www.symantec.com/connect/articles/ip-spoofing-introduction
この博文がレンガを投げて玉を引くことができることを望んで、批判と提案を歓迎します.