开启ECN导致windows客户端 telnet 服务端端口耗时十几秒

2022-11-16 19:50:27 浏览数 (1)

遇到个case,服务端开启了ECN,导致不同的客户端telnet它的时候,有的瞬间就有反应,有的需要等六七秒,有的则需要等十五秒以上。

反应慢的,抓包有如下特征:

发出去的【SYN,ECN,CWR】一直没有响应 最后发了【SYN,ACK】才有响应的

怀疑是ECN导致的,服务端或客户端关闭ECN后再telnet测试则快速响应。问题根因在服务端,当然在客户端关闭ecn也行,但客户端太多了,参差不齐也没法把控,如果客户端是自己的当然可以操作,如果不是,就得动服务端。

关于ECN Capability(Explicit Congestion Notification Capability)

代码语言:javascript复制
ECN(显式拥塞通知,RFC 3168)是一种机制,可为路由器提供通信网络拥塞的另一种方法。目的是减少重传。本质上,ECN假定任何数据包丢失的原因都是路由器拥塞。它允许出现拥塞的路由器标记数据包,并允许客户端自动降低其传输速率以防止进一步的数据包丢失。传统上,TCP / IP网络通过丢弃数据包来表示拥塞。成功协商ECN后,支持ECN的路由器可以在IP 标头中(在DiffServ字段中)设置一个位,而不是丢弃数据包为了表示拥塞。接收者将拥塞指示回送给发送者,发送者必须做出反应,就像检测到数据包丢失一样。当拥塞发生时,发送主机仍然必须降低其传输速率。然而,通过避免丢包,发送主机不再产生重传丢包所需的数据包处理和时间,在拥塞期间,损失敏感的数据包流不会受到那么严重的影响。

要想在互联网层支持ECN(对于IP),发送主机必须能够表明它能够执行ECN,路由器必须能够表明它在转发数据包时遇到了拥塞。IP头中的ECN支持使用ECN字段,这两个字段是RFC 2474定义的服务类型(TOS)字段中未使用的位。ECN字段表示发送主机是否支持ECN,以及转发路由器是否遇到了拥塞。

对于传输层的ECN支持(对于TCP),TCP连接的两端必须向对方表明它们是可以支持ECN的。接收端必须能够通知发送端,它已经收到了来自经历拥塞的路由器的数据包。发送对等体必须能够通知接收对等体它已经收到了来自接收对等体的拥塞指示,并且已经降低了它的传输速率。

当路由器将IP数据包的ECN字段设置为11表示路由器拥塞时,接收方会被告知路径中的拥塞情况,但发送方不会被告知。ECN使用TCP报头向发送方表示网络正在发生拥塞,并向接收方表示发送方已经收到接收方的拥塞指示,并降低其传输速率。

TCP中的ECN支持在TCP头中使用ECN-Echo(ECE)和Congestion Window Reduced(CWR)标志。ECE标志用于在TCP 3-way握手过程中表明TCP对等体是可以支持ECN的,并表明在连接上收到了一个TCP段,IP头中的ECN字段设置为11。当两个具有ECN能力的TCP对等体建立TCP连接时,SYN段同时设置ECE和CWR标志,SYN-ACK段设置ECE标志,清除CWR标志。CWR标志由发送主机设置,表示它收到了一个设置了ECE标志的TCP段。

支持ECN的主机为支持ECN的TCP连接发送TCP段,IP头中的ECN字段设置为10或01。遇到拥塞的ECN功能路由器将IP头中的ECN字段设置为11。当接收的TCP对等体发送的ACK包括接收到的TCP段的数据,而该段的ECN字段被设置为11时,它就会在TCP头中设置ECE标志,并在后续的ACK中继续设置ECE标志。

当发送主机收到设置了ECE标志的ACK时,它的行为就像丢弃了一个数据包,并使用慢速启动和拥塞避免算法降低其传输速率。对于下一个网段,发送方设置CWR标志。在收到设置了CWR标志的新段后,接收方在随后的ACK中停止设置ECE标志。

一开始我也不知道是ECN的原因,我先是找了国内外不同外网IP、不同windows系统的客户端去telnet看看规律,发现server2008R2做客户端时,telnet响应很快,win10/win11做客户端时也很快,2012R2-2022做客户端时普遍很慢,平均在10-15秒之间。执行netsh interface tcp show global对比,发现server2008R2、win10、win11的ECN默认是关闭的,而2012R2/2016/2019/2022的ECN默认是开启的。

微软在PC系统上默认是关闭ECN的,但在server系统上,从server2012开始是默认开启ECN的,这就印证了我一开始的测试

综上,建议云厂商的winserver镜像默认不要开启ECN

执行netsh interface tcp show global 看下ecn是不是开启的,是的话,关闭下

关闭ECN可以执行

代码语言:javascript复制
netsh int tcp set global ecncapability=disabled

要开启ECN可以执行

代码语言:javascript复制
netsh int tcp set global ecncapability=enabled

即时生效,无需重启机器

友商资料:https://help.aliyun.com/document_detail/74566.html

0 人点赞