问题描述
在我公司中,我们开发了一种网络产品,其作用类似于嗅探器。
为了捕获所有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 },null);
这就是我们要从网络接口捕获所有IPV4数据包所需的一切。其余的是循环内的简单读取操作。在Windows上,必须以管理员权限执行该过程。
现在,我们还希望支持IPV6。本来很简单,但是我们无法提出一个可行的解决方案。即使没有异常抛出异常,套接字仍被“卡住”在读取操作中。那里什么也没收到。
为了捕获IPV6数据包,我们对上述过程做了一些修改
- 使用
Socket(AddressFamily.InterNetworkV6,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会为其Chromecast功能启用IPV6和IPV4的MDNS数据包。 Wireshark(使用内核驱动程序)看到此数据包并正确显示。我的代码不会不受读取操作的限制。
我使用支持IPV6的Windows 10。
一个想法如何像IPV4一样从网络接口读取所有IPV6数据包? 谢谢。
解决方法
解决方案是使用 ProtocolType.IP 而不是 ProtocolType.IPv6。