【发布时间】:2021-01-08 11:33:21
【问题描述】:
在我的公司,我们开发了一种网络产品,其作用类似于嗅探器。
为了捕获所有 IPV4 数据包,我们遵循下一个过程:
- 创建一个原始套接字(确切代码:
new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Udp); - 将其绑定到网络接口的IPV4地址,端口0(确切代码:
socket.Bind(new IPEndPoint(address, 0));) - 如果我们在 Windows 上,请将套接字设置为混杂模式(确切代码:
socket.IOControl(IOControlCode.ReceiveAll, new byte[]{ 1, 0, 0, 0 }, null);
这就是我们从网络接口捕获所有 IPV4 数据包所需的一切。其余的是循环内的简单读取操作。在 Windows 上,该进程必须以管理员权限执行。
现在,我们还想支持 IPV6。这应该很容易,但我们无法想出一个可行的解决方案。即使没有抛出异常,套接字仍然“卡”在读取操作上。那里从来没有收到任何东西。
为了捕获IPV6数据包,我们对上面的程序稍作修改
- 使用
Socket(AddressFamily.InterNetworkV6, SocketType.Raw, ProtocolType.IPv6)创建一个套接字(注意:使用ProtocolType.Udp也无济于事) - 绑定到链接本地地址(例如:
socket.Bind(new IPEndPoint(IPAddress.Parse("fe80::dd37:936f:d87:b70c"), 0));)。注意:添加范围 ID(如fe80::dd37:936f:d87:b70c%9)也无济于事。 - 在 Windows 上,将套接字设置为混杂模式,就像 IPV4 过程一样。
我尝试过的另一件事:
- 通过在 (1) 和 (2) 之间调用
socket.DualMode = true;将套接字设置为双模式。 - 通过在 (1) 和 (2) 之间调用
socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);来禁用套接字上的仅 IPV6 选项。
我通过打开 Chrome 进行测试 - Chrome 会为 IPV6 和 IPV4 触发一个 MDNS 数据包,以实现其 chrome-cast 功能。 Wireshark(使用内核驱动程序)看到这个数据包并正确显示它。我的代码没有解除对读取操作的阻塞。
我使用支持 IPV6 的 Windows 10。
如何从网络接口读取所有 IPV6 数据包(如 IPV4)? 谢谢。
【问题讨论】:
-
收听 IPAddress.IPv6Any : IPEndPoint(IPAddress.IPv6Any, 0));)。
-
没有帮助。它使第 3 步抛出异常,如果我注释掉第 3 步,它仍然会卡在阅读中。
-
@jdweng 这不适用于 Windows 中的原始套接字。
-
IOControl 有效值显示在以下页面上:referencesource.microsoft.com/#System/net/System/Net/Sockets/… 和referencesource.microsoft.com/#System/net/System/Net/Sockets/… 0x80000000 似乎不是有效值(新字节[]{ 1, 0, 0, 0 }) .
-
不要把window和net库搞混了。 windows 套接字可与任何类型的套接字一起使用。托管的 c# 库对有效的套接字类型非常有限。看起来 c# 对原始套接字没有任何支持。所以你的问题真的是原始套接字而不是 IPV6。 Microsoft 决定在 Net Library 中创建自己的套接字类,而不是使用 Windows 类作为套接字。因此,将 windows dll 用于套接字将起作用。请参阅:pinvoke.net/default.aspx/ws2_32.SendTo
标签: c# sockets networking .net-core ipv6