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

时间:2014-02-23 18:23:09

标签: c# sockets networking

我在this (frequently cited) sample project上建立了一个数据包嗅探器。在实现HTTP数据包之后,我注意到我收到的唯一HTTP数据包是请求,我没有收到任何响应。

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

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

我提供了一个工作示例here,您可以将其复制粘贴到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());
}
  • Windows 8.1
  • Killer e2200千兆以太网控制器(NDIS 6.30) - 最新版本的驱动程序
    • 昨天安装了一个独立的网卡,它没有改变任何东西。
最接近我的问题的

A post描述解决了我已经拥有的工作代码。

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

3 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

如果你最终遇到同样的问题,那么“禁用防火墙C#”的第一个结果可能是this blogpost。这在我的情况下不起作用,而是扔了NotImplementedException。我猜这只是可能在Windows XP上this MSDN document表示。

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

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

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仅提供code samples in C / C++,但你仍然可以取消它的主旨。

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

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