使用 ping 命令确定最佳 MTU 大小

May 31, 2024 • 预计阅读时间 2 分钟

macOS:

ping lvv.me -D -s 1464

Linux:

ping -4 lvv.me -M do -s 1464

Windows:

ping -4 lvv.me -f -l 1464

Linux 和 Windows 的 ping 的 -4 参数表示对 IPv4 地址进行测试,因为设置 Don't Fragment bit 仅在 IPv4 下支持。

如果数字设置过大 ping 就会失败,找到最大的可以 ping 的通的数字,最后加上 28 就是最佳的 MTU 了。

如果使用的是 1464 可以 ping 的通,调整到 1465 就失败了,就可以确定当前最佳的 MTU 应该配置为: 14921464 + 28)。

Tips:不要在虚拟机中测试 MTU 的值,结果是不准确的。

MSS 和 MTU 的关系

IPv4: MSS = MTU - 40, 40 = (20 IP header + 20 TCP header)

IPv6: MSS = MTU - 60, 60 = (40 IP header + 20 TCP header)

参考资料:

TCP 最大报文段长度 MSS(Max Segment Size)是 TCP 协议里面定义的一个选项,表示可以被对端设备接收的最大 TCP 报文段的长度。通信双方在建立 TCP 连接时会协商出 MSS 值,以确定 TCP 报文段的最大数据长度。这样,当对端发送的 TCP 报文段的长度超过协商出来的 MSS,报文会进行分片处理。

注意事项

为了保证 TCP 报文不分片,配置过程中需要注意 MSS 与 MTU 的关系。最大传输单元 MTU(Maximum Transmission Unit)是用来标识 IP 报文是否分片的选项。如果对端发送的 IP 报文长度超过 MTU 值,则 IP 报文会进行分片处理。一般情况下,为了不影响报文传输,MSS 值加上报文开销(TCP 首部、IP 首部等)不超过 MTU 值。例如,一个 CAPWAP 封装的 TCP 报文构成为:IP 封装(20 字节)+ UDP 封装(8 字节)+ CAPWAP 封装(8 字节)+ ETH 封装(18 字节)+ IP 封装(20 字节)+ TCP 封装(20 字节)+ TCP 数据报文。设备上默认的 MTU 值为 1500 ,为了保证 CAPWAP 封装的 TCP 报文不分片,MSS 值的最大配置值为 1406,但 CAPWAP 首部或 TCP 首部均可能携带选项字段,推荐用户配置 MSS 值为 1380 字节。

Ref: tcp adjust-mss

Linux 中开启 PMTU 发现功能:

$ sudo vi /etc/sysctl.d/10-pmtu.conf

net.ipv4.ip_no_pmtu_disc = 0
net.ipv4.tcp_mtu_probing = 1
net.ipv4.tcp_base_mss = 1200

FreeBSD 中开启 PMTU 发现功能:

$ sudo vi /etc/sysctl.d/10-pmtu.conf

net.inet.tcp.path_mtu_discovery = 1
net.inet.tcp.pmtud_blackhole_detection = 1
net.inet.tcp.pmtud_blackhole_mss = 1200

相关资源

Linux 系统

可以使用 tracepath 命令跟踪 PMTU 发现功能:

sudo apt install iputils-tracepath

使用 tracepath

tracepath -n lvv.me

Windows 系统

有开源的小工具 mturoute

使用方法:

mturoute -t lvv.me
MTU
版权声明:如果转发请带上本文链接和注明来源。

lvv.me

iOS/macOS Developer

使用 PF 防火墙设置端口白名单

Nginx 配置端口转发