IP地址是否与本地计算机位于同一子网上(支持IPv6)

Spe*_*ort 5 .net c# ipv6 subnet

有没有人有一些代码可以确定IP地址(IPv4或IPv6)是否与运行应用程序的计算机位于同一子网上?我已经看过很多用IPv4做的代码示例,但我找不到任何支持IPv6的代码.

编辑:

我不确定我是否理解v4和v6之间的所有差异,所以这里有一点我的问题.我有一个为Internet客户端和Intranet客户端提供服务的应用程序,也就是说有些客户端与服务器位于同一物理网络上.所以有时客户端之间有路由器,有时候没有路由器.使用IPv4,我可以通过检查服务器IP地址和子网的客户端IP地址来确定这一点,这样如果我的服务器的IP和子网掩码分别是:

192.168.123.15 255.255.255.0

并且服务器从192.168.123.100接收客户端请求我知道客户端和服务器之间没有路由器.但是,如果服务器收到来自192.168.1.100或67.7.23.4的客户端请求,我知道这些客户端和服务器之间存在路由器.在.Net中,我可以收集客户端和服务器IP地址(v4和v6)但我找不到IPv6子网掩码.

有没有办法在.Net中收集这些信息,还是我误解了IPv4和IPv6之间有什么区别?

编辑x2:

我在MS连接站点上发布了这个,看看它们是否正在处理,或者是否有原因他们没有向UnicastIPAddressInformation类添加IPv6Mask属性.

https://connect.microsoft.com/VisualStudio/feedback/details/643031/unicastipaddressinformation-class-has-no-ipv6mask-property

我也在同一时间在MSDN论坛上发布了同样的问题.1800多个观点,而不是一个回复.猜猜我不是唯一一个对此感到好奇的人.

http://social.msdn.microsoft.com/Forums/en-US/netfxnetcom/thread/dd30e161-9be5-4d70-97c0-22e2756ce953

mpo*_*llo 3

框架似乎没有办法做到这一点。最准确的方法是进行路由查找,但我没有看到在 C# 中执行此操作的好方法。(在 Linux 下,我会这样做/sbin/ip -6 route get <ipv6-addr>并查看返回哪个路由。)您必须找到一个本机调用才能在 Windows 中执行此操作;我没有看到命令行应用程序。

最好的方法可能是解析netsh interface ipv6 show route verbose. 您可以查找任何非 /128 前缀并对这些前缀进行最长前缀匹配。(好吧,如果你点击 /128,那就是分配给该盒子的地址)

您还可以检查邻居表。( netsh interface ipv6 show neighbors),但如果您最近没有与该主持人交谈过,则该条目可能不包含您要查找的条目。

您需要考虑的其他潜在问题:

  • 链路本地地址 (fe80::/10)(以及多播、环回和未指定 - 表中的所有内容)
  • 事实上,在 IPv6 中,分配的地址并不意味着在线前缀。前缀表是单独的。目前尚不清楚如何在 Windows 下对此进行测试,但netsh interface ipv6 show siteprefixes可能会有所帮助。看来 Windows 实际上可能会比标准预期更像 IPv4。

编辑:听起来检查邻居表将是您执行此操作阻力最小的路径;如果您接受来自 Intranet 的连接,然后转身检查邻居表,您可以合理地确信,如果邻居是本地的,它将存在于表中。如果您检查邻居表,请注意仅查看 LAN 接口的邻居表。(许多 Windows 系统上默认安装的 ISATAP 接口将整个IPv4 互联网公开为链路本地“子网”。)

同样,IPv6 地址没有“网络掩码”的概念,因为链路上前缀表与地址分配是分开的。然而,如果您有一台服务器位于某处,您可以 99% 确定它位于/64上。(尽管你必须小心;如果它本身是一个隧道端点,有时我会看到为 6in4 隧道分配了更长的前缀)所以一个快速而肮脏的算法是:

  • 忽略前 64 位为 0 的所有地址(本地环回)
  • 忽略与 ff00::/8 匹配的所有地址(多播)
  • 如果地址与 fe80::/10 匹配,则它是接口本地。请小心这一点,因为如果您启用了 ISATAP 接口,“本地链路”意味着“自动隧道到整个 IPv4 互联网”!(不好。)因此,最好不要信任链接本地地址,除非您确定它们来自 LAN 接口。(它们无法被路由)
  • (现在是复杂的部分)判断该地址是否是邻居。(邻居查找)黑客解决方案是检查系统上配置的所有 IPv6 地址(通过无状态地址自动配置、DHCPv6 或静态地址自动配置,如果您可以确定)并检查前 64 位。在服务器上(假设没有使用非 /64 前缀配置时髦的隧道),在极少数情况下这将是一个错误,因为 - 再次 - 你无法确定该地址是否真的在链接上,除非你检查 on-链接前缀表。(Windows 没有这个概念;它似乎存储在路由表中。)大多数可配置为在以太网接口上发送路由器通告的网络设备将始终通告 /64 前缀。如果您可以检查数据包是否来自 LAN 接口,则这更不可能是一个错误。

编辑2

我已经编写了一些代码来解析 IPv6 路由表并将其发布在这里。它还没有解决这个问题中提出的难题,但这是朝着正确方向迈出的一步。