C#取真實IP地址及分析

來源:互聯網
上載者:User

  1. 說一哈,我也是轉來的,不是想騙PV,方便自己查而已!

    目前網上流行的所謂"取真實IP地址"的方法,都有bug,沒有考慮到多層透明代理的情況。
    多數代碼類似:

    string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]!=null
    && HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] !=String.Empty)
    ?HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]
    :HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

    事實上,上面的代碼只試用與使用者只使用了1層代理,如果使用者有2層,3層HTTP_X_FORWARDED_FOR 的值是:"本機真實IP,1層代理IP,2層代理IP,....." ,如果這個時候你的資料中儲存IP欄位的長度很小(15個位元組),資料庫就報錯了。

    實際應用中,因為使用多層透明代理的情況比較少,所以這種使用者並不多。

    其他應用情況,現在越來越多的網站使用了代理加速方式,比如 新浪、SOHU的新聞 都使用Squid做代理方式,利用多台伺服器分流。Squid本身類似透明代理,會發送"HTTP_X_FORWARDED_FOR" ,HTTP_X_FORWARDED_FOR 中包括客戶的IP地址,如果此時客戶已經使用了一層透明代理,那麼程式取的 "HTTP_X_FORWARDED_FOR" 就包括兩個IP地址。(我遇到過3個IP地址的情況,4個的未遇到過)

    所以取"真正"IP地址的方式,還應該判斷 "HTTP_X_FORWARDED_FOR" 中是否有","逗號,或者長度是否超長(超過15位元組 xxx.xxx.xxx.xxx)。

    所以代碼應該如下: > 純文字方式> 拷貝到裁剪板> 列印

    1. /**//// <summary>    
    2. /// 取得用戶端真實IP。如果有代理則取第一個非內網地址    
    3. /// </summary>    
    4. public static string IPAddress    
    5. {    
    6.     get    
    7.     {    
    8.         string result = String.Empty;    
    9.         result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];    
    10.         if(result!=null&&result!= String.Empty)    
    11.         {    
    12.             //可能有代理    
    13.             if(result.IndexOf(".")==-1)    //沒有"."肯定是非IPv4格式    
    14.                 result = null;    
    15.             else    
    16.             {    
    17.                 if(result.IndexOf(",")!=-1)    
    18.                 {    
    19.                     //有",",估計多個代理。取第一個不是內網的IP。    
    20.                     result = result.Replace(" ","").Replace(""","");    
    21.                     string[] temparyip = result.Split(",;".ToCharArray());    
    22.                     for(int i=0;i<temparyip.Length;i++)    
    23.                     {    
    24.                         if( Text.IsIPAddress(temparyip[i])    
    25.                             && temparyip[i].Substring(0,3)!="10."    
    26.                             && temparyip[i].Substring(0,7)!="192.168"    
    27.                             && temparyip[i].Substring(0,7)!="172.16.")    
    28.                         {    
    29.                             return temparyip[i];    //找到不是內網的地址    
    30.                         }    
    31.                     }    
    32.                 }    
    33.                 else if(Text.IsIPAddress(result)) //代理即是IP格式    
    34.                     return result;    
    35.                 else    
    36.                     result = null;    //代理中的內容 非IP,取IP    
    37.             }    
    38.         }    
    39.         string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]!=null && HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] !=String.Empty)?HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]:HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];    
    40.          if (null == result || result == String.Empty)    
    41.             result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];    
    42.         if (result == null || result == String.Empty)    
    43.             result = HttpContext.Current.Request.UserHostAddress;    
    44.         return result;    
    45.     }    
    46. }    

    /**//// <summary><br />/// 取得用戶端真實IP。如果有代理則取第一個非內網地址<br />/// </summary><br />public static string IPAddress<br />{<br />get<br />{<br />string result = String.Empty;<br />result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];<br />if(result!=null&&result!= String.Empty)<br />{<br />//可能有代理<br />if(result.IndexOf(".")==-1) //沒有"."肯定是非IPv4格式<br />result = null;<br />else<br />{<br />if(result.IndexOf(",")!=-1)<br />{<br />//有",",估計多個代理。取第一個不是內網的IP。<br />result = result.Replace(" ","").Replace(""","");<br />string[] temparyip = result.Split(",;".ToCharArray());<br />for(int i=0;i<temparyip.Length;i++)<br />{<br />if( Text.IsIPAddress(temparyip[i])<br />&& temparyip[i].Substring(0,3)!="10."<br />&& temparyip[i].Substring(0,7)!="192.168"<br />&& temparyip[i].Substring(0,7)!="172.16.")<br />{<br />return temparyip[i]; //找到不是內網的地址<br />}<br />}<br />}<br />else if(Text.IsIPAddress(result)) //代理即是IP格式<br />return result;<br />else<br />result = null; //代理中的內容 非IP,取IP<br />}<br />}<br />string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]!=null && HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] !=String.Empty)?HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]:HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];<br />if (null == result || result == String.Empty)<br />result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];<br />if (result == null || result == String.Empty)<br />result = HttpContext.Current.Request.UserHostAddress;<br />return result;<br />}<br />}<br />
    取"HTTP_X_FORWARDED_FOR" 的弊端。

    HTTP_X_FORWARDED_FOR 是HTTP協議中頭的一部分,不影響TCP的通訊。也就是說實際上用戶端可以發送任意內容的 HTTP_X_FORWARDED_FOR,以就是偽造IP。最簡單的是WEB程式的IP記錄,本來是要記錄真實IP的,反而被"駭客"欺騙。當你的應用程式記錄客戶的訪問IP、拒絕或允許部分IP的訪問、錯誤記錄檔 都會出錯,甚至誤殺。

    因此必要的安全日誌應該記錄 完整的 "HTTP_X_FORWARDED_FOR" (至少給資料庫中的欄位分配 3*15+2 個位元組,以記錄至少3個IP) 和 "REMOTE_ADDR"。對 HTTP_X_FORWARDED_FOR 的IP格式檢查也是不可少的。

    附:(Text是我自訂的一個類,IsIPAddress是其中的一個判斷是否是IP地址格式的方法)

    > 純文字方式> 拷貝到裁剪板> 列印

    1. #region bool IsIPAddress(str1) 判斷是否是IP格式    
    2. /**//// <summary>   
    3. /// 判斷是否是IP地址格式 0.0.0.0   
    4. /// </summary>   
    5. /// <param name="str1">待判斷的IP地址</param>   
    6. /// <returns>true or false</returns>   
    7. public static bool IsIPAddress(string str1)   
    8. {   
    9.     if(str1==null||str1==string.Empty||str1.Length<7||str1.Length>15) return false;    
    10.     string regformat = @"^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$";   
    11.     Regex regex = new Regex(regformat,RegexOptions.IgnoreCase );   
    12.     return regex.IsMatch(str1);   
    13. }  
    14. #endregion  

      

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.