WSL 上的 SendPingAsync 超时

SendPingAsync Timeouts on WSL

我想在某些站点以高间隔发送 Pings,因此我创建了一个简单的 C# 控制台应用程序来执行此操作:

while (true)
{
    var start = DateTimeOffset.Now.ToUnixTimeMilliseconds();

    var pingTask = Task.Run(async () =>
    {
        try
        {
            var pinger = new System.Net.NetworkInformation.Ping();
            var pingReply = await pinger.SendPingAsync("google.com", 250);
            Console.WriteLine(pingReply.Status);
        } catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    });
    await Task.WhenAny(Task.Delay(50), pingTask);
    Console.WriteLine($"total wait: {DateTimeOffset.Now.ToUnixTimeMilliseconds() - start}");
}

虽然 运行 这直接在 Windows 上,但几乎所有 pingTask 的结果都是 Success。但是,在 WSL 或 Docker 上 运行(使用从 Visual Studio 自动生成的默认 Dockerfile)结果如下:

total wait: 69
Success
Success
total wait: 23
Success
total wait: 22
Success
total wait: 24
Success
total wait: 14
Success
total wait: 20
Success
total wait: 20
Success
total wait: 19
Success
total wait: 23
Success
total wait: 18
total wait: 53
total wait: 44
total wait: 53
total wait: 50
total wait: 50
TimedOut
total wait: 53
TimedOut
total wait: 42
TimedOut
total wait: 51
TimedOut
total wait: 52
TimedOut
total wait: 50
TimedOut
total wait: 51
TimedOut

后续所有任务都是TimedOut。这适用于 WSL1 和 WSL2。在实际的 Linux 机器中 Docker 上 运行 时不会发生这种情况。我还没有在没有 Docker.

的情况下直接在 Linux 盒子上尝试 运行

另请注意,ping google.com -i 0.05 命令在 WSL1 和 WSL2 中运行良好(当然,当 运行 作为 root 时),因此在 WSL 上发送 ping 也可以工作。

看起来有一些套接字队列建立并且它阻止了所有后续 ping 请求的发生,但我想知道是否有人知道这可能是为什么。我可以调整一些设置来解决这个问题吗?

事实证明这实际上是被洪水禁止,但不是被服务器禁止。我自己的路由器将我的 ping 检测为 PING OF DEATH ATTACK 并阻止了它们。在稍微弄乱了 wireshark 之后,看起来是导致我的路由器将 Linux 中的 .NET SendPingAsync 检测为攻击的具体原因,但不是来自 Windows 设置的快速 ping或 Linux 中的 ping cli 工具是由于使用 ICMP header.

IdentifierSequence Number 部分的差异所致
Identifier Sequence Number
Linux ping CLI Constant Incrementing
Windows ICMP system call Constant Incrementing
.NET SendPingAsync in Linux Incrementing Constant

特别是 Identifier 的自动递增是我的路由器认为有问题的地方。

.NET 的 SendPingAsync 实现之所以如此,其背后的原因是它似乎复制了 Mono 的实现(参见讨论 here and the relevant source code parts。)我不确定为什么要在此实现 Mono方式。

根据 spec 两者都是有效的用途所以我想我的路由器只是很奇怪:

Identifier

      If code = 0, an identifier to aid in matching echos and replies,
      may be zero.

Sequence Number

      If code = 0, a sequence number to aid in matching echos and
      replies, may be zero.