2016-02-12 95 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 
相关问题