套接字只捕获传出的数据包,而不是传入的数据包

我已经在这个(经常被引用的)示例项目中使用了数据包嗅探器。 实现HTTP数据包后,我注意到我收到的唯一HTTP数据包是请求,我没有收到任何响应。

我看了很多不同的来源,但由于使用的代码经常是相同的,我倾向于认为它可能是我自己的本地。

当我查看我的日志时,我看到每个数据包都有我的本地IP作为SourceIP ,既用于HTTP数据包,也用于到达其他端口的数据包。

我在这里提供了一个工作示例,您可以将其复制粘贴到LINQPad中并展示问题(添加System.NetSystem.Net.Socket程序集)。 不要忘记以管理员身份执行LINQPad以访问套接字。

这导致192.168.0范围内有数百/数千个条目,总共3个IP地址exception引用我的托管提供商(使用nslookup检查)。

 private readonly byte[] _data = new byte[4096]; private Socket _mainSocket; public void Capture() { _mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP); _mainSocket.Bind(new IPEndPoint(GetLocalIP(), 0)); var byTrue = new byte[] {1, 0, 0, 0}; var byOut = new byte[] {1, 0, 0, 0}; _mainSocket.IOControl(IOControlCode.ReceiveAll, byTrue, byOut); _mainSocket.EnableBroadcast = true; _mainSocket.BeginReceive(_data, 0, _data.Length, SocketFlags.None, OnReceive, null); } private void OnReceive(IAsyncResult ar) { SocketError error; var received = _mainSocket.EndReceive(ar, out error); Parse(_data, received); _mainSocket.BeginReceive(_data, 0, _data.Length, SocketFlags.None, OnReceive, null); } private void Parse(byte[] data, int size) { var packet = new IPHeader(data, size); Console.WriteLine (packet.SourceIP.ToString()); } 
  • Windows 8.1
  • Killer e2200千兆以太网控制器(NDIS 6.30) – 最新版本的驱动程序
    • 昨天安装了一个独立的网卡,它没有改变任何东西。

最接近我的问题的post的描述作为我已经拥有的工作代码的解决方案。

为什么我只能跟踪出站数据包?

您是否尝试过查看操作系统/独立/路由器防火墙? 它经常被忽视,但防火墙对传入和传出连接有不同的规则,这可能是导致问题的原因。

检查GetLocalIP()返回的地址。 您可能正在接收环回ip,在这种情况下您无法捕获进入的数据包。 此处讨论类似问题。

正如@Saibal和@Saverio都提到的那样:防火墙就是问题所在。 作为临时解决方案,我现在在分组跟踪器启动时禁用防火墙,并在停止时启用它(不会在帐户中意外退出)。

如果你最终遇到同样的问题,那么你的第一个“禁用防火墙C#”的结果可能就是这篇博文 。 这在我的情况下不起作用,而是抛出NotImplementedException 。 我猜这只是在Windows XP上,因为这个MSDN文件表明。

幸运的是,Vista和更高版本有其他选择(仅在Windows 8.1上进行过测试,但这可能是inheritance者,并提到了这一点)。

我禁用/启用防火墙的代码:

 private static readonly Type policyType = Type.GetTypeFromProgID("HNetCfg.FwPolicy2"); private static readonly INetFwPolicy2 firewall = (INetFwPolicy2) Activator.CreateInstance(policyType); private void DisableFirewall() { var firewallEnabled = firewall.get_FirewallEnabled( NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE); if (firewallEnabled) { firewall.set_FirewallEnabled( NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE, false); } } 

另一种写作方式是

 firewall.FirewallEnabled[NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE] = false; 

遗憾的是,MSDN仅提供C / C ++中的代码示例,但您仍然可以消除其中的要点。

请记住,您必须将Interop.NetFwTypeLib库添加到项目中。 您可以在C:\ Windows \ SysWOW64 \ FirewallAPI.dll或32位等效文件中找到它。

然而,这非常简陋。 在稍后阶段(这篇文章会随时更新)我会考虑简单地将程序添加到防火墙的例外列表中,但现在这已经足够了。