2011-11-13 41 views
17

到目前爲止,我有這樣的代碼:如何判斷一個IP地址是否私密?

NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces(); 

foreach (NetworkInterface adapter in adapters) 
{ 
    IPInterfaceProperties properties = adapter.GetIPProperties(); 

    foreach (IPAddressInformation uniCast in properties.UnicastAddresses) 
    { 

    // Ignore loop-back addresses & IPv6 
    if (!IPAddress.IsLoopback(uniCast.Address) && 
     uniCast.Address.AddressFamily!= AddressFamily.InterNetworkV6) 
     Addresses.Add(uniCast.Address); 
    } 
} 

我怎樣才能篩選私有IP地址呢?以同樣的方式我篩選環回IP地址。

回答

33

更詳細的迴應是在這裏:

private bool _IsPrivate(string ipAddress) 
{ 
    int[] ipParts = ipAddress.Split(new String[] { "." }, StringSplitOptions.RemoveEmptyEntries) 
          .Select(s => int.Parse(s)).ToArray(); 
    // in private ip range 
    if (ipParts[0] == 10 || 
     (ipParts[0] == 192 && ipParts[1] == 168) || 
     (ipParts[0] == 172 && (ipParts[1] >= 16 && ipParts[1] <= 31))) { 
     return true; 
    } 

    // IP Address is probably public. 
    // This doesn't catch some VPN ranges like OpenVPN and Hamachi. 
    return false; 
} 
13

專用地址範圍在RFC1918中定義。它們是:

  • 10.0.0.0 - 10.255.255.255(10/8前綴)
  • 172.16.0.0 - 172.31.255.255(172.16/12前綴)
  • 192.168.0.0 - 192.168.255.255(192.168/16前綴)

您可能還想過濾掉在RFC3927中定義的鏈接本地地址(169.254/16)。

4
10.0.0.0  - 10.255.255.255 (10/8 prefix) 
172.16.0.0  - 172.31.255.255 (172.16/12 prefix) 
192.168.0.0  - 192.168.255.255 (192.168/16 prefix) 

使用RFC中定義的範圍(由Anders建議);比使用正則表達式來檢測/刪除列表中的私有IP地址。

以下是用於檢測私有IP地址的RegEx示例。 (我沒測試過)

(^127\.0\.0\.1)| 
(^10\.)| 
(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)| 
(^192\.168\.) 
+2

可能更容易轉換爲uint32,然後使用按位運算:'((地址&0xFF000000U)== 0x0A000000U)|| ...'。如果有很多地址檢查它也應該更快。 – Richard

+1

我懷疑這會起作用,但是如果小整數在正確的範圍內,則regexps在概念上是測試的錯誤工具。比較數字比匹配字符串更有效率。 – Anthony

+0

將當前IP轉換爲數字表示,然後查看它是否適合該類別中的任何一個(僅使用數字比較)。它對我來說非常合適。 – Edi

4

最好做這將是一個擴展方法的IP地址類

/// <summary> 
    /// An extension method to determine if an IP address is internal, as specified in RFC1918 
    /// </summary> 
    /// <param name="toTest">The IP address that will be tested</param> 
    /// <returns>Returns true if the IP is internal, false if it is external</returns> 
    public static bool IsInternal(this IPAddress toTest) 
    { 
     byte[] bytes = toTest.GetAddressBytes(); 
     switch(bytes[ 0 ]) 
     { 
      case 10: 
       return true; 
      case 172: 
       return bytes[ 1 ] < 32 && bytes[ 1 ] >= 16; 
      case 192: 
       return bytes[ 1 ] == 168; 
      default: 
       return false; 
     } 
    } 

然後,可以在IP地址類的實例上調用該方法

bool isIpInternal = ipAddressInformation.Address.IsInternal(); 
3

增加了IPv6和localhost情況。

/* An IP should be considered as internal when: 

     ::1   - IPv6 loopback 
     10.0.0.0  - 10.255.255.255 (10/8 prefix) 
     127.0.0.0 - 127.255.255.255 (127/8 prefix) 
     172.16.0.0 - 172.31.255.255 (172.16/12 prefix) 
     192.168.0.0 - 192.168.255.255 (192.168/16 prefix) 
    */ 
    public bool IsInternal(string testIp) 
    { 
     if(testIp == "::1") return true; 

     byte[] ip = IPAddress.Parse(testIp).GetAddressBytes(); 
     switch (ip[0]) 
     { 
      case 10: 
      case 127: 
       return true; 
      case 172: 
       return ip[1] >= 16 && ip[1] < 32; 
      case 192: 
       return ip[1] == 168; 
      default: 
       return false; 
     } 
    } 
相關問題