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

Jer*_*vel 10 c# sockets networking

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

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

当我查看我的日志时,我发现每个数据包都有我的本地IP SourceIP,既包括HTTP数据包,也包含到达其他端口的数据包.

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

这导致192.168.0范围内有数百/数千个条目,总共3个IP地址异常引用我的托管服务提供商(使用检查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());
}
Run Code Online (Sandbox Code Playgroud)
  • Windows 8.1
  • Killer e2200千兆以太网控制器(NDIS 6.30) - 最新版本的驱动程序
    • 昨天安装了一个独立的网卡,它没有改变任何东西.

最接近我的问题的帖子的描述已经解决了我已经拥有的工作代码.

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

Sav*_*ano 5

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


Jer*_*vel 0

正如@Saibal 和@Saverio 都提到的:防火墙是问题所在。作为目前的临时解决方案,我在数据包跟踪器启动时禁用防火墙,并在其停止时重新启用防火墙(不考虑意外退出)。

如果您最终遇到同样的问题,那么“禁用防火墙 C#”的第一个结果可能是这篇博文。这在我的情况下不起作用,而是抛出了NotImplementedException. 我猜测这可能仅适用于 Windows XP,正如MSDN 文档所示。

幸运的是,Vista 及更高版本有替代方案(仅在 Windows 8.1 上进行了测试,但这应该是继任者并提到了这一点)。

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

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

另一种写法是

firewall.FirewallEnabled[NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE] = false;
Run Code Online (Sandbox Code Playgroud)

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

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

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