如何判断IPv6地址是否私有?

des*_*lsj 6 c# ipv6

我试图确定给定的 IPv6 地址在 C# 中是否是私有的,并且我很想简单地使用 IPAddress 类上的“IsIPv6SiteLocal”属性。但是,正如此评论中所解释的,此属性中实现的逻辑已被弃用。我运行了以下单元测试:

[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);
}
Run Code Online (Sandbox Code Playgroud)

单元测试中的断言失败,这确认 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;
}
Run Code Online (Sandbox Code Playgroud)

2016 年 2 月 13 日编辑

  • 确保第一个单词的长度至少为 4 个字符(按照@RonMaupin 的建议)
  • 按照 @RonMaupin 的建议改进了“else return false”上面的评论
  • 检查 @KevinBurdett 建议的“fe80”前缀
  • 按照@KevinBurdett的建议检查“丢弃”前缀

des*_*lsj 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;
}
Run Code Online (Sandbox Code Playgroud)