关于通过ping检测mtu

问题

最近遇到一个问题,个别安装在客户现场的设备报告问题:

  • 设备在线(我们设备内置管理程序和平台保持连接),但是无法更新配置和版本等。
  • 用户反馈网络差,或者无法上网。
  • 之前这些设备都是正常的,出问题之前,运营商刚刚改造过线路、或者更换过光猫。
  • 出问题的设备,一般都是pppoe拨号。

分析问题

通过ping包来看分析,小包正常、大包收不到应答,如下:

root@OpenWrt:/tmp# ping 114.114.114.114 -s 1464
PING 114.114.114.114 (114.114.114.114): 1464 data bytes
1472 bytes from 114.114.114.114: seq=0 ttl=58 time=12.224 ms
1472 bytes from 114.114.114.114: seq=1 ttl=58 time=12.065 ms
^C
--- 114.114.114.114 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 12.065/12.144/12.224 ms
root@OpenWrt:/tmp# 
root@OpenWrt:/tmp# 
root@OpenWrt:/tmp# ping 114.114.114.114 -s 1465
PING 114.114.114.114 (114.114.114.114): 1465 data bytes
^C
--- 114.114.114.114 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss
root@OpenWrt:/tmp#

再比如,这条线路的mtu更小:

root@OpenWrt:~# ping www.baidu.com -s 1345
PING www.baidu.com (115.239.210.27): 1345 data bytes
^C
--- www.baidu.com ping statistics ---
4 packets transmitted, 0 packets received, 100% packet loss
root@OpenWrt:~# 
root@OpenWrt:~# ping www.baidu.com -s 1344
PING www.baidu.com (115.239.210.27): 1344 data bytes
1352 bytes from 115.239.210.27: seq=0 ttl=55 time=15.572 ms
1352 bytes from 115.239.210.27: seq=1 ttl=55 time=24.104 ms
^C
--- www.baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 15.572/19.838/24.104 ms
root@OpenWrt:~# 

基本可以确定是wan口mtu设置问题了。

解决办法

设置系统的mtu。
注意:openwrt有效的mtu设置最大为1500,ubuntu没有这个限制。

openwrt

uci set network.wan.mtu='1480'
uci commit network

最好同步设置

uci set network.lan.mtu='1480'
uci commit network

这样确保dhcp拿到地址的客户端也拿到同样的mtu,减少不必要的分包。

centos

网卡配置文件 /etc/sysconfig/network-scripts/ifcfg-eth0 中设置 MTU=1500

命令行配置的是临时的,重启并不能保存。

ubuntu

也是在网卡配置文件 /etc/network/interfaces 中设置 mtu 1500

windows

默认值需要修改注册表。

dhcp拿到地址的时候,一般会拿到正确的mtu。

扩展

如何检测线路的mtu

通过ping包可以检测系统mtu,步骤:

  • 设置一个比较大的mtu,比如1500
  • windows使用命令 ping -l 1472 -f 114.114.114.114,逐步减小-l 1472 的值,直到ping出去了,这个值加上 28 就是线路mtu
  • 普通linux下使用 ping -l 1472 -M do 114.114.114.114
  • 裁剪过的ping命令,没有参数可以设置 df,目标服务器要选好,看到没有响应就表示中间被分包了。

注意:

  • pppoe默认是1492,部分pppoe线路mtu会很小,比如 1392

mtu限制什么

mtu是链路层的名称,限制了链路层的最大长度,在以太网包中,就是从ip头开始到FCS之前的长度。所以,不拆分的ping包的最大大小应该是 mtu - 20 - 8,其中20为ip报头、8为icmp报头

ping不同的地址、出现不同的效果

实验中发现,同一台机器中,用同样大小(超过mtu限制)的包ping不同的地址,会有不同的效果,类似如下:

root@OpenWrt:~# ping -s 1480 114.114.114.114
PING 114.114.114.114 (114.114.114.114): 1480 data bytes
^C
--- 114.114.114.114 ping statistics ---
4 packets transmitted, 0 packets received, 100% packet loss
root@OpenWrt:~# 
root@OpenWrt:~# ping -s 1480 120.55.162.110
PING 120.55.162.110 (120.55.162.110): 1480 data bytes
1488 bytes from 120.55.162.110: seq=0 ttl=128 time=8.061 ms
1488 bytes from 120.55.162.110: seq=1 ttl=128 time=8.102 ms
^C
--- 120.55.162.110 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 8.061/8.081/8.102 ms
root@OpenWrt:~#

更多的测试发现,对于拆分后的icmp包,不能正确响应的包括:

可以正常响应的包括:

  • www.163.com weibo.cn www.jd.com
  • 阿里云ECS的公网ip地址
  • ubuntu、centos等
  • 个别测试后的简单防火墙,比如 fortinet

具体原因未知。

pppoe的mtu为什么减少8个字节

pppoe的开销是8个字节,pppoe也是属于以太网帧的payload。

裁剪的ping命令没有参数可以设置df

openwrt以及一些路由器中使用的linux,使用的都是裁剪过的ping命令,一般都没有参数可以设置 ip的df(don’t fragmentation)

如何通过dhcp来设置mtu

dhcp分配地址的时候,可以有mtu。
openwrt把lan口的mtu设置成合适的,dnsmasq会读取lan口的mtu发给dhcp client。

mtu的作用

mtu仅仅对系统发出去的包有效,不能限制进入系统的数据包。

pppoe可以自动设置mtu么?

不能,相关的rfc文档都没有提到ncp协商、ipcp分配地址的时候可以设定该字段。