在IPSEC、GRE网络下的MTU、TCP-MSS计算
一、关于MTU的定义
在华为文档(链接)里写得非常清楚,不同厂商可能对MTU定义不一样,但主流设备将MTU用以指示整个IP报文的最大长度(IP头+三层Payload),MTU是一个三层的定义,即MTU = IP MTU。MTU默认范围是46~1500字节。
如果算上14字节以太网帧头+4字节FCS校验,加起来就是64~1518字节。
如果再加上4字节的VLAN标签,那么长度就变成68~1522字节。
Windows的MTU默认值也是1500,用powershell下执行netsh interface ipv4 show subinterfaces命令可以查看当前系统的MTU值。如果用wireshark在Windows上抓到的最长报文长度一般是1514字节,这是因为wireshark抓到的报文里没有校验部分,所以少了4个字节。
如果设备发出报文时发现超过了MTU值就会分片,对方设备收到分片会重组。很明显,分片重组会影响处理和转发效率,应该避免。正常情况下,大部分设备MTU值都是1500不会出现分片情况,但在IPSEC、MPLS、L2TP、GRE等技术需要增加报文长度的语境下,会导致报文最终超过1500,不修改MTU就会分片。上层协议如何感知MTU值,并发送适合长度报文,避免分片?
二、关于TCP MSS
用户业务流量都是TCP和UDP流量。TCP协议更复杂,对于单个报文长度有自己的协商计算,就是TCP MSS。关于TCP MSS上面引用的华为文档也说的很明白,TCP MSS(Maximum Segment Size)是指TCP协议所允许的从对方收到的最大报文长度,即TCP数据包每次能够传输的最大数据分段,只包含TCP Payload,不包含TCP Header和TCP Option。
TCP MSS是是在TCP握手时候协商的,双方均发送己方的TCP MSS值大小,然后取小的那个值作为本次会话通信的最大值。所以,这个值取决于两端设备的MTU值。
如果中间转发设备的MTU值比较小,两端设备能发现吗?在网络设备上有自动发现MTU值的功能,可以自动修改端口MTU,但很明显无法影响计算机的MTU、TCP MSS。在部分网络设备上还可以直接修改TCP协商报文中的MSS值,比如华为防火墙中的firewall tcp-mss命令,可以修改TCP协商报文中的MSS值,使其可以符合路径中最小的值,而不需要修改计算机MSS值。
三、计算机上如何判断与对端通信的最大MTU
在链接里的这篇文章里详细说明了如何测试链路MTU最小值。在计算机上执行ping命令,参数指定不分片和发送大小,发送大小不包括IP头和ICMP头大小。其中,IP头是20字节,ICMP的ping请求头是8字节,加起来刚好是28字节,所以对于MTU是1500的接口,最大应该能通过数据是1472字节大小的ping报文。通过回显可以知道当前MTU是否能正常通过转发路径。
# windows执行
ping -f -l (1500-28) 对端IP地址# Linux执行
ping -M do -s $((1500-28)) 对端IP地址
四、不同协议对报文分片的影响
关于各协议对MTU的影响,华为专门编写了《MTU专题》(链接)的册子,里面详细说明了相关内容,实在太多太复杂。
1. GRE协议对MTU的影响。如果在IP协议采用GRE隧道,会在原IP报文上增加一个20字节的隧道IP头和一个4字节的GRE头,也就是总计28字节。也就是说如果路径上的设备不修改默认MTU1500,当你ping时负载最大只能填写1448(1472-28),否则就会分片,虽然对用户无感,但却影响性能。
2. IPESC对MTU的影响。IPSEC就更为复杂,密文用ESP协议封装,又有隧道和透明两种模式,隧道还有额外增加一个IP头。即便是透明模式,除了8字节的ESP头还有数字节的尾部。而且,加密算法的要求也会额外填充部分字节。如果采用的是ipsec客户端,可以修改ipsec服务器的接口MTU。如果两端使用ipsec设备,计算机和服务器无法感知中间的ipsec,那么应该增加相关设备MTU值。
当我们的网络存在可能影响MTU的协议时,感觉比较好的方法还是让路径相关设备MTU值变大,毕竟修改用户计算机或者服务器的MTU值,数量太多实在太过麻烦。