关于mtu和mss 网上的资料很多,在看《tcp/ip详解卷1》的时候里面重点说了下mtu的重要性. 但是却没找到mss,或许是因为mss是tcp层的一个概念吧,当然mss和mtu也有莫大的关系.这里为什么再写一下,是因为在实际工作中,前方测试遇到的一个奇怪问题. 解决完之后,做一个总结而已.
那么什么奇怪的问题呢? 就是大部分网站能上去,有些网站上不去. 或许经常玩网络设备的人马上就会想到了mtu或者mss ,当时我们没有遇到过.并没有发现问题!通过网络接口抓包也没有发现什么... 因为在家里测试没有问题.所以只有环境的问题了,那么问题出在了什么地方呢?1. 这里先说说mtu
![](https://i-blog.csdnimg.cn/blog_migrate/b44c417bf43f3994145cf79cdf306949.jpeg)
简单的看这个图,来说哈,(画的很拙劣 - - !)
mtu是一个链路层的一个概念,mtu的定义:除去帧头的数据包大小.RFC 894(以太网)
以太网帧报头为 目的地址 6+源地址 6+协议类型 2+CRC 4=18 bytes
所以一般以太网mtu最大是1500 ,而对于ppp还要减去8字节的开销,就是1492字节.
我们就从lan到wan数据包的流程说起吧.
首先pc会发送一个数据帧,一般模式1500(mtu).虽然有mtu协商的功能,但是有时候并不那么智能.这里举例:
#ping -f -l 2000 x.x.x.x
这里ping一个大包 ,并且不允许分片.
#来自 x.x.x.x 的回复: 需要拆分数据包但是设置 DF。
有时候网络中pc会发一个我们认为合理的包,但是不通.首先pc发送的数据帧,先达到switch芯片,那么switch一般会允许多大的帧通过呢?
这里我们简单的参考6097的一个芯片. 默认是允许1522的帧(tag) 1518 (untag) ,如果开启了超大帧模式,为1632.
而对于lan侧,或许我们调整可以接收的范围就行了.当然很多时候pc不会发送一个那么大的帧. 如果是从vlan到pc呢?
首先对于一个网络设备,从tcp/udp层封包,往下面传递,到vlan,加tag,封帧,驱动发送.所以vlan所允许的mtu很重要,或许发送给pc的帧,pc不能接受!
如果vlan的mtu为1500 ,那么最大可以发送出去的帧为1522 (tag) ,1518(untag) .
所以在ip层,如果ip包大于mtu值,会分片小于mtu.并发送出去. 这里并不讲数据包的收发具体的函数流程.
但是实际中我们需要上网,就需要wan---lan之间的数据通信. 一般我们的路由器会pppoe拨号,即wan口. 我们知道对于pppoe的帧,它会附加8字节的pppoe头信息,所以一般默认的pppoe所允许的mtu大小为1500-8=1492 .
这里附加说明一下对于icmp包的,ip头长度默认是28字节,而一般ip头位20字节,(默认没有附加字段)。
2. 在ip foward的时候会检查mss和mtu值.决定是否分片.而mss和tcp连接有关.
一般在tcp建立连接的时候,双方会协商出来一个最小的mss值,因为一般tcp通信中一些数据包不允许分片.所以需要在发送的时候,直接发送一个比较小的数据报文.
不然就会被网络处理的时候丢弃掉.
我们来看看mss的定义:
MSS: Maxitu Segment Size 最大分段大小
它是tcp数据包每次能够传输的最大数据分段.为了达到最佳的传输效能,tcp
协议在建立连接的时候通常要协商双方的MSS值,这个值一般是减去ip头和tcp头
即1460,
而有时候我们会遇到一些问题:
MSS---路径最大传输单元 (PMTU) 黑洞路由器 当路由器必须将 IP 包分段但又因 DF 标记设置为 1 而不能分段时,路由器可采用以下任一种方式:
(1) 发送符合 RFC 792 中最初定义的“ICMP Destination Unreachable-Fragmentation Needed and DF Set”消息,然后丢弃该包。 原始消息格式中不包含有关转发失败的链路的 IP MTU 的信息。
(2) 发送符合 RFC 1191 中重新定义的“ICMP Destination Unreachable-Fragmentation Needed and DF Set”消息,然后丢弃该包。此新消息格式包含一个 MTU 字段,可指出转发失败的链路的 IP MTU。 RFC 1191 定义了路径 MTU (PMTU) 发现,它使得成对的 TCP 对等方能够动态地发现二者之间路径的 IP MTU,从而发现该路径的 TCP MSS。一旦收到符合 RFC 1191 定义的“Destination Unreachable-Fragmentation Needed and DF Set”消息,TCP 就会将该连接的 MSS 调整为指定 IP MTU 减去 TCP 和 IP 报头的大小。这样,在该 TCP 连接上发送的后续包就不会超过最大大小,无需分段即可在该路径上传输。
(3)直接丢弃包。 直接丢弃需分段但 DF 标记设置为 1 的包的路由器称为 PMTU 黑洞路由器。
PMTU 黑洞路由器会给 TCP 连接带来问题
在 TCP 三次握手期间交换的 TCP 数据段不会太大,因而不会被 PMTU 黑洞路由器丢弃。但是,一旦开始在连接上传输数据—假定基于协商的 MSS 确定的 PMTU 比实际 PMTU 大—TCP 数据段的大于实际 PMTU 的 IP 包就会被直接丢弃
是的,有时候我们不能保证每个网络设备都有(2)中,mtu自动发现功能. 对于涉及PPPOE+NAT、IPsec、L2TP、GRE等组网,通常由于报文太大需要分片,这样会降低传输速率; 所以选择一个合适的MSS对传输数据来说比较重要. linux中一般可以通过netfilter iptables设置TCP MSS来解决
iptables -A FORWARD -p tcp- -tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
这条规则的目的就是改变TCP MSS以适应PMTU(Path MTU)
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN- j TCPMSS --set-mss 128
设置MSS为128
对于有兴趣分析代码的朋友,可以自己看内核代码关于发现与协商的流程,有空我也需要看看.