关于MTU和MSS 网上的资料很多,在看《tcp/ip详解卷1》的时候里面重点说了下MTU的重要性. 但是却没找到MSS,或许是因为MSS是TCP层的一个概念吧,当然MSS和MTU也有莫大的关系.这里为什么再写一下,是因为在实际工中遇到了很奇怪的问题,解决完之后,做一个总结而已.
那么到底遇到奇怪的问题呢?就是客户反馈的在一些地区,通过路由器上网,一部分网站可以访问,而另外一些则无法访问. 或许经常玩网络设备的人马上就会想到了MTU或者MSS ,当时我们没有遇到过.并没有发现问题!通过网络接口抓包也没有发现什么... 因为在家里测试也没有遇到问题.所以只有环境的问题了,那么问题出在了什么地方呢?
一、下面我来先说说MTU吧(见下图)
MTU是一个链路层的一个概念,MTU的定义:除去帧头的数据包大小.
RFC 894(以太网)以太网帧报头为:目的地址 6bytes+源地址 6bytes+协议类型 2bytes+CRC 4bytes=18 bytes 所以一般以太网mtu最大是1500 ,而对于ppp还要减去8字节的开销,就是1492字节.
我们就从lan到wan数据包的流程说起吧.首先pc会发送一个数据帧,一般模式1500(mtu).虽然有mtu协商的功能,但是有时候并不那么智能.这里举例:#ping -f -l 2000 192.168.10.1 这里ping一个大包,并且不允许分片. #来自 192.168.10.1 的回复: 需要拆分数据包但是设置 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字节,(默认没有附加字段)。
二、在ip foward的时候会检查MTU和MSS值.决定是否分片.而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 UnreachableFragmentation 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 -jTCPMSS --clamp-mss-to-pmtu
这条规则的目的就是改变TCP MSS以适应PMTU(Path MTU)
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN- jTCPMSS --set-mss 128
这条规则的目的是设置MSS为128