分享

【大咖讲网络】MTU导致的悲剧

 文化龙乡 2019-02-24

MTU带来的问题实在太多了,但凡做过运维、实施或者技术支持的工程师,或多或少都会遇到。一个典型的MTU问题发生在类似图1的环境中,即两个子网的MTU大小不一样。

图1

当客户端发给服务器的巨帧经过路由器时,或者被丢包,或者被分片。这取决于该巨帧是否在网络层携带了DF(Don’t fragment)标志。如果带了就被丢弃,如果没带就被分片。从Wireshark上很容易看到DF标志,如图2中的方框内所示。分片的情况往往被忽略,因为它只影响一点点性能,大多数时候甚至察觉不出。丢包的情况就无法忽略了,因为丢包之后再重传多少遍都没用,会一直丢,整个传输就像掉进了黑洞,所以往往会导致严重的后果。

图2

我有个实验环境恰好就是图1这样的,可以来做个实验加深理解。我从客户端给服务器发送了两个ping请求,第一个携带1472字节,第二个携带1473字节,并都用了“-f”参数设置了DF标志。命令及结果请看图3,第一个ping成功,第二个则失败了。

图3

由于ICMP头为8字节,IP头为20字节,所以第一个ping请求在网络层的长度为1472+8+20=1500字节,第二个ping请求则为1473+8+20=1501字节。我的路由器MTU是1500字节,不难理解第一个ping请求的长度没有超过MTU,所以可以传输成功;而第二个ping请求的长度超过了路由器出口的MTU,又不允许被切分,所以不能传输成功。在图3底部可以看到路由器提示了“Packet needs to be fragmented but DF set”。

这个过程的网络包可以从图4中看到,请注意最后一个包是路由器回复的“Fragmentation needed”,而不是服务器回复的。假如ping的时候没有用“-f”设置DF标志,那么1473字节也是能ping成功的,只是在路上会被切分成两个包。

图4

理论说起来很简单,实验做出来也不难,但在生产环境中的症状就没这么明显了,要发现MTU问题往往需要一些想象力。我收藏了不少MTU相关的案例,在本文挑出三个最有代表性的来分享。

案例1 用户浏览某些共享目录时客户端会死机,浏览其他目录则不会。

碰到这种症状,恐怕没有人会想到是MTU导致的,所以经过长时间徒劳无功的排错之后,工程师不得不抓了个包。这个包是在服务器上抓的(因为客户端死机,根本没法抓),如图5所示,服务器回复的包“Seq=193,Len=1460”在持续重传,但客户端一直没有确认,似乎是发生丢包了。从图5底部还可以看到这个包携带的信息是该目录的子文件(夹)列表。

图5

导致丢包的可能性有很多,我为什么认定是MTU导致的呢?推理过程如下。

如果端口被防火墙阻止了也可能丢包,但是会从三次握手时就开始丢,而不是等到浏览目录的时候。

如果网络拥塞也可能丢包,但一段时间后能恢复,而不是这样持续地丢。

丢的那个包携带了1460字节(相当于占满了整个1500字节的MTU),算是比较大的。而没被丢弃的2号包和4号包都携带了很少的字节数,只丢大包的症状说明很可能就是MTU导致的。

我用“ping <server_ip> -l 1472 -f”测试,果然失败了。逐渐减小每次ping的长度,到了1400字节左右才成功,这说明网络上有个设备的MTU比较小。

于是把服务器上网卡的MTU相应改小,问题果然就消失了。

之所以浏览其他目录没有死机,可能是因为这些目录中的子文件(夹)比较少,凑不满一个大包。

我曾经访问公司内网时出现问题,在抓包里也看到类似于图5的症状,后来也是通过修改MTU解决的。

案例2 客户端的MTU为1500字节,服务器端的MTU为9000字节,平时连接正常。运维人员听说两端的MTU最好一致,所以把客户端的MTU提高到9000字节,没想到连接反而出问题了。

虽然该案例听上去不太科学,但如果网络路径上有个设备的MTU是1500字节,这个问题就真会发生。原先客户端和服务器在三次握手时,双方会“协商”使用一个1460字节(MTU-TCP头-IP头)的MSS,所以可以顺利通过那个MTU为1500的网络设备。如果两端都是9000字节了,那三次握手时就会得到8960字节的MSS,因此通不过那个网络设备。

案例3 无法完成Kerberos身份认证,在客户端抓到的包如图6所示。

由图6可见客户端在持续地向KDC发送TGS-REQ,但是收不到任何回复。本来碰到这种情况最好在KDC上也抓个包看看的,但是KDC一般不让人登上去。怎么办呢?

图6

从这几个网络包里是挖掘不出更多线索了,我们只能推测哪些因素会导致TGS-REQ得不到回复。有一个可能是端口被防火墙封掉,但那样的话之前的其他Kerberos包(比如AS-REQ)也得不到回复,不可能走到TGS-REQ这一步,因此防火墙可以排除。还有一个可能就是MTU导致的丢包了,假如网络路径上有个交换机的MTU偏小,大包无法通过就可能出现此症状。仅从Wireshark中我们无法判断是客户端发给KDC时丢包了,还是KDC回复客户端时丢包了,只能先试着把客户端的MTU改小一点,问题果然就消失了。其实利用“ping -f -l <字节数>”试探出路径上的最小MTU也可以,前提是网络中没有禁用 ICMP。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多