2016-02-12 68 views
2

我想確定一個給定的IPv6地址是否是私有的或不是在C#中,我試圖簡單地在IPAddress類上使用'IsIPv6SiteLocal'屬性。但是,如本comment中所解釋的,此屬性中實現的邏輯已被棄用。我跑了以下的單元測試:如何判斷IPv6地址是否私密?

[TestMethod] 
public void IsPrivate_ipv6_True() 
{ 
    // This sample private IPv6 address was generated using: http://unique-local-ipv6.com/ 
    var ip = IPAddress.Parse("fd44:fda4:e1ba::1"); 
    Assert.IsTrue(ip.IsIPv6SiteLocal); 
} 

在單元測試斷言失敗這證實了IsIPv6SiteLocal不正確地確定某個地址是本地的。所以我需要一個替代方案。

我寫了下面的擴展方法,我想知道是否有人可以想到一個場景,它不會正確地確定該地址是私人/公共。

public static bool IsPrivateIPv6(this IPAddress address) 
{ 
    var addressAsString = address.ToString(); 
    var firstWord = addressAsString.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries)[0]; 

    // Make sure we are dealing with an IPv6 address 
    if (address.AddressFamily != AddressFamily.InterNetworkV6) return false; 

    // The original IPv6 Site Local addresses (fec0::/10) are deprecated. Unfortunately IsIPv6SiteLocal only checks for the original deprecated version: 
    else if (address.IsIPv6SiteLocal) return true; 

    // These days Unique Local Addresses (ULA) are used in place of Site Local. 
    // ULA has two variants: 
    //  fc00::/8 is not defined yet, but might be used in the future for internal-use addresses that are registered in a central place (ULA Central). 
    //  fd00::/8 is in use and does not have to registered anywhere. 
    else if (firstWord.Substring(0, 2) == "fc" && firstWord.Length >= 4) return true; 
    else if (firstWord.Substring(0, 2) == "fd" && firstWord.Length >= 4) return true; 

    // Link local addresses (prefixed with fe80) are not routable 
    else if (firstWord == "fe80") return true; 

    // Discard Prefix 
    else if (firstWord == "100") return true; 

    // Any other IP address is not Unique Local Address (ULA) 
    else return false; 
} 

EDITED 2016年2月13日

  • 確保第一個字是長至少4個字符由@RonMaupin的建議
  • 改進評論上述 '否則返回false' 爲由@RonMaupin建議
  • 檢查'fe80'前綴,如@KevinBurdett建議的
  • 檢查'Discard'前綴,如@KevinBurdett建議的
+1

你還在檢查已棄用區塊的原因是什麼?它自2004年以來已被棄用。此外'fc'仍未定義,您只需檢查'fd'。您可以在這裏找到更多信息。 https://en.wikipedia.org/wiki/Unique_local_address – Will

+2

看起來像[XY問題](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。爲什麼你認爲你需要知道IPv6地址是否是唯一的本地地址與全局地址?你會如何使用這些信息?您發佈的代碼是否存在_specific_問題?你有沒有具體的問題陳述?如上所述,你的問題是非常廣泛的(「任何人都可以想到任何東西嗎?」) –

+0

@對'fd ::'(保留)之類的東西的簡單檢查'fd'將會失敗。添加一個檢查,看看第一個單詞是否有四位數字會使這個更正確。 –

回答

0

這是我最後使用的代碼,到目前爲止,它似乎打算工作:

public static bool IsPrivateIPv6(this IPAddress address) 
{ 
    var addressAsString = address.ToString(); 
    var firstWord = addressAsString.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries)[0]; 

    // Make sure we are dealing with an IPv6 address 
    if (address.AddressFamily != AddressFamily.InterNetworkV6) return false; 

    // The original IPv6 Site Local addresses (fec0::/10) are deprecated. Unfortunately IsIPv6SiteLocal only checks for the original deprecated version: 
    else if (address.IsIPv6SiteLocal) return true; 

    // These days Unique Local Addresses (ULA) are used in place of Site Local. 
    // ULA has two variants: 
    //  fc00::/8 is not defined yet, but might be used in the future for internal-use addresses that are registered in a central place (ULA Central). 
    //  fd00::/8 is in use and does not have to registered anywhere. 
    else if (firstWord.Substring(0, 2) == "fc" && firstWord.Length >= 4) return true; 
    else if (firstWord.Substring(0, 2) == "fd" && firstWord.Length >= 4) return true; 

    // Link local addresses (prefixed with fe80) are not routable 
    else if (firstWord == "fe80") return true; 

    // Discard Prefix 
    else if (firstWord == "100") return true; 

    // Any other IP address is not Unique Local Address (ULA) 
    else return false; 
} 
1

雖然不是特別優雅......我真的不能想到什麼更好:)

但是,我還要檢查鏈路本地地址,用fe80:前綴。它們不可路由,但如果您直接從接口拉IP,則當沒有其他IPv6地址存在時,它仍然可以報告本地鏈路。

關於IPv6的維基百科文章(https://en.wikipedia.org/wiki/Reserved_IP_addresses#IPv6)也顯示100:作爲丟棄前綴。根據你想要完成的事情,你可能也想要檢查這些。

+0

除了所有的保留地址範圍和特殊地址範圍外,全局地址範圍中還有一些非Internet路由的地址範圍。組播在Internet上也不可路由。由於ULA範圍在本地可路由,因此我認爲該問題涉及無法在Internet上路由的地址。 –

+0

一個合理的假設,但仍然是一個假設:)更多信息永遠不會傷害 –

+0

@KevinBurdett我根據您的反饋改進了我的代碼 – desautelsj

2
加入了特殊情況下 ::1,避免從他解決一個ArgumentException

改進@ desautelsj的回答(這將發生在Substring()調用):

public static bool IsPrivateIPv6(IPAddress address) 
{ 
    // Make sure we are dealing with an IPv6 address 
    if (address.AddressFamily != AddressFamily.InterNetworkV6) 
     throw new ArgumentException("IP address is not V6", "address"); 

    var addressAsString = address.ToString(); 
    var firstWord = addressAsString.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries)[0]; 

    // equivalent of 127.0.0.1 in IPv6 
    if (addressAsString == "::1") 
     return true; 

    // The original IPv6 Site Local addresses (fec0::/10) are deprecated. Unfortunately IsIPv6SiteLocal only checks for the original deprecated version: 
    else if (address.IsIPv6SiteLocal) 
     return true; 

    // These days Unique Local Addresses (ULA) are used in place of Site Local. 
    // ULA has two variants: 
    //  fc00::/8 is not defined yet, but might be used in the future for internal-use addresses that are registered in a central place (ULA Central). 
    //  fd00::/8 is in use and does not have to registered anywhere. 
    else if (firstWord.Length >= 4 && firstWord.Substring(0, 2) == "fc") 
     return true; 
    else if (firstWord.Length >= 4 && firstWord.Substring(0, 2) == "fd") 
     return true; 

    // Link local addresses (prefixed with fe80) are not routable 
    else if (firstWord == "fe80") 
     return true; 

    // Discard Prefix 
    else if (firstWord == "100") 
     return true; 

    // Any other IP address is not Unique Local Address (ULA) 
    return false; 
} 

而在F#:

let private IsIpv6AddressPrivate (address: IPAddress) = 
    if (address.AddressFamily = AddressFamily.InterNetwork) then 
     invalidArg "address" "address must be IPv6" 

    // The original IPv6 Site Local addresses (fec0::/10) are deprecated. Unfortunately IsIPv6SiteLocal only checks for the original deprecated version: 
    else if (address.IsIPv6SiteLocal) then 
     true 
    else 
     let addressAsString = address.ToString() 

     // equivalent of 127.0.0.1 in IPv6 
     if (addressAsString = "::1") then 
      true 
     else 
      let firstWord = addressAsString.Split([|':'|], StringSplitOptions.RemoveEmptyEntries).[0] 
      // These days Unique Local Addresses (ULA) are used in place of Site Local. 
      // ULA has two variants: 
      //  fc00::/8 is not defined yet, but might be used in the future for internal-use addresses that are registered in a central place (ULA Central). 
      //  fd00::/8 is in use and does not have to registered anywhere. 
      if (firstWord.Length >= 4 && firstWord.Substring(0, 2) = "fc") || 
       (firstWord.Length >= 4 && firstWord.Substring(0, 2) = "fd") || 
       // Link local addresses (prefixed with fe80) are not routable 
       (firstWord = "fe80") || 
       // Discard Prefix 
       (firstWord = "100") then 
       true 
      else 
       false