某些网站上的随机 TCP RST,这是怎么回事?

Mor*_*rty 35 networking tcp windows-server-2012

简短版本:我网络上的一台 Windows Server 2012 机器在连接到某些网站时会出现持续但间歇性的 TCP RST。不知道他们从哪里来。查看wireshark日志以了解我的分析和问题。

长版:

我们在其中一台服务器上运行缓存网络代理来为我们的小型办公室提供服务。一位同事报告说,在连接到某些站点时,出现了很多“连接重置”或“页面无法显示”错误,但刷新通常会修复它。

我验证了浏览器行为,然后更直接地通过在服务器本身上尝试未代理的浏览器。但是对麻烦站点的 pings 和 traceroutes 没有显示任何问题,问题似乎仅限于 tcp 连接。

然后我编写了一个脚本来测试受影响的站点,方法是通过 cURL 直接向它们发送 HTTP HEAD 请求并检查它们成功的频率。一个典型的测试看起来像这样:(这是未经代理的,直接在坏服务器上运行)

C:\sdk\Apache24\htdocs>php rhTest.php
Sending HTTP HEAD requests to "http://www.washingtonpost.com/":
20:21:42: Length: 0     Response Code: NULL (0%)
20:22:02: Length: 0     Response Code: NULL (0%)
20:22:22: Length: 0     Response Code: NULL (0%)
20:22:42: Length: 0     Response Code: NULL (0%)
20:23:02: Length: 3173  Response Code: HTTP/1.1 302 Moved Temporarily (20%)
20:23:22: Length: 3174  Response Code: HTTP/1.1 302 Moved Temporarily (33.33%)
20:23:43: Length: 0     Response Code: NULL (28.57%)
20:24:03: Length: 3171  Response Code: HTTP/1.1 302 Moved Temporarily (37.5%)
20:24:23: Length: 3173  Response Code: HTTP/1.1 302 Moved Temporarily (44.44%)
20:24:43: Length: 3172  Response Code: HTTP/1.1 302 Moved Temporarily (50%)
20:25:03: Length: 0     Response Code: NULL (45.45%)
Run Code Online (Sandbox Code Playgroud)

从长远来看,只有大约 60% 的请求成功,其余的什么都不返回,curl 错误代码为:“cURL 错误 (56):从对等方接收数据时失败” 不良行为与我的网站一致测试(没有任何站点“变得更好”)并且它非常持久,我已经排除故障一周了,同事报告问题显然已经存在数月了。

我在我们网络上的其他机器上测试了 HEAD 请求脚本:没问题,所有连接都通过我的测试列表中的所有站点。然后我在我的个人桌面上设置了一个代理,当我通过它运行来自有问题的服务器的 HEAD 请求时,所有连接都会通过。所以无论问题是什么,它都非常特定于该服务器。

接下来,我尝试隔离哪些网站表现出连接重置行为:

  • 我们的内部网站 (192.168.xx) 都没有断开连接。
  • 我测试过的没有 ipv6 站点会断开连接。(我们是双栈)
  • 只有少数 Internet ipv4 站点断开连接。
  • 每个使用 cloudflare 作为 CDN(我已经测试过)的站点都会断开连接。(但问题似乎不是 cloudflare 站点独有的)

这个角度并没有发展成任何真正有用的东西,所以接下来我安装了wireshark来查看请求失败时发生了什么。失败的 HEAD 请求如下所示:(此处的较大屏幕截图:http : //imgur.com/TNfRUtX

127 48.709776000    192.168.1.142   192.33.31.56    TCP 66  52667 > http [SYN, ECN, CWR] Seq=0 Win=8192 Len=0 MSS=8960 WS=256 SACK_PERM=1
128 48.728207000    192.33.31.56    192.168.1.142   TCP 66  http > 52667 [SYN, ACK, ECN] Seq=0 Ack=1 Win=42340 Len=0 MSS=1460 SACK_PERM=1 WS=128
129 48.728255000    192.168.1.142   192.33.31.56    TCP 54  52667 > http [ACK] Seq=1 Ack=1 Win=65536 Len=0
130 48.739371000    192.168.1.142   192.33.31.56    HTTP    234 HEAD / HTTP/1.1 
131 48.740917000    192.33.31.56    192.168.1.142   TCP 60  http > 52667 [RST] Seq=1 Win=0 Len=0
132 48.757766000    192.33.31.56    192.168.1.142   TCP 60  http > 52667 [ACK] Seq=1 Ack=181 Win=42240 Len=0
133 48.770314000    192.33.31.56    192.168.1.142   TCP 951 [TCP segment of a reassembled PDU]
134 48.807831000    192.33.31.56    192.168.1.142   TCP 951 [TCP Retransmission] http > 52667 [PSH, ACK] Seq=1 Ack=181 Win=42240 Len=897
135 48.859592000    192.33.31.56    192.168.1.142   TCP 951 [TCP Retransmission] http > 52667 [PSH, ACK] Seq=1 Ack=181 Win=42240 Len=897
138 49.400675000    192.33.31.56    192.168.1.142   TCP 951 [TCP Retransmission] http > 52667 [PSH, ACK] Seq=1 Ack=181 Win=42240 Len=897
139 50.121655000    192.33.31.56    192.168.1.142   TCP 951 [TCP Retransmission] http > 52667 [PSH, ACK] Seq=1 Ack=181 Win=42240 Len=897
141 51.564009000    192.33.31.56    192.168.1.142   TCP 951 [TCP Retransmission] http > 52667 [PSH, ACK] Seq=1 Ack=181 Win=42240 Len=897
143 54.452561000    192.33.31.56    192.168.1.142   TCP 951 [TCP Retransmission] http > 52667 [PSH, ACK] Seq=1 Ack=181 Win=42240 Len=897
Run Code Online (Sandbox Code Playgroud)

我阅读这篇文章的方式(如果我错了,请纠正我,这不是我真正的领域)是:

  • 我们打开一个到网络服务器的 tcp 连接
  • 网络服务器 ACK
  • 发送 HTTP HEAD 请求
  • 有一个 RST 数据包,标记为来自网络服务器 IP,会终止连接。
  • 网络服务器发送 ACK
  • Web 服务器(尝试)使用有效的 HTTP 数据响应 HEAD 请求(951 字节回复包含正确的 HTTP 标头)
  • Web 服务器重新传输(在几秒钟内多次)有效的 HTTP 响应,但由于连接已 RST,因此无法成功

那么,如果网络服务器发送了一个有效的 RST,它为什么还要继续尝试填充请求?如果网络服务器没有生成 RST,那到底是怎么回事?

我尝试过但没有效果的事情:

  • 禁用 NIC 组合
  • 更换网络适配器(更换 NIC 可以正常工作)
  • 分配静态IP。
  • 禁用ipv6。
  • 禁用巨型帧。
  • 一晚将服务器直接插入我们的调制解调器,绕过我们的交换机和路由器。
  • 关闭windows防火墙。
  • 通过 netsh 重置 TCP 设置
  • 禁用服务器上的几乎所有其他服务。(我们主要将它用作文件服务器,但也有 apache 和几个 DB)
  • 用头敲桌子(反复)

我怀疑服务器上的某些东西正在生成 RST 数据包,但我一生都找不到它。我觉得如果我知道:为什么只有这台服务器?或者为什么只有一些网站?它会很有帮助。虽然我仍然很好奇,但我越来越倾向于从轨道上核弹并重新开始。

想法/建议?

-谢谢

Mic*_*ton 41

您的数据包捕获有些不寻常:ECN 位在传出的 SYN 数据包中设置。

显式拥塞通知是 IP 协议的扩展,允许主机更快地对网络拥塞做出反应。它于 15 年前首次引入 Internet,但在首次部署时出现了严重问题。其中最严重的是,许多防火墙在接收到设置了 ECN 位的 SYN 数据包时会丢弃数据包或返回 RST

因此,大多数操作系统默认禁用 ECN,至少对于传出连接是这样。结果,我怀疑很多站点(和防火墙供应商!)根本就没有修复他们的防火墙

直到 Windows Server 2012 发布。Microsoft从此操作系统版本开始默认启用ECN

不幸的是,在最近的记忆中,没有人对互联网站点对 ECN 的响应进行过任何重大测试,因此很难判断 2000 年代初出现的问题是否仍然存在,但我强烈怀疑它们存在并且您的流量至少是有的时候,路过这样的装备。

在我的桌面上启用 ECN 并启动 Wireshark 之后,我只用了几秒钟就抓住了一个主机的例子,我从中得到了一个 RST 到一个设置了 SYN 和 ECN 的数据包,尽管大多数主机似乎工作正常。也许我会自己去扫描互联网......

您可以尝试在您的服务器上禁用 ECN 以查看问题是否解决。这也会使您无法使用 DCTCP,但在小型办公室中,您极不可能这样做或有任何需要这样做。

netsh int tcp set global ecncapability=disabled
Run Code Online (Sandbox Code Playgroud)

  • 公平地说,我不认为某些防火墙管理员是白痴是微软的错。拥有 ECN 非常好,因为它确实有很大帮助,如果我们都可以开始使用它就好了……总有一天。 (9认同)
  • 谢谢你!禁用 ECN 后,我看到连接到最麻烦站点的成功率为 100%!我必须在早上重新打开代理之前进行更多测试,但我将继续并将其标记为既已回答,又是 Microsoft QA 对用户的持续战争中的又一次重大胜利。 (4认同)