MTU网络问题排查及解决思路

前奏:什么是MTU ?

网络层发送数据包是有最大长度的,网络层从传输层接收到要发送的数据包时,它要判断向本地哪个接口发送数据,并查询该接口获得其最大传输单元MTU(MaximumTransmissionUnit),网络层把MTU值与要发送的IP数据包长度进行比较,如果IP数据包的长度比MTU值大,那么IP数据包就需要进行分片,分片后的数据包长度小于等于MTU(包括IP层头部,大小单位:byte)

简单说:IP规定每一个单独的数据包大小,在网络层时不能超过1500字节,同时也是数据链路层的最大payload。

1、MTU问题常见现象:

在网络中,由于不同厂商,甚至同一厂商不同型号的设备,对MTU的定义和MTU分片机制不尽相同,常出现MTU引起的网络问题,常表现为游戏卡、部分网站或链接打不开,Email无法发送附件,部分网页或对话框无法打开等。遇到此类问题时,建议先检查是否接口MTU不匹配导致。
此外,OSPF、IS-IS、L2VPN、VPLS等协议邻居关系无法建立,也可能是链路两端MTU值不一致导致。

2、MTU问题处理通用思路

对于MTU值问题处理,需要分析数据包传递的全路径上的MTU值设置。通用处理步骤如下:

1、首先分析数据转发路径。

2、检查数据包传递的全路径上各设备的出接口MTU值,站点间传输设备的MTU值也需要检查。

3、逐段ping大包测试。大包长度分别为大于、小于、等于接口MTU值。
   如果ping长度大于接口MTU时不通,小于等于接口MTU时能通,可初步认为是MTU问题。

4、析报文头格式。

5、根据出问题的报文的最大长度修改MTU。
   在修改MTU值时,需要注意华为路由器不同单板的MTU分片机制,并注意不同厂商设备MTU值的定义。

6、再次ping大包测试。

3、解决办法:

1、直接调整机器mtu

2、使用iptables的-j TCPMSS --clamp-mss-to-pmtu来调整mss,自适应路径PMTU(Path MTU)

4、如何探测路径MTU:

  • Linux主机中: 执行ping x.x.x.x -s 1422 -M do

    • x.x.x.x是目标地址
    • -s指明icmp报文的数据部分大小(不包含icmp 8字节头部)
    • -M do 表示不允许分片。多试几次,找到临界点。以mtu为1450为例,1450 = 20字节IP头 + 8字节icmp头 + 1422数据,则-s指定为1422可以正常通过
  • Windows主机中: 执行ping x.x.x.x -l 1472 -f

    • x.x.x.x是目标地址
    • -l指明icmp报文的数据部分大小(不包含icmp 8字节头部)
    • -f表示不允许分片。
  • traceroute–mtu www.baidu.com

    traceroute to www.baidu.com (14.215.177.39), 30 hops max, 65000 byte packets
    1 192.168.109.1 (192.168.109.1) 3.063 ms F=1500 2.908 ms *
    2 192.168.98.36 (192.168.98.36) 1.686 ms 1.422 ms *
    3 113.98.59.57 (113.98.59.57) 7.075 ms 7.544 ms 5.851 ms

    可以看到,探测到 MTU F=1500。

5、为什么mtu值是探测出来的值加上28?

因为ping使用icmp协议,你指定的探测值是数据包数据净荷的长度,还需要加上20字节的ip头部,和8字节的icmp封装。

6、隧道下的mtu问题:

GRE隧道对MTU的影响:

GRE 是三层技术,是对原始 IP 报文进行了封装。网络是个复杂的环境,MTU 不一定都是 1500 字节,例如以太网标准是 1500 字节,如果在以太网上使用了隧道技术,则相应 MTU 会减少,例如 GRE 隧道,因为原始 IP 数据包增加了一个 GRE 头和新的 IP 头,那么 MTU 就要减少到 1476。

GRE 隧道接口为啥要减少 mtu?

因为以太网标准是 1500,数据包过 GRE 隧道,加上 GRE 隧道报文头,要保持不超过 1500,否则在标准以太网内无法传输,自然要压缩过 GRE 隧道前的数据报长度。GRE 隧道接口直接说自己 mtu 就支持 1476,你们原始数据包自己看着办吧。

GRE 带来的问题:

GRE 是在原始 IP 包前又封装了一个 GRE 头(4 字节)和新的 IP 头(20 字节),为了新封装的数据包不超过以太网标准 MTU 1500 字节,他会把自己的 MTU 自动减小,GRE 接口 MTU 是 1500 - 24 = 1476

一个很严重的问题,GRE 隧道把自己的 MTU 减小到了 1476,这时候服务器又不知道网络传输链路上最小 MTU 情况,还认为 MTU 是 1500,并传输数据,这个时候,应用程序如果不让分片,数据包到达 GRE 接口的时候,就会产生问题,最终数据包被丢弃。

如何防止隧道带来的MTU问题:

方法:带 GRE 隧道的服务器 MSS应该是 1436,才会避免分片。

MSS = MTU(1500byte) - IP 首部(20byte) - GRE 头部(24byte) - TCP 首部(20byte) = 1436byte

7、如何设置MTU

1、ifconfig eth0 mtu xxx

2、通过netfilter iptables设置TCP MSS来解决

  • 2-1、-j TCPMSS --clamp-mss-to-pmtu:

    • 用法:iptables -A FORWARD -p tcp- -tcp-flags SYN,RST SYN -jTCPMSS --clamp-mss-to-pmtu
      这条规则的目的就是改变TCP MSS以适应PMTU(Path MTU)

    • 解析:-jTCPMSS --clamp-mss-to-pmtu:
      自动将 MSS 设置为正确的值,因此您无需显式设置它。它自动设置为 PMTU(路径最大传输单元)减去 40 字节,这对于大多数应用程序来说应该是一个合理的值

  • 2-2、-j TCPMSS --set-mss mut-vaue

    • 用法:iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -jTCPMSS --set-mss 128
      这条规则的目的是设置MSS为128,人工设置为定值

8、网络设备收到的报文超过本身设置的MTU值时,将如何处理?

  • 当设备收到的报文超过设备本身的MTU时,IP数据包将进行分片继续处理(分片简单来讲就是将一个大报文拆分成多个小报文)

  • 报文是否能够分片取决于报文本身,在IP报文头部,看到Don’t fragment设置为1时,将不允许分片,否则允许分片。

  • 如果设备收到超过设备接口MTU时,且报文不允许分片,设备将丢弃此报文。

9、当链路两端的数据包MTU设置不一致时,影响大吗?

  • MTU只会影响到数据发出方向,对收入的数据,是没有MTU限制的,建议将链路两端的MTU设置为一样大小的,因为网络通讯都是双向的,一个大与接口MTU的数据收进来,如果又要从这个接口返回去,则入向收到的是一个完整的包,而出向会对这个数据分片,这种双向数据结构不匹配的通讯模型并不是很合理。

10、那么如果一个正常通讯的两台服务器,割接过程中,链路 MTU 变小,会发生什么?

答案是服务器初始协商的 MTU 是 1500,后续数据就是按 1500 进行通讯,如果中间链路 MTU 变小,较小 MTU 接口会丢弃报文,并向发送源服务器发送一条 type=3,code=4 的 ICMP 消息,告诉发送源,自己接口能支持的 MTU 是什么,希望后续报文按该 MTU 进行发送。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐