注:本文为 “MTU | 检测 / 设置 / 相关问题解析” 相关文章合辑。
图片清晰度限于引文原状。
未整理去重。
什么是 MTU,如何检测和设置路由器 MTU 值
原创 wx62fc501145180 2022-08-18 17:20:23
最大传输单元(Maximum Transmission Unit,MTU)是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位)。
最大传输单元这个参数通常与通信接口有关(网络接口卡、串口等)。如何检测网关的 MTU 在本机打开 dos 窗口,执行:
ping -f -l 1472 192.168.0.1
其中 192.168.0.1 是网关 IP 地址,1472 是数据包的长度。请注意,上面的参数是 “-l”(小写的 L),而不是 “-1”。
如果能 ping 通,表示数据包不需要拆包,可以通过网关发送出去。如果出现:
Packet needs to be fragmented but DF set.
表示数据包需要拆开来发送。此时,减少数据包长度,再执行上面的 ping 命令。从 1400 到 1472 之间多试几次,就能找到合适的数据包长度了。
把数据包长度加上数据包头 28 字节,就得到 MTU 的值。如果检测到网关的 MTU 值是 1500,不需要修改。如果网关有防火墙,ping 不通,可以试试直接把 MTU 设为 1400。
MTU size, PMTUD 和分段
posted on 2022-10-04 01:23 bdy
MTU Size
最大传输单元(MTU)是单个数据报在特定数据通信链路上可以具有的最大字节数。使用封装,加密或覆盖网络协议会导致端到端有效 MTU Size 会减小(增加协议头占用有效载荷?)。某些应用程序在减小的 MTU Size 上可能无法很好地工作,并且无法执行路径 MTU 发现(PMTUD)。
封装开销 Encapsulation Overhead
当一个协议的数据包或帧封装在另一个协议中时,帧大小会整体增加。封装会增加协议标头的开销,因此,通过网络发送 1500 字节数据包的系统无法以大包的形式发送到另一端(超过默认 MTU size,要么分段,要么被丢弃)。协议开销的字节数根据封装类型而变化。
以下是不同的协议封装的开销列表:
协议/封装类型 | 协议号/标准 | 开销增加 (字节) | 备注 |
---|---|---|---|
GRE | IP 协议 47 (RFC 2784) | 24 | 20 字节 IPv4 标头 + 4 字节 GRE 标头 |
6in4 封装 | IP 协议 41 (RFC 4213) | 20 | |
4in6 封装 (如 DS-Lite) | RFC 6333 | 40 | |
外部 IPv4 标头 | - | 20 | 每添加一个额外外部 IPv4 标头 |
DMVPN (IPsec 加密) | ESP-AES-256 + ESP-SHA-HMAC | 73 | 开销取决于传输/隧道模式及加密/认证算法和HMAC |
MPLS | - | 4 | 每个标签增加 4 字节 |
IEEE 802.1Q 标签 | - | 4 | Q-in-Q 增加 8 字节 |
VXLAN | - | 50 | |
OTV | - | 42 | |
LISP (IPv4 封装) | - | 36 | IPv6 封装增加 56 字节 |
NVGRE | - | 42 | |
STT | - | 54 |
在许多其他情况下,也会发生协议封装,因此您必须注意,这是在传输路径上发生的。尽管这可能很难检测到,但是您的网络文档应注意 MTU size 小于 1500 字节的位置。
路径 MTU 发现(PMTUD)
路径 MTU 发现是用来确定到达目的地的路径中最大传输单元 (MTU) 的大小。通过在 IP 报头中设置不分片 DF (Don’t Fragment) 标志来探测路径中的 MTU 值,如果路径中设备的 MTU 值小于此报文长度,并且发现 DF 标志,就会发回一个错误信息。
分段 Fragmentation
IPv4 路由器替源节点对发送的更大数据包的进行分段。除非 IPv4 标头中的 “Do - Not - Fragment” (DF) 位设置为 1,否则路由器可以对 IPv4 数据包进行分段。如果 DF 位设置为 0(默认值),则路由器将拆分太大的数据包以适合输出接口,然后将这两个数据包发送到目的地。当目的地接收到两个片段时,目的地的协议栈必须在处理协议数据单元(PDU)之前执行片段的重组。
关于 MTU、IP MTU、TCP MSS 探讨与分析
原创 Mark_L_Zhang 2014-02-08 11:31:20
1. 概述
本文主要分析了二层 MTU,IP MTU,MSS 之间的关系和在不同网络场景中的应用,最后通过一个案例分析来进一步认识 MTU 对实际 IP 数据包转发的影响。
2. MTU
最大传输单元(Maximum Transmission Unit,MTU)是指一种通信协议在某一层上面所能通过的最大数据报大小(以字节为单位),它通常与链路层协议有密切的关系。Ethernet II 帧结构如图所示:
由于以太网传输电气方面的限制,每个以太网帧都有最小的大小 64 bytes,最大不能超过 1518 bytes。对于小于或者大于这个限制的以太网帧,我们都可以视之为错误的数据帧。一般的以太网转发设备会丢弃这些数据帧。(注:小于 64 Bytes 的数据帧一般是由于以太网冲突产生的 “碎片” 或者线路干扰或者坏的以太网接口产生的,对于大于 1518 Bytes 的数据帧我们一般把它叫做 Giant 帧,这种一般是由于线路干扰或者坏的以太网口产生)。
由于以太网 EthernetII 最大的数据帧是 1518 Bytes,除去以太网帧的帧头(DMAC 目的 MAC 地址 48 bit = 6 Bytes + SMAC 源 MAC 地址 48 bit = 6 Bytes + Type 域 2 bytes)14 Bytes 和帧尾 CRC 校验部分 4 Bytes(这个部分有时候大家也把它叫做 FCS),那么剩下承载上层协议的地方也就是 Data 域最大就只能有 1500 Bytes,这个值我们就把它称之为 MTU。
这个 MTU 就是网络层协议非常关心的地方,因为网络层协议比如 IP 协议会根据这个值来决定是否把上层传下来的数据进行分片。就好比一个盒子没法装下一大块面包,我们需要把面包切成片,装在多个盒子里面一样的道理。当两台远程 PC 互联的时候,它们的数据需要穿过很多的路由器和各种各样的网络媒介才能到达对端,网络中不同媒介的 MTU 各不相同,就好比一长段的水管,由不同粗细的水管组成(MTU 不同),通过这段水管最大水量就要由中间最细的水管决定。
3. IP MTU
对于网络层的上层协议而言(我们以 TCP/IP 协议族为例),网络层 IP 协议会检查每个从上层协议下来的数据包的大小,并根据本机 MTU 的大小决定是否作 “分片” 处理。分片最大的坏处就是降低了传输性能,本来一次可以搞定的事情,分成多次搞定,所以在网络层更高一层(就是传输层)的实现中往往会对此加以注意!有些高层因为某些原因就会要求我这个面包不能切片,我要完整地面包,所以会在 IP 数据包包头里面加上一个标签:DF(Don’t Fragment)。这样当这个 IP 数据包在一大段网络(水管里面)传输的时候,如果遇到 MTU 小于 IP 数据包的情况,转发设备就会根据要求丢弃这个数据包,然后返回一个错误信息给发送者。这样往往会造成某些通讯上的问题,不过幸运的是大部分网络链路 MTU 都是等于 1500 或者大于 1500。
对于 UDP 协议而言,这个协议本身是无连接的协议,对数据包的到达顺序以及是否正确到达不甚关心,所以一般 UDP 应用对分片没有特殊要求。对于 TCP 协议而言就不一样了,这个协议是面向连接的协议,对于 TCP 协议而言它非常在意数据包的到达顺序以及是否传输中有错误发生。所以有些 TCP 应用对分片有要求 —— 不能分片(DF)。
4. MSS
MSS 是最大传输大小的缩写,它是 TCP 协议里面的一个概念。
MSS 是最大传输大小的缩写,它是 TCP 协议里面的一个概念。如图所示。
TCP 头部示意图
注:URG 等参数指的是 ACK URG PSH SIN FIN RST 等参数
在 TCP 报文中 MSS 的位置就在选项的位置,根据 RFC1323 和 RFC793 规定,选项中内容有很多种,MSS 是其中的一种,用 kind = 2 表示;kind = 1 表示无操作,kind = 4、5、6、7 称为选择 ACK 及回显选项,但是由于回显选项已经被时间戳选项取代,同时,目前定义的选择 ACK 选项仍未定论,也没有包括在 RFC1323 中,所以具体代表什么含义还无定论。在实际网络数据传输,要求 MSS + 20 TCP 包头 + 20 IP 包头不大于 MTU。MSS 在 TCP 报文中是可选项,不是必选项,换句话说,MSS 是可协商项,而且在协商过后,该选项内容可以改变,也可以没有;在协商 MSS 时,一般是建立 TCP 连接的两端发送 Syn 标志报文时互相通报,然后选取最小 MSS 作为双方的约定,如果双方都不通报或者有一方不通报,MSS 就是 TCP 数据包每次能够传输的最大数据分段。为了达到最佳的传输效能,TCP 协议在建立连接的时候通常要协商双方的 MSS 值,这个值 TCP 协议在实现的时候往往用 MTU 值代替(需要减去 IP 数据包包头的大小 20 Bytes 和 TCP 数据段的包头 20 Bytes),所以往往 MSS 为 1460。通讯双方会根据双方提供的 MSS 值的最小值确定为这次连接的最大 MSS 值。
5. 区别及联系
由前面的叙述可知:MTU 是一个二层的概念,以太网最大的 mtu 就是 1500(它是不包含二层头部的,加上头部应该为 1518 bytes),当然这里说的是很常规的情况,也有些 server,比如 server 2008,出来的就是 jumbo frame 了,我们在这里讨论常规情况。IP MTU 是一个三层概念,它包含了三层头部及所有载荷,根据下层为上层服务的,上层基于下层才能做进一步的扩展的原则,尽管 IP MTU 的变化范围很大(68 - 65535),但也不得不照顾以太网 MTU 的限制,说白了就是 ip 对以太网的妥协。MSS 是 TCP 里面的一个概念,它是 TCP 数据包每次能够传输的最大数据分段,不包含包头部分,它与 IP MTU 满足如下关系:IP MTU = MSS + 20 bytes(IP 包头)+ 20 bytes(TCP 包头)。当然,如果传输的时候还承载有其他协议,还要加些包头在前面,简言之,mtu 就是总的最后发出去的报文大小,MSS 就是需要发出去的数据大小,比如 PPPoE,就是在以太网上承载 PPP 协议(点到点连接协议),它包括 6 bytes 的 PPPoE 头部和 2 bytes 的 PPP 协议 ID 号,此时,由于以太网的 MTU 值为 1500,所以上层 PPP 负载数据不能超过 1492 字节,也就是相当于在 PPPOE 环境下的 MTU 是 1492 字节,MSS 是 1452 字节。
6. MTU 问题解决方法
通常情况下,MTU 不匹配会表现为两种故障情况:
- ping 大包时不通
- 无法访问某些站点
在这种情况下,通常有两种解决方法:
- 修改用户端 MTU 值(不推荐使用)
- 修改传输路由所有设备 MTU 值,确保路径 MTU 值大于用户发送的 IP 报文的长度,以保证用户报文不会因为超过设备的 MTU 值被丢弃。主要要考虑下面几种情况:
・对于纯 IP 网络,要保证:路径 MTU 值 > 最大用户报文长度
・对于纯 MPLS 网络(没有 ××× 业务),要保证路径 MTU 值 > 最大用户报文 + 一层标签长度(4)
・对于三层 ××× 业务,要保证:路径 MTU 值 > 最大用户报文 + 两层标签长度(8);
・对于二层 ××× 业务,要保证:路由 MTU 值 > 最大用户报文长度 + 两处标签长度(8)+ 二层帧头长度(18)。
值得注意的是:fastethernet 接口不能调整 MTU,所以说在有些设备中,使用 MTU 命令不能解决问题的。此外,更改 MTU 后,如果 IGP 是 OSPF 的话,不同的 MTU 可能会造成 OSPF 停留在 INIT 状态,此时需要将两端的 MTU 调整一致。
7. 案例分析
下面通过一个某公司 TCP MSS 配置不匹配导致应用不正常的案例分析,来加深对上述概念的理解。其拓扑图如图所示:
某公司网络拓扑示意图
设备 | 角色 | 说明 |
---|---|---|
NBR2000 | 公司总出口路由器 | 启用 L2TP 功能,同时在 L2TP 虚拟模板接口中配置了 TCP MSS 为 1300。 |
NBR1200 | 分公司出口路由器 | 启用 L2TP 功能,同时在 L2TP 虚拟模板接口中配置了 TCP MSS 为 1400。 |
NBR1200 与 NBR2000 通过 L2TP 协议建立隧道,NBR2000 作为服务端,NBR1200 作为客户端。
故障现象:
在分公司 NBR1200 的 PC 上登录总公司 ISOFLOW 服务器,在 ISOFLOW 里签核表单的时候,会无法签核下去而导致 IE 死掉的现象。如果碰见 ISOFLOW 单子的附件,会发现附件要过很长、很长的时间才能打开。
访问 ERP 系统普通表单的速度不错,但是一旦进行数据库的读写,速度极慢;数据查询时经常超时。
诊断故障原因及分析:
- 故障诊断的思路
登录到总公司 NBR2000 和分公司 NBR1200,查看配置,具体如下:
NBR2000 虚拟模板配置:
interface Virtual-Template 1
mtu 1400
ppp authentication pap
ip nat inside
ip tcp adjust-mss 1300
ip unnumbered GigabitEthernet 0/0
peer default ip address pool VPDN
NBR1200 虚拟模板配置:
interface Virtual-ppp 1
pseudowire X.X.X.X 20 encapsulation l2tpv2 pw-class pw
mtu 1400
ppp pap sent-username star-net password 7 0058274d4c24
ip tcp adjust-mss 1400
ip address negotiate
故障诊断的分析
判断网络层是否正常
在现场从分公司 PC PING 总公司 ISOFLOW 服务器 IP,长 PING 没有丢包,说明网络层是正常的。
应用异常
目前用户应用是通过 HTTP 来访问,出现能访问,但很慢的现象,说明是在应用层上出现了问题。一般来说,在应用层出问题,在排除软件本身问题的情况下,基本可以定位是 MTU 或 TCP MSS 不匹配原因引起。
TCP MSS 分析
一般来说一般的应用软件,当客户端和服务器端在建立 TCP 连接的时候需要根据实际传输的报文大小来协商 TCP 的窗口大小 MSS。在 TCP 协商的第一个报文也就是 SYN 置位的报文中会告知对方自己所能接收的最大 TCP 数据净荷(也就是 TCP 报文中的数据长度)—MSS,对方收到 TCP 同步报文也会回复一个 SYN 置位的 TCP 报文,其中也携带了 MSS 参数来告知对方自己能接收的最大 MSS。根据以上分析,我们来看一下总公司与分公司路由器是怎么协商 TCP MSS 的:
(1)分公司 -> 总公司
PC 发起 TCP SYN 报文与总公司 ISOFLOW 服务器进行协商,在 TCP SYN 报文经过分公司路由器虚拟模板接口(out 方向)时,路由器会将接口配置的 MSS 值 1400(分公司路由器在虚拟模板接口上配置了 ip tcp adjust-mss 1400)与 TCP 报文中的 MSS 值 1460(windows XP 系统默认是 1460)比较,取二者的最小值 1400。ISOFLOW 服务器收到此 TCP 同步报文,查看其中的 MSS = 1400,服务端在后续发送数据时封装的最大 TCP 数据载荷为 1400。一般来说 TCP MSS 是不分包的,DF 置位为 1。
(2)总公司 -> 分公司
ISOFLOW 发响应 TCP SYN ACK 报文给分公司的 PC,在 TCP SYN 报文经过总公司路由器虚拟模板接口(out 方向)时,路由器会将接口配置的 MSS 值 1300(总公司路由器在虚拟模板接口上配置了 ip tcp adjust-mss 1300)与 TCP 报文中的 MSS 值 1460(windows XP 系统默认是 1460)比较,取二者的最小值 1300。PC 收到此 TCP 同步确认报文,查看其中的 MSS = 1300,PC 在后续发送数据时封装的最大 TCP 数据载荷为 1300。一般来说 TCP MSS 是不分包的,DF 置位为 1。
PC 在向 ISOFLOW 发送请求,作为 ISOFLWO 的被请求端,发出的数据包括的数据文件,数据包较大,需要封装成最大 MSS 载荷传送(提高效率),在此 MSS = 1400,当数据包经过总公司 L2TP ××× 虚拟模板接口时,由于配置了 mtu 1400,而此时数据包的 MTU(MTU = 1400 + TCP (20) + IP (20) + PPP (4) + L2TP(8)+ UDP(8)+ IP(20)= 1480)远远大于总公司路由器虚拟模板接口 MTU 1400,且 IP 包头强制不分片位被置位,导致在出 ××× 隧道时报文被丢弃,所以现象就是能够建立 TCP 连接,但服务器端返回大数据包时,出现 IE 应用程序没有响应现象。同理,如果是从服务端发起的访问客户端口 PC,由于客户端接收到的 TCP 同步报文中的 MSS = 1300,那么其封装的数据经过分公司路由器 L2TP ××× 隧道时,数据包的 MTU (MTU = 1300 + TCP (20) + IP (20) + PPP (4) + L2TP(8)+ UDP(8)+ IP(20)= 1380) 小于分公司路由器隧道 MTU = 1400,所以能够正常。
解决 GRE 和 IPsec 中的 IPv4 分段、MTU、MSS 和 PMTUD 问题
简介
本文档介绍 IPv4 分段和路径最大传输单元发现 (PMTUD) 的工作方式。
背景信息
此外,还讨论了当结合不同的 IPv4 隧道组合时,涉及 PMTUD 行为的场景。
IPv4 分段和重组
尽管 IPv4 数据报的最大长度为 65535 字节,但大多数传输链路强制执行更小的最大数据包长度限制(即 MTU)。MTU 值取决于传输链路。
IPv4 的设计可以容纳 MTU 差异,因为它允许路由器根据需要对 IPv4 数据报进行分段。
接收站负责将分段重组为原始的全尺寸 IPv4 数据报。
IPv4 分段将数据报划分为多个片段,稍后再重新组合。
IPv4 报头中的 IPv4 source、destination、identification、total length 和 fragment offset 字段以及 “更多分段” (MF) 和 “不分段” (DF) 标志用于 IPv4 分段和重组。
有关 IPv4 分段和重组机制的更多信息,请参阅 RFC 791。
下图显示了 IPv4 报头的布局。
标识是 16 位,是由 IPv4 数据报的发送方分配的值。这有助于重组数据报的片段。
分段偏移量字段长 13 位,表示分段在原始 IPv4 数据报中所属的位置。此值为 8 字节的倍数。
IPv4 报头的标志字段中有 3 个控制标志位。“不分段” (DF) 位确定是否允许对数据包进行分段。
位 0 被保留,并且始终设置为 0。
位 1 是 DF 位 (0 = “can fragment”,1 = “do not fragment”)。
位 2 为 MF 位(0 =“最后一个分段”,1 =“更多分段”)。
价值 | 位 0(保留) | 位 1 (DF) | 位 2 (MF) |
---|---|---|---|
0 | 0 | 5 月 | 最后一页 |
1 | 0 | 不分段 | 更多 |
如果添加 IPv4 分段的长度,则值会比原始 IPv4 数据报长度大 60 字节。总长度之所以增加 60 字节是因为为第一个分段后的另外三个分段多创建了三个 IPv4 报头,每个分段一个。
第一个分段的偏移量为 0,此分段的长度为 1500;这包括 20 个字节,表示经过略微修改的原始 IPv4 报头。
第二个分段的偏移量为 185 (185 x 8 = 1480);此分段的数据部分从原始 IPv4 数据报的 1480 个字节开始。此分段的长度为 1500;其中包括为此分段创建的其他 IPv4 报头。
第三个分段的偏移量为 370 (370 x 8 = 2960);此分段的数据部分从原始 IPv4 数据报的 2960 个字节开始。此分段的长度为 1500;其中包括为此分段创建的其他 IPv4 报头。
第四个分段的偏移量为 555 (555 x 8 = 4440),这意味着此分段的数据部分从原始 IPv4 数据报的第 4440 字节后开始。此分段的长度为 700 个字节;其中包括为此分段创建的其他 IPv4 报头。
只有当收到最后一个分段时,才可以确定原始 IPv4 数据报的大小。最后一个分段中的分段偏移量 (555) 表示数据偏移量为原始 IPv4 数据报的 4440 字节。最后一个分段的数据字节总和 (680 = 700 - 20) 可产生 5120 个字节,这是原始 IPv4 数据报的数据部分。IPv4 报头增加 20 个字节等于原始 IPv4 数据报的大小 (4440 + 680 + 20 = 5140),如图所示。
IPv4 分段相关问题
IPv4 分段会小幅增加 CPU 和内存开销,从而对 IPv4 数据报进行分段。对于发送方以及发送方和接收方之间路径中的路由器,情况也是如此。
分段的创建包括创建分段报头并将原始数据报复制到分段中。
由于创建分段所需的信息立即可用,因此可以高效地完成此操作。
重组分段时,分段会导致接收者产生更大开销,原因是接收者必须为到达的分段分配内存,然后在收到所有分段后将它们重新组合为一个数据报。
在主机上进行重组不会带来任何问题,因为主机拥有完成此任务所需的时间和内存资源。
但是,如果路由器的主要任务是尽快转发数据包,则重组效率会非常低。
路由器不是为了将数据包保存任意时长而设计的。
执行重组的路由器会选择可用的最大缓冲区 (18K),因为在收到最后一个分段之前,它无法确定原始 IPv4 数据包的大小。
另一个分段问题涉及到已丢弃分段的处理方式。
如果 IPv4 数据报的一个分段被丢弃,则整个原始 IPv4 数据报必须存在,并且它也是分段的。
网络文件系统 (NFS) 中可看到此情况。NFS 的读写块大小为 8192。
因此,NFS IPv4/UDP 数据报约为 8500 字节(包括 NFS、UDP 和 IPv4 报头)。
连接到以太网 (MTU 1500) 的发送站必须将 8500 字节的数据报分段为六 (6) 段;五 (5) 个 1500 字节的分段和一 (1) 个 1100 字节的分段。
如果由于链路拥塞而丢弃了六个分段中的任何一个,则必须重新传输完整的原始数据报。这会导致创建另外六个分段。
如果此链路丢弃六分之一的数据包,则通过此链路传输任何 NFS 数据的可能性较低,因为每个 NFS 8500 字节的原始 IPv4 数据报至少会丢弃一个 IPv4 分段。
防火墙根据从第 4 层 (L4) 到第 7 层 (L7) 的信息过滤或处理数据包,无法正确处理 IPv4 分段。
如果 IPv4 分段顺序混乱,防火墙会阻止非初始分段,因为它们不携带与数据包过滤器匹配的信息。
这意味着接收主机无法重组原始 IPv4 数据报。
如果防火墙配置为允许信息不足的非初始分段与过滤器正确匹配,则可能通过防火墙进行非初始分段攻击。
网络设备(如内容交换引擎)根据 L4 到 L7 信息转发数据包,如果数据包跨越多个分段,设备将难以实施其策略。
避免 IPv4 分段:TCP MSS 的工作原理
传输控制协议 (TCP) 最大分段大小 (MSS) 定义主机在单个 TCP/IPv4 数据报中接受的最大数据量。
此 TCP/IPv4 数据报可能在 IPv4 层分段。MSS 值仅作为 TCP SYN 数据段中的一个 TCP 报头选项发送。
TCP 连接的每一端都会向另一端报告其 MSS 值。主机之间 * 不 * 协商 MSS 值。
发送主机需要将单个 TCP 数据段中的数据大小限制为小于或等于接收主机报告的 MSS 的值。
最初,MSS 决定着接收站上分配用于存储单个 IPv4 数据报所含 TCP 数据的缓冲区的大小(大于等于 65496 字节)。
MSS 是 TCP 接收方将要接受的最大数据段。此 TCP 数据段可能高达 64K,在 IPv4 层进行分段以便传输到接收主机。
在将完整的 TCP 分段传送至 TCP 层之前,接收主机会重组 IPv4 数据报。
如何设置 MSS 值并用于限制 TCP 数据段和 IPv4 数据报大小。
示例 1 说明了 MSS 的首次实施方式。
主机 A 的缓冲区为 16K,主机 B 的缓冲区为 8K。这些主机发送和接收其各自的 MSS 值,并调整其发送 MSS 以便彼此发送数据。
主机 A 和主机 B 必须对大于接口 MTU 但小于发送 MSS 的 IPv4 数据报进行分段,因为 TCP 堆栈会将 16K 或 8K 字节的数据沿堆栈向下传递到 IPv4。
对于主机 B,对数据包进行分段以进入令牌环 LAN,然后再次进入以太网 LAN。
示例 1
- 主机 A 将其 MSS 值 16K 发送到主机 B。
- 主机 B 收到来自主机 A 的 MSS 值 16K。
- 主机 B 将其发送 MSS 值设置为 16K。
- 主机 B 将其 MSS 值 8K 发送到主机 A。
- 主机 A 收到来自主机 B 的 MSS 值 8K。
- 主机 A 将其发送 MSS 值设置为 8K。
为帮助避免 TCP 连接终端的 IPv4 分段,MSS 值的选择已更改为最小缓冲区大小和传出接口的 MTU (- 40)。
MSS 编号比 MTU 编号小 40 字节,因为 MSS(TCP 数据大小)不包括 20 字节的 IPv4 报头和 20 字节的 TCP 报头。
MSS 基于默认报头大小;发送方堆栈必须减去 IPv4 报头的相应值,TCP 报头取决于使用的 TCP 或 IPv4 选项。
MSS 当前的工作方式是,每台主机首先将其传出接口 MTU 与自己的缓冲区进行比较,并选择最低值作为 MSS 发送。
然后,主机将收到的 MSS 大小与其自己的接口 MTU 进行比较,并再次选择两个值中较小的一个。
示例 2 说明了发送方为避免本地和远程线路上的分段而执行的这一附加步骤。
在主机相互发送其 MSS 值之前,每台主机都会考虑传出接口的 MTU。这有助于避免分段。
示例 2
- 主机 A 比较其 MSS 缓冲区 (16K) 和其 MTU (1500 - 40 = 1460),并使用较小的值作为 MSS (1460),以便发送到主机 B。
- 主机 B 收到来自主机 A 的发送 MSS (1460),并将其与出站接口 MTU - 40 (4422) 的值进行比较。
- 主机 B 将较低的值 (1460) 设置为 MSS,以便向主机 A 发送 IPv4 数据报。
- 主机 B 比较其 MSS 缓冲区 (8K) 和其 MTU (4462 - 40 = 4422),并使用 4422 作为 MSS,以便发送到主机 A。
- 主机 A 从主机 B 接收发送 MSS (4422),并将其与出站接口 MTU - 40 (1460) 的值进行比较。
- 主机 A 将较低的值 (1460) 设置为 MSS,以便向主机 B 发送 IPv4 数据报。
1460 便是两台主机为彼此选择的发送 MSS 的值。通常,TCP 连接的每一端的发送 MSS 值相同。
在示例 2 中,TCP 连接的终端不会发生分段,因为主机会考虑两个传出接口 MTU。
如果路由器 A 和路由器 B 之间链路的 MTU 低于任一主机的出站接口,则数据包仍然会在网络中分段。
什么是 PMTUD
TCP MSS 解决 TCP 连接的两个端点上的分段,但不处理这两个端点之间中间有较小的 MTU 链路的情况。
为了避免在终端之间的路径上出现分段,开发了 PMTUD。它用于动态确定从数据包源到其目的地的路径中的最低 MTU。
注意:PMTUD 仅受 TCP 和 UDP 支持。其他协议不支持 PMTUD。如果在主机上启用 PMTUD,则来自该主机的所有 TCP 和 UDP 数据包都会设置 DF 位。
如果主机发送设置了 DF 位的完整 MSS 数据包,则在收到数据包需要分段的信息时,PMTUD 将减少连接的发送 MSS 值。
主机记录目标的 MTU 值,因为它会在路由表中创建具有此 MTU 值的主机 (/32) 条目。
如果路由器尝试将 IPv4 数据报(设置了 DF 位)转发到 MTU 低于数据包大小的链路上,路由器会丢弃该数据包,并将互联网控制消息协议 (ICMP)“目标不可达”(Destination Unreachable) 消息返回到 IPv4 数据报源,消息中带有指示 “需要分段并设置 DF”(类型 3,代码 4)的代码。
当源站点收到 ICMP 消息时,它降低发送 MSS,当 TCP 重新传输数据段时,它使用较小的数据段大小。
以下示例说明了在启用 debug ip icmp
命令后,在路由器上看到的 ICMP “fragmentation needed and DF set” 消息:
ICMP: dst (10.10.10.10) frag. needed and DF set
unreachable sent to 10.1.1.1
下图显示了 “需要分段和设置 DF”、“无法到达目标” 消息的 ICMP 报信头的格式。
根据 RFC 1191,如果某路由器返回 ICMP 消息 “需要分段但 DF 已设置”,则该路由器必须在根据 ICMP 规范 RFC 792 标记为 “未使用” 的低阶 16 位 ICMP 附加报头字段中,使用下一跳网络的 MTU。
RFC1191 的早期实现未提供下一跳 MTU 信息。即使提供了此信息,某些主机也会忽略它。
在本例中,RFC 1191 还包含一个表,其中列出了 PMTUD 期间 MTU 降低的建议值。主机使用它来更快地为发送 MSS 得出一个合理的值,如本例所示。
由于发送方和接收方之间的路径可以动态更改,因此会对所有数据包持续执行 PMTUD。发送方每次收到 “Cannot Fragment” ICMP 消息时,都会更新路由信息(存储 PMTUD 的位置)。
执行 PMTUD 时,可能会发生以下两种情况:
- 数据包可以一直传输到接收方,而不会被分段。
注意:为了使路由器保护 CPU 免受 DoS 攻击,它会将发送的 ICMP 不可达消息数限制为每秒两条。因此,在这种情况下,如果您的网络方案预期路由器每秒钟将需要响应超过两个 ICMP 消息(类型 = 3,代码 = 4)(可以是不同主机),请使用 no ip icmp rate-limit unreachable [df] interface
命令禁用 ICMP 消息限制。
- 发送方从通往接收方的路径上的每一跳收到 ICMP “无法分段” 消息。
PMTUD 在 TCP 流量的两个方向上独立执行。
在某些情况下,流量一个方向的 PMTUD 会触发其中一个终端站降低发送 MSS,而另一个终端站会保留原始发送 MSS,因为它从未发送足够大的 IPv4 数据报来触发 PMTUD。
例如,示例 3 中描述的 HTTP 连接。TCP 客户端发送小数据包,服务器发送大数据包。
在这种情况下,只有来自服务器的大数据包(大于 576 字节)触发 PMTUD。
来自客户端的数据包较小(小于 576 字节),并且不触发 PMTUD,因为它们不需要分段即可通过 576 MTU 链路。
示例 3
示例 4 显示了一个非对称路由示例,其中一条路径的最小 MTU 小于另一条路径。
采用不同的路径在两个终端之间发送和接收数据时,将会出现非对称路由。
在本示例中,PMTUD 仅在 TCP 流的一个方向上触发发送 MSS 的下降。
从 TCP 客户端到服务器的流量会经过路由器 A 和路由器 B,而从服务器到客户端的返回流量会经过路由器 D 和路由器 C。
当 TCP 服务器向客户端发送数据包时,PMTUD 会触发服务器降低发送 MSS,因为路由器 D 必须对 4092 字节的数据包进行分段,然后才能将其发送到路由器 C。
相反,客户端永远不会收到代码为 “fragmentation needed and DF set” 的 ICMP “Destination Unreachable” 消息,因为路由器 A 在通过路由器 B 向服务器发送数据包时不必对数据包进行分段。
示例 4
注意:可以使用 ip tcp path-mtu-discovery 命令对路由器启动的 TCP 连接(例如 BGP 和 Telnet)启用 TCP MTU 路径发现。
PMTUD 问题
这些东西可以破坏 PMTUD。
- 路由器丢弃数据包,且不发送 ICMP 消息。(不常见)
- 路由器生成并发送 ICMP 消息,但此路由器和发送器之间的路由器或防火墙阻止该 ICMP 消息。(常见)
- 路由器生成并发送 ICMP 消息,但发送方忽略该消息。(不常见)
这里的三项要点中的第一项、最后一项通常是由错误导致的,但中间一项描述的是一个常见问题。
实施 ICMP 数据包过滤器的那些设备倾向于阻止所有 ICMP 消息类型,而不是只阻止某些 ICMP 消息类型。
数据包过滤器可以阻止所有 ICMP 消息类型,但 “无法到达” 或 “超时” 消息除外。
PMTUD 的成功或失败取决于到达 TCP/IPv4 数据包发送方的 ICMP 不可达消息。
ICMP 超时消息对于其他的 IPv4 问题非常重要。
下面显示了在路由器上实现的此类数据包过滤器示例。
access-list 101 permit icmp any any unreachable
access-list 101 permit icmp any any time-exceeded
access-list 101 deny icmp any any
access-list 101 permit ip any any
还有其他技术可用于缓解 ICMP 完全阻塞的问题。
- 清除路由器上的 DF 位并允许分段。(不过,这不是个好主意。有关详细信息,请参阅 [IPv4 分段和重组]。
- 使用接口命令
ip tcp adjust-mss <500 - 1460>
调整 TCP MSS 选项值 MSS。
在下一个示例中,路由器 A 和路由器 B 位于同一个管理域中。路由器 C 不可访问并且会阻止 ICMP,因此,PMTUD 将中断。
在这种情况下,解决方案是在路由器 B 的两个方向上清除 DF 位,从而允许分段。这可以通过策略路由来完成。
Cisco IOS® 软件版本 12.1 (6) 和更高版本中提供了用于清除 DF 位的语法。
interface serial0
...
ip policy route-map clear-df-bit
route-map clear-df-bit permit 10
match ip address 111
set ip df 0
access-list 111 permit tcp any any
另一个选择是更改流经路由器的 SYN 数据包的 TCP MSS 选项值(在思科 IOS® 12.2 (4) T 及更高版本中可用)。
这会减小 TCP SYN 数据包中的 MSS 选项的值,使其小于 ip tcp adjust-mss
命令中的值 (1460)。
结果是 TCP 发送方发送的数据段不大于此值。
IPv4 数据包的大小比 MSS 值(1460 字节)大 40 字节 (1500),以说明 TCP 报头(20 字节)和 IPv4 报头(20 字节)。
您可以使用 ip tcp adjust-mss
命令调整 TCP SYN 数据包的 MSS。此语法将 TCP 数据段的 MSS 值减少到 1460。
此命令将影响 serial0 接口上的入站和出站流量。
int s0
ip tcp adjust-mss 1460
随着 IPv4 隧道部署越来越广泛,IPv4 分段问题也变得越来越普遍。
隧道会导致更多分段,因为隧道封装会增加数据包大小的 “开销”。
例如,增加通用路由器封装 (GRE) 会向数据包中添加 24 个字节,增加之后,数据包需要分段,因为它大于出站 MTU。
需要 PMTUD 的常见网络拓扑
在网络环境中,如果中间链路的 MTU 小于终端链路的 MTU,则需要 PMTUD。存在这些较小的 MTU 链路的一些常见原因是:
- 与令牌环(或 FDDI)相连的终端主机之间存在以太网连接。两端的令牌环(或 FDDI)MTU 大于中间的以太网 MTU。
- PPPoE(通常与 ADSL 配合使用)的报头需要 8 个字节。这使得以太网的有效 MTU 减小至 1492 (1500 - 8)。
GRE、IPv4sec 和 L2TP 等隧道协议还需要用于各自报头和报尾的空间。这也会降低出站接口的有效 MTU。
隧道
隧道是 Cisco 路由器上的一个逻辑接口,它提供了一种将乘客数据包封装在传输协议内的方法。
这种架构旨在为点对点封装方案的实施提供服务。隧道接口有以下三个主要组件:
- 乘客协议(AppleTalk、Banyan VINES、CLNS、DECnet、IPv4 或 IPX)
- 运载载波协议 - 以下封装协议之一:
- GRE - 思科多协议运营商协议。有关详细信息,请参阅 RFC 2784 和 RFC 1701。
- IPv4-in-IPv4 隧道;有关详细信息,请参阅 RFC 2003。
- 传输协议 - 用于传输经过封装的协议。
本部分中的数据包展示了以 GRE 为封装协议、以 IPv4 为传输协议的 IPv4 隧道概念。
乘客协议还是 IPv4。在这种情况下,IPv4 同时是传输协议和乘客协议。
正常数据包
IPv4 | TCP | Telnet |
---|
隧道数据包
IPv4 | GRE | IPv4 | TCP | Telnet |
---|
- IPv4 为传输协议。
- GRE 是封装协议。
- IPv4 为乘客协议。
在下一封装示例中,IPv4 和 DECnet 为乘客协议,GRE 为承载协议。这说明运营商协议封装多个乘客协议的可能性,如图所示。
网络管理员考虑在存在两个不连续非 IPv4 网络(由 IPv4 主干分隔)的情况下建立隧道。
如果不连续网络运行 DECnet,管理员可以选择通过配置主干网中的 DECnet 将它们连接在一起(或不连接)。
管理员不希望允许 DECnet 路由消耗主干带宽,因为这可能会干扰 IPv4 网络的性能。
一种可行的备选方案就是在 IPv4 主干网上通过隧道传输 DECnet。隧道解决方案将 DECnet 数据包封装在 IPv4 中,并通过主干网将它们发送到隧道终端,在那里删除封装,并且 DECnet 数据包通过 DECnet 路由到其目的地。
将流量封装在另一个协议中有一些优点:
- 终端使用私有地址 (RFC 1918),并且主干不支持路由这些地址。
- 允许在 WAN 或 Internet 中建立虚拟专用网络 (VPN)。
- 通过一个单一协议的骨干网将不连续多协议网络连接在一起。
- 通过骨干网或 Internet 对流量进行加密。
之后,IPv4 用作乘客协议,IPv4 用作传输协议。
有关隧道接口的注意事项
以下是建立隧道时的注意事项。
- Cisco IOS® 版本 11.1 中引入了 GRE 隧道的快速交换,版本 12.0 中引入了 CEF 交换。
- 多点 GRE 隧道的 CEF 交换功能是在版本 12.2 (8) T 中引入的。
- 在早期版本的 Cisco IOS® 中,如果仅支持进程交换,则隧道端点上的封装和解封操作会非常慢。
- 对数据包建立隧道时,存在安全和拓扑问题。隧道可以绕过访问控制列表 (ACL) 和防火墙。
- 如果通过防火墙建立隧道,则绕过通过隧道传输的乘客协议。因此,为了对乘客协议执行策略,建议在隧道终端部署防火墙功能。
- 由于延迟增加,隧道会对具有有限计时器(例如 DECnet)的传输协议造成问题。
- 在具有不同速度链路的环境中(例如快速 FDDI 环和通过 9600-bps 慢速电话线),使用隧道会导致数据包重新排序问题。一些乘客协议在混合媒体网络中的运行效率非常低下。
- 点对点隧道会消耗物理链路上的带宽。在多个点对点隧道上,每个隧道接口都有一个带宽,并且运行隧道的物理接口也有一个带宽。例如,如果在 10 Mb 链路上运行了 100 个隧道,请将隧道带宽设置为 100 Kb。隧道的默认带宽是 9 Kb。
- 路由协议更偏爱实际链路上的隧道,因为隧道看似是一跳链路,具有最低开销路径,但实际上它涉及的跳数更多,因此成本也高于另一条路径。通过正确配置路由协议可以缓解此问题。请考虑在隧道接口上运行与物理接口上运行的路由协议不同的路由协议。
- 通过配置通往隧道目的地的适当静态路由,可避免递归路由问题。递归路由指通往隧道目的地的最佳路径就是通过隧道本身。这种情况会导致隧道接口上下跳动。出现递归路由问题时,会出现此错误。
% TUN-RECURDOWN Interface Tunnel 0
temporarily disabled due to recursive routing
在隧道终端作为 PMTUD 参与者的路由器
当路由器作为隧道端点时,它将扮演两种不同的 PMTUD 角色。
- 路由器的第一个作用就是充当主机数据包的转发端。对于 PMTUD 处理,路由器需要检查原始数据包的 DF 位和数据包大小,并在必要时采取相应操作。
- 路由器将原始 IPv4 数据包封装到隧道数据包后,开始发挥第二个作用。在此阶段,路由器的作用对于 PMTUD 和隧道 IPv4 数据包来说更像主机。
当路由器充当第一个角色(转发主机 IPv4 数据包的路由器)时,该角色将在路由器将主机 IPv4 数据包封装到隧道数据包中之前发挥作用。
如果路由器作为主机数据包的转发器参与,它将完成以下操作:
- 检查是否已设置 DF 位。
- 检查隧道可容纳的数据包大小。
- 分段(如果数据包太大,但未设置 DF 位),封装分段并发送;或
- 丢弃数据包(如果数据包太大,且设置了 DF 位),并向发送者发送 ICMP 消息。
- 封装(如果数据包并不太大)并发送。
一般情况下,可以选择先封装再分段(发送两个封装分段)或者先分段再封装(发送两个已封装分段)。
本部分详细介绍 两个示例,它们显示了 PMTUD 与通过示例网络的数据包的交互。第一个示例展示的是在(隧道源中的)路由器充当转发路由器的角色时,数据包发生的情况。要处理 PMTUD,路由器需要检查原始数据包的 DF 位和数据包大小,并采取适当操作。本示例对隧道使用 GRE 封装。GRE 在封装之前执行分段。
后面的示例显示在封装后进行分段的方案。
在示例 1 中,DF 位未设置 (DF = 0),GRE 隧道 IPv4 MTU 为 1476 (1500 - 24) 字节。
示例 1
转发路由器(在隧道源上)从发送主机收到一个 1500 字节且清除 DF 位 (DF = 0) 的数据报。
此数据报由一个 20 字节的 IP 报头和一个 1480 字节的 TCP 负载组成。
IPv4 1480 字节 TCP + 数据 由于在添加 GRE 开销(24 字节)后,数据包对于 IPv4 MTU 而言太大,因此转发路由器将数据报分成 1476(20 字节 IPv4 报头 + 1456 字节 IPv4 负载)和 44 字节(20 字节 IPv4 报头 + 24 字节 IPv4 负载)的两个分段
添加 GRE 封装后,数据包不会大于传出物理接口 MTU。
IP0 1456 字节 TCP + 数据 IP1 24 字节数据 转发路由器将 GRE 封装(包括 4 字节 GRE 报头和 20 字节 IPv4 报头)添加到原始 IPv4 数据报的每个分段。这两个 IPv4 数据报的长度现在分别为 1500 字节和 68 字节,它们被视为单独的 IPv4 数据报,而不是分段。
IPv4 GRE IP0 1456 字节 TCP + 数据 IPv4 GRE IP1 24 字节数据 隧道目标路由器从原始数据报的每个分段中删除 GRE 封装,从而留下两个长度为 1476 和 24 字节的 IPv4 分段。路由器向接收主机单独转发这些 IPv4 数据报分段。
IP0 1456 字节 TCP + 数据 IP1 24 字节数据 接收主机将这两个分段重组为原始数据报。
IPv4 1480 字节 TCP + 数据
示例 2 描述了转发路由器在网络拓扑环境中的角色。
路由器的作用与转发路由器的作用相同,但这次设置了 DF 位 (DF = 1)。
示例 2
位于隧道源的转发路由器从发送主机收到一个 1500 字节的数据报,其中 DF = 1。
IPv4 1480 字节 TCP + 数据 由于设置了 DF 位,并且数据报大小(1500 字节)大于 GRE 隧道 IPv4 MTU (1476),因此路由器会丢弃数据报并向数据报的源发送 “需要进行 ICMP 分段但 DF 位已设置” 消息。ICMP 消息通知发送方 MTU 为 1476。
IPv4 ICMP MTU 1476 发送主机收到 ICMP 消息,在重新发送原始数据时,它使用 1476 字节的 IPv4 数据报。
IPv4 1456 字节 TCP + 数据 此 IPv4 数据报长度(1476 字节)的值现在等于 GRE 隧道 IPv4 MTU,因此路由器会将 GRE 封装添加到 IPv4 数据报。
IPv4 GRE IPv4 1456 字节 TCP + 数据 接收路由器(位于隧道目标位置)删除 IPv4 数据报的 GRE 封装并将其发送到接收主机。
IPv4 1456 字节 TCP + 数据
当路由器充当与 PMTUD 和隧道 IPv4 数据包相关的第二个发送主机时,会发生这种情况。
路由器将原始 IPv4 数据包封装到隧道数据包中后,此角色开始发挥作用。
注意:默认情况下,路由器不会对其生成的 GRE 隧道数据包执行 PMTUD。可以使用 tunnel path-mtu-discovery
命令对 GRE-IPv4 隧道数据包启用 PMTUD。
示例 3 展示的是当主机发送的 IPv4 数据报小到足以适应 GRE 隧道接口上的 IPv4 MTU 时发生的情况。
在此情况下,可以设置或清除 DF 位(1 或 0)。
GRE 隧道接口未配置 tunnel path-mtu-discovery
命令,因此 GRE-IPv4 数据包上的路由器 die 不是 PMTUD。
示例 3
位于隧道源的转发路由器从发送主机接收一个 1476 字节的数据报。
IPv4 1456 字节 TCP + 数据 此路由器将 1476 字节的 IPv4 数据报封装在 GRE 内,以获取 1500 字节的 GRE IPv4 数据报。GRE IPv4 报头中的 DF 位被清除 (DF = 0)。然后,此路由器将此数据包转发到隧道目标。
IPv4 GRE IPv4 1456 字节 TCP + 数据 假设隧道源和目标之间有一个路由器,且链路 MTU 为 1400。由于 DF 位是空的 (DF = 0),因此此路由器对隧道数据包进行分段。请记住,此示例对最外层的 IPv4 进行分段,因此 GRE、内部 IPv4 和 TCP 报头仅显示在第一个分段中。
IP0 GRE IP 1352 字节 TCP + 数据 IP1 104 字节数据 隧道目标路由器必须重组 GRE 隧道数据包。
IP GRE IP 1456 字节 TCP + 数据 重组 GRE 隧道数据包后,路由器会删除 GRE IPv4 报头,并在途中发送原始 IPv4 数据报。
IPv4 1456 字节 TCP + 数据
示例 4 显示当路由器充当发送主机的角色时,对于 PMTUD 和隧道 IPv4 数据包会发生什么情况。
此时,在原始 IPv4 报头中设置了 DF 位 (DF = 1),并且配置了 tunnel path-mtu-discovery
命令,以便将 DF 位从内部 IPv4 报头复制到外部 (GRE + IPv4) 报头。
示例 4
位于隧道源的转发路由器从发送主机收到一个 1476 字节的数据报,其中 DF = 1。
IPv4 1456 字节 TCP + 数据 此路由器将 1476 字节的 IPv4 数据报封装在 GRE 内,以获取 1500 字节的 GRE IPv4 数据报。此 GRE IPv4 报头设置了 DF 位 (DF = 1),因为原始 IPv4 数据报设置了 DF 位。然后,此路由器将此数据包转发到隧道目标。
IPv4 GRE IPv4 1456 字节 TCP 同样,假设隧道源和目标之间有一个路由器,且链路 MTU 为 1400。由于设置了 DF 位 (DF=1),此路由器不会对隧道数据包进行分段。此路由器必须丢弃数据包并向隧道源路由器发送 ICMP 错误消息,因为它是数据包上的源 IPv4 地址。
IPv4 ICMP MTU 1400 位于隧道源的转发路由器收到此 “ICMP” 错误消息,并将 GRE 隧道 IPv4 MTU 降至 1376 (1400 - 24)。下一次发送主机重新传输 1476 字节的 IPv4 数据包中的数据时,该数据包可能太大,然后路由器会向发送方发送 “ICMP” 错误消息,MTU 值为 1376。当发送主机重新传输数据时,它会以 1376 字节的 IPv4 数据包的形式发送数据,此数据包会通过 GRE 隧道发送到接收主机。
示例 5
本示例说明 GRE 分段。先对 GRE 进行分段,再对数据包执行 PMTUD,当 IPv4 数据包由 GRE 封装时,不会复制 DF 位。未设置 DF 位。GRE 隧道接口的 IPv4 MTU 默认比物理接口的 IPv4 MTU 少 24 字节,因此 GRE 接口的 IPv4 MTU 为 1476 字节,如下图所示。
- 发送端发送一个 1500 字节的数据包(20 字节 IPv4 报头 + 1480 字节 TCP 负载)。
- 由于 GRE 隧道的 MTU 是 1476,因此 1500 字节的数据包将被分解为两个 IPv4 分段(1476 和 44 字节),每个分段预计会额外增加 24 个字节的 GRE 报头。
- 每个 IPv4 分段增加 24 字节的 GRE 报头。现在,两个分段分别为 1500 字节 (1476 + 24) 和 68 字节 (44 + 24)。
- 包含两个 IPv4 分段的 GRE + IPv4 数据包被转发到 GRE 隧道对等路由器。
- GRE 隧道对等路由器将删除两个数据包中的 GRE 报头。
- 此路由器将两个数据包转发到目标主机。
- 目标主机将 IPv4 分段重组为原始 IPv4 数据报。
示例 6
此示例与示例 5 类似,但这次设置了 DF 位。使用 tunnel path-mtu-discovery
命令将路由器配置为对 GRE + IPv4 隧道数据包执行 PMTUD,并且 DF 位从原始 IPv4 报头被复制到 GRE IPv4 报头。如果路由器收到面向 GRE + IPv4 数据包的 ICMP 错误,则会降低 GRE 隧道接口的 IPv4 MTU 值。
默认情况下,GRE 隧道 IPv4 MTU 设置为比物理接口 MTU 小 24 字节,因此,此处的 GRE IPv4 MTU 为 1476。GRE 隧道路径中有一个 1400 MTU 链路,如图所示。
- 路由器收到 1500 字节的数据包(20 字节 IPv4 报头 + 1480 字节 TCP 负载),然后丢弃该数据包。路由器丢弃数据包是因为该数据包大于 GRE 隧道接口上的 IPv4 MTU (1476)。
- 路由器向发送者发送一条 ICMP 错误,通知发送者下一跳 MTU 为 1476。主机在其路由表中记录此信息,通常作为目的主机路由。
- 当重新发送数据时,发送主机采用 1476 字节作为数据包大小。GRE 路由器添加 24 字节的 GRE 封装,然后发送一个 1500 字节的数据包。
- 该 1500 字节的数据包无法通过 1400 字节的链路,因此中间路由器将丢弃该数据包。
- 中间路由器将向 GRE 路由器发送一个含有下一跳 MTU 为 1400 的 ICMP(类型 = 3,代码 = 4)。GRE 路由器将其降低至 1376 (1400 - 24) 字节,并在 GRE 接口上设置内部 IPv4 MTU 值。仅当使用
debug tunnel
命令时,才会显示此更改;而在show ip interface tunnel<#>
命令的输出中不会看到此更改。 - 下次主机重新发送 1476 字节的数据包时,GRE 路由器会丢弃该数据包,因为它大于 GRE 隧道接口上当前的 IPv4 MTU (1376)。
- GRE 路由器向下一跳 MTU 为 1376 的发送方发送另一个 ICMP(类型 = 3,代码 = 4),主机使用新值更新其当前信息。
- 主机再次重新发送数据,但现在 GRE 在一个较小的 1376 字节数据包中添加 24 字节的封装,然后继续转发。此时,数据包到达 GRE 隧道对等体,数据包在该隧道中解封并发送到目的主机。
注意:如果在本案例中,转发路由器上没有配置 tunnel path-mtu-discovery
命令,并且 DF 位设置在 GRE 隧道转发的数据包中,那么主机 1 向主机 2 仍成功发送 TCP/IPv4 数据包,但它们在 1400 MTU 链路的中途分段。此外,GRE 隧道必须在解封装和转发数据包前,对数据包进行重组。
纯 IPsec 隧道模式
IPv4 安全 (IPv4sec) 协议是一种基于标准的方法,用于确保 IPv4 网络上传输的信息保密、完整且真实。
IPv4sec 提供 IPv4 网络层加密。IPv4sec 通过添加至少一个 IPv4 报头(隧道模式)而加长 IPv4 数据包。
添加的报头长度因 IPv4sec 配置模式而异,但每个数据包不超过—58 个字节 (封装安全负载 (ESP) 和 ESP 身份验证 (ESPauth))。
IPv4sec 有两种模式:隧道模式和传送模式。
- 隧道模式是默认模式。在隧道模式下,整个原始 IPv4 数据包都受到保护(加密、身份验证或两者同时执行),并由 IPv4sec 报头和报尾进行封装。然后,新的 IPv4 报信头附加到数据包前面,用于将 IPv4sec 终端(对等体)指定为源端和目标端。隧道模式可用于任何单播 IPv4 流量,但如果将 IPv4sec 用于保护来自 IPv4sec 对等体背后的主机流量,则必须使用隧道模式。例如,隧道模式可与虚拟专用网络 (VPN) 结合使用,其中通过一组 IPv4sec 对等体,一个受保护网络上的主机可向另一个受保护网络上的主机发送数据包。在 VPN 网络中,IPv4sec 隧道通过加密 IPv4sec 对等路由器间的流量来保护主机之间的 IPv4 流量。
- 使用传输模式 (在转换定义上使用子命令
mode transport
配置),仅原始 IPv4 数据包的负载受保护(加密、认证或两者)。负载由 IPv4sec 报头和报尾封装。原始 IPv4 报头保持不变,只不过 IPv4 协议字段更改为 ESP (50),而原始协议值保存在 IPv4sec 报尾,并在解密数据包时恢复。只有在要保护的 IPv4 流量位于 IPv4sec 对等体之间,并且数据包上的源和目标 IPv4 地址都与 IPv4sec 对等体地址相同时,才使用传送模式。正常情况下,只有在使用另一种隧道协议(例如 GRE)来首先封装 IPv4 数据包,然后使用 IPv4sec 保护 GRE 隧道数据包的情况下,才会使用 IPv4sec 传送模式。
对于数据包和自己的数据包,IPv4sec 始终会执行 PMTUD。可以使用 IPv4sec 配置命令来修改对 IPv4sec IPv4 数据包的 PMTUD 处理,IPv4sec 可以清除、设置 DF 位,或将 DF 位从数据包 IPv4 报头复制到 IPv4sec IPv4 报头。该功能称为 “DF 位覆盖功能”。
注意:完成 IPv4sec 硬件加密后,请避免在封装后进行分段。硬件加密可提供约 50 Mbs 的吞吐量(取决于硬件),但如果对 IPv4sec 数据包进行分段,则会丢失 50% 至 90% 的吞吐量。这是因为分段的 IPv4sec 数据包重组时会经过进程交换,然后传送给硬件加密引擎进行解密。上述吞吐量损失会使硬件加密吞吐量降至软件加密的性能水平 (2 - 10 Mbs)。
示例 7
本场景描述的是 IPv4sec 分段过程。在此方案中,整个路径上的 MTU 为 1500。在此方案中,未设置 DF 位。
- 路由器收到发往主机 2 的 1500 字节的数据包(20 字节 IPv4 报头 + 1480 字节 TCP 负载)。
- 1500 字节的数据包经过 IPv4sec 加密,增加了 52 字节的开销(IPv4sec 报头、报尾和另外的 IPv4 报头)。现在 IPv4sec 需要发送 1552 字节的数据包。由于出站 MTU 为 1500,因此必须对此数据包进行分段。
- IPv4sec 数据包被拆分为两个分段。在分段期间,将为第二个分段添加额外的 20 字节 IPv4 报头,从而生成一个 1500 字节的分段和 72 字节的 IPv4 分段。
- IPv4sec 隧道对等路由器接收分段,剥离附加的 IPv4 报头,并将 IPv4 分段合并为原始 IPv4sec 数据包。然后 IPv4sec 解密该数据包。
- 最后,路由器将 1500 字节的原始数据包转发到主机 2。
示例 8
此示例与示例 6 类似,不同之处在于,在这种情况下,原始数据包中设置了 DF 位,并且 IPv4sec 隧道对等体之间的路径上存在一条链路,其 MTU 低于其他链路。
本示例说明 IPv4sec 对等路由器如何执行两种 PMTUD 角色,如 在隧道终端作为 PMTUD 参与者的路由器 部分所述。由于需要分段,IPv4sec PMTU 变为较低的值。_
当 IPv4sec 加密数据包时,DF 位从内部 IPv4 报头复制到外部 IPv4 报头。
介质 MTU 和 PMTU 值存储在 IPv4sec 安全关联 (SA) 中。
介质 MTU 基于出站路由器接口的 MTU,而 PMTU 基于 IPv4sec 对等体间路径上看到的最小 MTU。
如图所示,IPv4sec 在数据包尝试分段之前会对其进行封装 / 加密。
路由器收到一个 1500 字节的数据包并将其丢弃,因为添加的 IPv4sec 开销会使数据包大于 PMTU (1500)。
路由器向主机 1 发送一条 ICMP 消息,并通知该主机下一跳 MTU 为 1442 (1500 - 58 = 1442)。此 58 字节是使用 IPv4sec ESP 和 ESPauth 时的最大 IPv4sec 开销。实际 IPv4sec 开销可能比此值小 7 个字节。主机 1 通常在其路由表中以目标(主机 2)主机路由的形式记录该信息。
主机 1 将主机 2 的 PMTU 降低到 1442,因此主机 1 在将数据重新传输到主机 2 时发送更小(1442 字节)的数据包。路由器接收 1442 字节的数据包,然后 IPv4sec 添加 52 字节的加密开销,由此产生 1496 字节的 IPv4sec 数据包。由于此数据包的报头中设置了 DF 位,因此,采用 1400 字节 MTU
链路的中间路由器将丢弃此数据包。
丢弃数据包的中间路由器向 IPv4sec 数据包的发送端(第一个路由器)发送一条 ICMP 消息,告知发送端下一跳 MTU 为 1400 字节。这个值记录在 IPv4sec 安全关联 (SA) 的 PMTU 中。
主机 1 下次重新传输 1442 字节的数据包(它未收到确认)时,IPv4sec 将丢弃该数据包。路由器会丢弃数据包,因为添加到数据包中的 IPv4sec 开销会使其大于 PMTU (1400)。
路由器向主机 1 发送 ICMP 消息,告知其下一跳 MTU 现在为 1342。(1400 - 58 = 1342)。主机 1 再次记录此信息。
当主机 1 再次重新传输数据时,它使用较小的数据包 (1342)。此数据包不需要分段,而是通过 IPv4sec 隧道到达主机 2。
GRE 与 IPv4sec 协同工作
使用 IPv4sec 来加密 GRE 隧道时,分段和 PMTUD 的交互会更为复杂。
IPv4sec 和 GRE 以这种方式组合是因为 IPv4sec 不支持 IPv4 组播数据包,这意味着在 IPv4sec VPN 网络上无法运行动态路由协议。
GRE 隧道支持组播,因此可先使用 GRE 隧道加密 GRE IPv4 单播数据包中的动态路由协议组播数据包,然后再使用 IPv4sec 加密单播数据包。
执行此操作时,通常在 GRE 之上以传输模式部署 IPv4sec,因为 IPv4sec 对等体和 GRE 隧道终端(路由器)相同,并且传输模式可节省 20 字节的 IPv4sec 开销。
有个有趣的案例,其中 IPv4 数据包被拆分为两个分段,并采用 GRE 封装。在这种情况下,IPv4sec 将看到两个独立的 GRE + IPv4 数据包。通常,在默认配置中,这些数据包中有一个足够大,需要在加密后进行分段。
IPv4sec 对等体必须在解密之前重组此数据包。这种发送路由器上的 “两次分段”(GRE 前一次,IPv4sec 后一次)会提高时延,并降低吞吐量。重组是进程交换的,因此每当发生这种情况时,接收路由器上都会发生 CPU 命中。
如果考虑 GRE 和 IPv4sec 开销而将 GRE 隧道接口的 “ip mtu” 设置得足够低,则可以避免这种情况(默认情况下,GRE 隧道接口 “ip mtu” 被设置为实际传出接口 MTU 值 - GRE 开销字节数)。
此表列出了假设传出物理接口的 MTU 为 1500 的每个隧道 / 模式组合的建议 MTU 值。
隧道组合 | 需要的特定 MTU | 建议的 MTU |
---|---|---|
GRE + IPv4sec(传送模式) | 1440 字节 | 1400 字节 |
GRE + IPv4sec(隧道模式) | 1420 字节 | 1400 字节 |
注意:建议将 MTU 值设置为 1400 字节,因为该值涵盖了最常见的 GRE + IPv4sec 模式组合。并且,额外允许 20 或 40 字节的开销不会产生显著的负面影响。记住并设置一个值相对较容易,并且该值几乎涵盖了所有情况。
示例 9
IPv4sec 部署在 GRE 之上。传出物理 MTU 为 1500,IPv4sec PMTU 为 1500,GRE IPv4 MTU 为 1476 (1500 - 24 = 1476)。
因此,TCP/IPv4 数据包分片两次,一次在 GRE 之前,一次在 IPv4sec 之后。
数据包在 GRE 封装之前分段,其中一个 GRE 数据包在 IPv4sec 加密之后再次分段。
在本场景下,如果在 GRE 隧道上配置 “ip mtu 1440”(IPv4sec 传送模式)或 “ip mtu 1420”(IPv4sec 隧道模式),则可以消除两次分段的可能性。
- 路由器收到一个 1500 字节的数据报。
- 在封装之前,GRE 将 1500 字节的数据包拆分为两个分段,一个 1476 字节 (1500 - 24 = 1476),另一个 44 字节(24 字节数据 + 20 字节 IPv4 报头)。
- GRE 封装 IPv4 分段,该过程将导致每个数据包增加 24 字节。因而将产生两个 GRE + IPv4sec 字段,一个 1500 字节 (1476 + 24 = 1500),另一个 68 字节 (44 + 24 = 68)。
- IPv4sec 对这两个数据包进行加密,每个数据包会增加 52 字节(IPv4sec 隧道模式)的封装开销,从而产生 1552 字节和 120 字节的数据包。
- 由于 1552 字节的 IPv4sec 数据包大于出站 MTU (1500),因此,路由器会将其分段。1552 字节的数据包被拆分为 1500 字节的数据包和 72 字节的数据包(52 字节负载加上为第二个分段附加的 20 字节 IPv4 报头)。三个数据包(1500 字节、72 字节和 120 字节)被转发到 IPv4sec + GRE 对等设备。
- 接收路由器重组两个 IPv4sec 分段(1500 字节和 72 字节),以便获取原始 1552 字节的 IPv4sec + GRE 数据包。对于 120 字节的 IPv4sec + GRE 数据包无需任何操作。
- IPv4sec 对 1552 字节和 120 字节的 IPv4sec + GRE 数据包进行解密,以便获取 1500 字节和 68 字节的 GRE 数据包。
- GRE 解封装 1500 字节和 68 字节的 GRE 数据包,以便获取 1476 字节和 44 字节的 IPv4 数据包分段。然后这些 IPv4 数据包分段被转发到目标主机。
- 主机 2 重组这些 IPv4 分段,以便获取原始 1500 字节的 IPv4 数据报。
示例 10
本示例与示例 8 相似,不同之处在于示例 10 的隧道路径中存在更小 MTU 的链路。对于从主机 1 发往主机 2 的第一个数据包而言,这是最糟糕的场景。在完成本示例的最后一步后,主机 1 为主机 2 设置正确的 PMTU,并都适合主机 1 和主机 2 之间的 TCP 连接。主机 1 与其他主机(可通过 IPv4sec + GRE 隧道访问)之间的 TCP 流只需经过示例 10 的最后三个步骤。
在本场景中,GRE 隧道上配置了 tunnel path-mtu-discovery
命令,并且在来自主机 1 的 TCP/IPv4 数据包上设置了 DF 位。
路由器收到一个 1500 字节的数据包。由于设置了 DF 位,并且在增加 GRE 开销(24 字节)之后数据包大小超过出站接口 “ip mtu”,因此 GRE 无法对该数据包进行分段或转发,并丢弃此数据包。
路由器向主机 1 发送 ICMP 消息,以便该主机知晓下一跳 MTU 为 1476 (1500 - 24 = 1476)。
主机 1 针对主机 2 将其 PMTU 更改为 1476,并在重新传输数据包时发送更小大小。GRE 封装数据包,并将 1500 字节的数据包传递给 IPv4sec。由于 GRE 从内部 IPv4 报头中复制了 DF 位(已设置),并且加上 IPv4sec 开销(最大 38 字节)后,数据包因太大而无法传出物理接口,因此 IPv4sec 丢弃该数据包。
IPv4sec 向 GRE 发送 ICMP 消息,指明下一跳 MTU 为 1462 字节(因为加密和 IPv4 开销最多添加 38 字节)。GRE 在隧道接口上将值 1438 (1462 - 24) 记录为 “ip mtu”。
- 注意:值的更改在内部存储,无法在
show ip interface tunnel<#>
命令输出中看到。仅当改用debug tunnel
命令时,才会显示此更改。
- 注意:值的更改在内部存储,无法在
主机 1 下次重新传输 1476 字节的数据包时,GRE 将丢弃此数据包。
路由器向主机 1 发送 ICMP 消息,指明下一跳 MTU 为 1438。
主机 1 针对主机 2 减小其 PMTU,并重新传输 1438 字节的数据包。这次 GRE 接受该数据包,对其进行封装,并将其传递给 IPv4sec 进行加密。
IPv4sec 数据包被转发到中间路由器并被丢弃,因为该路由器出站接口 MTU 为 1400。
中间路由器向 IPv4sec 发送 ICMP 消息,指明下一跳 MTU 为 1400。IPv4sec 将该值记录在关联 IPv4sec 安全关联 (SA) 的 PMTU 值中。
当主机 1 重新传输 1438 字节的数据包时,GRE 封装该数据包,然后将其传递给 IPv4sec。IPv4sec 丢弃该数据包,因为其已将自己的 PMTU 改为 1400。
IPv4sec 向 GRE 发送 ICMP 错误消息,指明下一跳 MTU 为 1362,并且 GRE 在内部记录值 1338。
当主机 1 重新传输原始信息包时 (因为没有收到确认),GRE 将丢弃它。
路由器向主机 1 发送 ICMP 消息,指明下一跳 MTU 为 1338(1362 - 24 字节)。主机 1 针对主机 2 将其 PMTU 减小至 1338。
主机 1 转发 1338 字节信息包,同时它可以最终到达主机 2。
其他建议
如果在同一台路由器上配置了 GRE 和 IPv4sec,则在隧道接口上配置 tunnel path-mtu-discovery
命令可以帮助 GRE 和 IPv4sec 交互。
如果未配置 tunnel path-mtu-discovery
命令,GRE IPv4 报头中将始终会清除 DF 位。这样便可对 GRE IPv4 数据包进行分段,即使已封装的数据 IPv4 报头设置了 DF 位(通常不允许对数据包进行分段)也是如此。
如果在 GRE 隧道接口上配置了 tunnel path-mtu-discovery
命令:
- GRE 将 DF 位从数据 IPv4 报头复制到 GRE IPv4 报头。
- 如果在 GRE IPv4 报头中设置了 DF 位,并且数据包在物理传出接口上的 IPv4 MTU 经过 IPv4sec 加密后 “过大”,则 IPv4sec 将丢弃数据包并通知 GRE 隧道减小其 IPv4 MTU 大小。
- IPv4sec 对其自己的数据包执行 PMTUD,如果 IPv4sec PMTU 更改(如果减少),则 IPv4sec 不会立即通知 GRE,但当另一个更大的数据包通过时,则会执行第 2 步中的过程。
- GRE IPv4 MTU 现在更小,因此它会丢弃任何设置了 DF 位且现在过大的数据 IPv4 数据包,并向发送主机发送 ICMP 消息。
tunnel path-mtu-discovery
命令有助于 GRE 接口动态设置其 IPv4 MTU,而非使用 ip mtu
命令静态设置。实际上,建议同时使用这两个命令。
ip mtu
命令用于为 GRE 和 IPv4sec 开销提供空间(相对于本地物理传出接口的 IPv4 MTU)。
如果 IPv4sec 对等体之间的路径上存在 IPv4 MTU 更小的链路,tunnel path-mtu-discovery
命令允许 GRE 隧道 IPv4 MTU 进一步减小。
如果在已配置 GRE + IPv4sec 隧道的网络中有 PMTUD 相关的问题,可以参考以下解决方案。
下面列表从最可取的解决方案开始列出。
- 修复 PMTUD 无法正常工作的问题,这通常是由阻止 ICMP 的路由器或防火墙造成的。
- 在隧道接口上使用
ip tcp adjust-mss
命令,以使路由器减小 TCP SYN 数据包中的 TCP MSS 值。这有助于两个终端主机(TCP 发送方和接收方)使用足够小的数据包,以便不需要 PMTUD。 - 在路由器的入口接口上使用策略路由并配置路由映射,从而在 DF 位传入 GRE 隧道接口之前,清除数据 IPv4 报头中的 DF 位。这允许在 GRE 封装之前对数据 IPv4 数据包进行分段。
- 在 GRE 隧道接口上增大 “ip mtu”,使其等于出站接口 MTU。这允许数据 IPv4 数据包进行 GRE 封装,而无需首先对其进行分段。然后,对 GRE 数据包进行 IPv4sec 加密,然后进行分段以传出物理出站接口。在此种情况下,您不必在 GRE 隧道接口上配置
tunnel path-mtu-discovery
命令。由于 IPv4sec 对等体上的 IPv4 数据包重组在进程交换模式下进行,因此这可以极大减少吞吐量。
相关信息
- IP 路由 支持页
- IPSec(IP 安全协议)支持页
- RFC 1191 路径 MTU 发现
- RFC 1063 IP MTU 发现选项
- RFC 791 Internet 协议
- RFC 793 传输控制协议
- RFC 879 TCP 最大数据段大小和相关主题
- RFC 1701 通用路由封装 (GRE)
- RFC 1241 Internet 封装协议方案
- RFC 2003 IP 中的 IP 封装
- 技术支持和文档 - Cisco Systems
修订历史记录
版本 | 发布日期 | 备注 |
---|---|---|
4.0 | 17-May-2023 | 已更新 “相关信息” 部分。 |
3.0 | 20-Dec-2022 | 向图像添加了 Alt Text。 已将图像.gif 更改为.png。 已更新简介错误、机器翻译、样式要求、动词和格式。 |
1.0 | 29-Jul-2002 | 初始版本 |
MTU 设置不合理,导致的链路不通问题的排查处理
Bogon IP属地: 广东
发布于:2022.06.17 00:07:10
最后编辑于 :2022.09.27 08:04:00
一、现象
现象 1
Server A 调用本机的接口能正常返回,调用 Server B 的接口总是超时。被调用接口是能正常执行的,而且有执行日志记录。
Server C 调用 Server B 的接口也能正常返回。
分析
根据以上,基本可以排除是 Server B 接口服务的问题导致超时,很有可能 Server A 与 Server B 之间的网络有问题,于是决定通过抓包分析。
Server A 调用 Server B 接口时,抓包情况如下:
可见,在调用 Server B 的接口时,重试很严重。见上图的黑色行。当 MTU 值或者 MSS 值设置不合适时,会导致这样的问题出现。
首先查看当前 MTU 的值是多少。
Linux 下查看方式如下:
再看这个 MTU 值设置多少合适。使用 ping 命令检测。
-s
参数说明包的大小,后面的 IP 可以设置为任何一个可以 ping 通的 IP。
当返回值如下时,表示包的大小设置的过大,可以调小:
当出现如下的结果时,说明包大小设置的正常了。
解决
经过上面的 ping 测试,我们可以知道原先的 MTU 值为 9001,设置的过大,应该改成 2000。
有多种修改的方式,下面就介绍一种。
设置完成后,再次抓包,情况如下:
拓展
MTU && MSS
MTU: Maxitum Transmission Unit 最大传输单元
MSS: TCP 数据包每次能够传输的最大数据分段
为了达到最佳的传输效能,TCP 协议在建立连接的时候通常要协商双方的 MSS 值,这个值 TCP 协议在实现的时候往往用 MTU 值代替(需要减去 IP 数据包包头的大小 20Bytes 和 TCP 数据段的包头 20Bytes),所以往往 MSS 为 1460。通讯双方会根据双方提供的 MSS 值得最小值确定为这次连接的最大 MSS 值。
现象 2
在学校搭建好 VPN 服务,回到家却发现连上就上不了网!
在学校时科学上网没问题,回到家连接上了就上不了网。
用基本的测试方法 ipconfig /all 看到有以太网网卡有 ip,dns 也正常,然后看看 VPN 连接状态,有 ip,DNS8.8.8.8 ,突然发现没有网关。
然后尝试改网关,用 route print 看看路由表的信息,然后用 route change ip mask 掩码 网关。改好了,然后重启一下 VPN 发现还是空,行不通。
上网查了下,需要取消√的 VPN 的 “在远程网络上使用默认网关”。然后竟然成功了,在连接 VPN 的情况下可以上网了。
不过还是不能科学上网,后来咨询了大神,他告诉我 PPP(点对点)不需要网关。
在服务器上执行如下命令。就可以科学上网了!
iptables -I FORWARD -p tcp --syn -s 10.82.88.0/24 -j TCPMSS --set-mss 1256
从家里出发有个路由器 MTU 不是 1500,封装的数据包还是封装成 1500,但是路径上有 MTU 小于 1500 的,数据包有不分包标记,然后那个数据包就被丢弃了,丢弃了当然也就上不了网。
上面的命令就是改 MSS 为 1256,加上包头,就等于间接把 MTU 改小成 1256 + 包头,小于某路由的 MTU,包就不会丢弃,然后就能顺利传输。
现象 3
装完虚拟机(win)之后发现无法打开部分网站,以百度为例 www.baidu.com 可以看到 302 消息,跳转后 https://www.baidu.com 就超时了,而另外一部分网站是正常的。
使用 curl -v
可以看到在收到服务器发来的 hello 后卡住不响应。
wireshark 抓包发现百度回复了几个包,其中有一条警告是 Ignored Unknown Record ,猜测是包被拆分后出现了点问题所以不认识,搜索这个警告信息确实有类似的案例 HTTPS Websites Not Reachable
修改 MTU 后问题解决,同样的,在其他某些虚拟机上如果有不合适的 MTU 也会打不开百度。
MTU 不是只会影响性能速度吗,怎么这都影响到功能了?
MTU 不合适会直接丢掉包,不只是影响速度。
不过我见过的一般是丢掉第一个包,收到一条 ICMP 消息后重新协商。
你给的链接似乎是用了他家的产品才会有这样的问题。
家用所有设备设置 1480 保持 MTU 对齐就行了,1492 没必要提升不了什么网速,其实更希望运营商把局端和光猫之间的 MTU 改为 1528,这样直接 MTU1500+8pppoe 头,最标准的 MTU 了。
我碰到过因为 MTU 问题导致 https 地址不能访问的问题。
大致的问题是中间链路上某个设备不支持这么大的 MTU 的时候,会给源地址发一个 icmp 协议的包,让源拆成小包之后再发,但是很多设备对这个 icmp 的报文支持的并不友好,从抓包上看到一直重传,超过次数之后就放弃了。
MTU 协商失败会导致 SSL 协商故障。
如果是 ipv6 的话可能会出现这个问题,因为 ipv6 在超出 mtu 以后不会像 ipv4 一样拆包重传,而是回一个 toobig 给发送方。
如果发送方(网站)配置不合理(特别是负载均衡配置不合理)不能正确转发 / 处理 toobig,同时你的运营商没有做 mssfix,就可能出现这个问题。
现象 4
工作中遇到一件怪事,在服务端服务器上搭建好服务后(VPN 服务,创建了虚拟网卡),服务器和客户端之间响应正常且很稳定。客户端也能正常通过服务器访问外网,但是访问个别网站时可以打开文字,但是部分图片打不开(也不是所有图片打不开)。
根据以上现象,基本排除了虚拟接口或者物理接口有问题,怀疑客户端和服务器之间的网络问题,或者服务器的物理网卡上的数据没有全部给虚拟网卡。所以在服务器的物理网卡和虚拟网卡上同时抓包,客户端的网卡上也抓包,看报文到底丢在哪里了。
有三种丢包的可能:
- 客户端的加载图片的 HTTP 请求没有送到服务器,可能性较小,因为有些图片是可以打开的。
- 图片数据经过服务器的物理网卡 eth0 后没有正确传给虚拟网卡
- 服务器虚拟网卡在转发图片时丢包
分析
MTU 是数据链路层的概念,表示接口的最大传输单元,一般情况下指的是接口所能传输 IP 报文的最大长度。
默认以太网接口 MTU 为 1500,那么传输长度为 1490 大小的 IP 报文完全没有问题。
VPN 隧道携带了一层层封装,比如 IPsec 报文。
这样就会导致封装过后的新 IP 报文长度可能会大于接口的 MTU 值,IPsec 为了确保传输报文不大于物理接口的 MTU 值,所以规定了隧道自己的 MTU 值,即 Path MTU,即要求被封装的报文长度不能大于这个值,否则将被分片处理。
Path MTU 在 ipsec sa 中可以看到,这个值不是固定的,因为每个隧道使用的模式和算法不同。
很多业务类型是基于 TCP 的,TCP 的 IP 报文 header 通常明确指定了本报文不能给分片(Don’t fragment)。
这样的话,就必须使得载荷为 TCP 业务的 IP 报文长度必须小于 Path MTU,否则将被 IPsec 隧道丢弃,MTU check failure 会一直增长。
IP 报文不可以被分片,但是 TCP 报文可以。
TCP 三次握手的时候,头部会有协商 MSS(Maximum segment size)的选项,在一长串网络设备中,以设置最小的 MSS 来传输 TCP 报文。
所以我们需要将 TCP MSS 调小以保证 TCP 报文长度变小,这样 IP 报文长度也会变小,经过 IPsec 隧道时就不会被隧道 MTU 限制。
TCP MSS 设置为多少合适呢?
由于 TCP 业务报文的 IP 头和 TCP 头长度都是 20 字节,那么 IP 场景下:
TCP MSS = Path MTU – IP Header – TCP Header = Path MTU – 40
比如 Path = 1428,那么在内外网口下设置 TCP MSS 为 1388 就可以,小一点也没关系,但是不能太小,否则 TCP 报文重组也会消耗一定性能。
综上,不能调整接口 MTU,要调整只能调整 TCP MSS。
二、设置 MSS 调整 MTU
在实际环境中,往往出现在某个链路上 MTU 不规范,比正常的 MTU (1500) 要小。
从理论上讲,出现这种情况后,应由路由器发送 ICMP 告知发送端调整 MTU,但是由于网络比较复杂,该告知无法到达发送者。
如下图所示,中间路由器的通路的 MTU 为 1496。这导致网络两侧设备通讯时,小包可以通过,但是大包无法通过。
现象就是可以 ping 通,但是无法下载数据或者打开页面。
防火墙可以调整 TCP 通讯的 MSS 值,使得链路两端的设备通讯时不发送 MTU 为 1500 的数据包,从而避免丢包事件。
MTU: Maxitum Transmission Unit 最大传输单元
MSS: Maxitum Segment Size 最大分段大小
由于以太网 EthernetII 最大的数据帧是 1518Bytes 这样,刨去以太网帧的帧头(DMAC 目的地址 MAC48bit = 6Bytes + SMAC 源 MAC 地址 48bit = 6Bytes + Type 域 2bytes)14Bytes 和帧尾 CRC 校验部分 4Bytes(这个部分有时候大家也把它叫做 FCS),那么剩下承载上层协议的地方也就是 Data 域最大就只能有 1500Bytes. 这个值我们就把它称之为 MTU。
MSS 就是 TCP 数据包每次能够传输的最大数据分段。
为了达到最佳的传输效能,TCP 协议在建立连接的时候通常要协商双方的 MSS 值,这个值 TCP 协议在实现的时候往往用 MTU 值代替(需要减去 IP 数据包包头的大小 20Bytes 和 TCP 数据段的包头 20Bytes)所以往往 MSS 为 1460。
通讯双方会根据双方提供的 MSS 值得最小值确定为这次连接的最大 MSS 值。也就是说,在上图的案例中 MTU 值为 1496,那么我们可以通过调整 MSS 为 1496 - 40 = 1456, 来达到调整发包大小满足 MTU 的要求。
当然如果不清楚中间链路的具体 MTU,可以再往小处调整。该方法的缺点是需要调整所有的策略。
三、关于 TCP segment of a reassembled PDU
windows 下 wireshark 抓包经常会出现 “TCP segment of a reassembled PDU” 提示:
可通过 wireshark 的 Edit --> Preferences --> Protocols/TCP --> Allow subdissector to reassemble TCP streams 取消勾选该选项可消除提示:
网上大部分转载文章都在争论显示 TCP segment of a reassembled PDU 的 ACK 序号是一样的,所以显示提示,其实与 ACK 没啥关系。
问题的关键在于报文长度 2194 字节,已超出 MTU 的 1500 大小,所以提示 TCP segment。
MTU Max Transmit Unit,1500,可通过 ifconfig 查看
MSS Max Segment Size,1460 = 1500 - 20 - 20
PDU Protocol Data Unit
NIC 传输的最大报文长度为 1514 字节 = MTU + Ether = 1500 + 14
那问题来了,2194 字节报文为什么是正常的,为何没有经过 IP 分片?
因为现代 OS 支持网络分载(TSO)功能,由 NIC 代替 CPU 实现 packet 的分段和合并,节省系统资源,让系统处理更多的连接。
TSO TCP Segment Offload
LSO Large Segment Offload
GSO Generic Segment Offload
LRO Large Receive Offload
RSC Receive Segment Coalescing
发送过程:
Many operating systems and NIC drivers support TCP Segmentation Offload (TSO) aka Large Segment Offload (LSO) aka Generic Segment Offload (GSO). What this means is that the TCP stack sends a chunk of data for the NIC to break up into Maximum Segment Size (MSS) pieces to send on the network. TCP might hand the NIC 16k of data and the NIC will break it into MSS sized bites: 11 segments of 1460 bytes and one segment of the remaining 324 bytes. This offloads the task to the NIC and saves overhead on the host’s resources. It’s a performance thing.
当 TCP 协议栈发送大块数据时,由 NIC 来进行分段。由于适配器硬件完成数据分段的速度比操作系统软件快得多,此功能可能会提高传输性能。此外,适配器使用的 CPU 资源较少。
接收过程:
Large Receive Offload (LRO) or Receive Segment Coalescing (RSC). The is the same thing but in reverse. The NIC coalesces TCP segments it receives from a remote host into larger packets before sending them up to the TCP stack.
过程与发送相反,NIC 会将接收到的数据合并成大的数据包,然后发送至 TCP/IP 协议栈。
如图 wireshark 工作在 NIC 和协议栈之间,抓取的是网卡上的数据,此时数据包长度可能大于 MTU。
四、合理设置操作系统网卡的 MTU 值
当最大传输单元(MTU)设置不合理时,会引发以下问题:
- 若本地 MTU 值大于网络 MTU 值,本地传输的数据包尺寸过大,致使网络在传输过程中需对数据包进行拆分。这不仅会产生额外的数据包,还会消耗用于拆包和组包的时间资源。
- 若本地 MTU 值小于网络 MTU 值,本地传输的数据包虽可直接传输,但未能充分利用网络所允许的数据包传输尺寸上限,从而导致传输能力无法得到完全发挥。
合理的 MTU 值定义
合理的 MTU 值设置应使本地 MTU 值与网络的 MTU 值保持一致,如此便能避免数据包大小超出网络传输的 MTU 值限制,进而无需进行拆包、组包及转发等额外操作。简而言之,合理设置 MTU 值就是确保本地与网络的 MTU 值相同,既能充分发挥传输性能,又可避免数据包被拆分。
探测合理 MTU 值的方法
- Linux 系统下探测 MTU 值
ping -s 1460 -M do baidu.com
- Windows 系统下探测 MTU 值
ping -f -l 1460 baidu.com
上述命令中,发送的数据包大小为 1460(+28)字节,并禁止路由器对数据包进行拆分操作。
回复结果分析:
- 若能收到正常回复,表明网络所允许的最大 MTU 为 1500 字节,此值与系统默认值相同。此时,只需将自身路由的 MTU 也设置为 1500 字节即可。
- 若未收到正常回复,则说明发送的数据包大小超过了网络所限定的 MTU 大小。在这种情况下,需要减小探测包的大小,然后再次进行尝试。
修改 MTU 值的方法
- Linux 系统下的临时修改方法
ifconfig eth0 mtu 1488 up
关于 MTU 值计算的说明
在使用 ping
命令探测 MTU 值时,由于 ping
使用的是 Internet 控制消息协议(ICMP),所指定的探测值实际上是数据包数据净荷的长度。而在实际传输中,还需加上 20 字节的 IP 头部和 8 字节的 ICMP 封装部分。因此,最终的 MTU 值为探测出来的值加上 28 字节。
MTU 设置不正确可能引发的问题(系统默认 MTU 值通常为 1500 字节)
- 在使用点到点隧道协议(PPTP)后,若未将服务器上的 MTU 值调小,可能会导致网络带宽无法充分利用,出现带宽跑不上去的情况。
- 在使用通用路由封装协议(GRE)后,若未将服务器上的 MTU 值调小,可能会导致部分网站无法正常打开,例如百度、hao123 等网站。
由于报文经 IPSec 隧道封装后超过 MTU 值导致 HTTP 业务变慢
发布时间:2014-09-20
文档编号:EKB1000052816
问题描述
组网结构:
如图 4-6 所示为某 LTE 组网,承载着各种用户业务流量。现需要对用户业务流量进行 IPSec 加封装,保证其在网络中安全的转发。
在对用户业务流量进行对比测试中,发现经过 IPSec 封装的业务与未经过 IPSec 封装的业务在吞吐量、时延方面没有明显区别,但 HTTP 业务除外,存在很大的区别。对比结果如下:
根因
- 可能是经过 IPSec 封装后,有报文乱序,导致性能降低。可以在 IPSec 封装前后,执行如下命令,查看是否有乱序报文。
IPSec 封装前执行
reset ipsec statistics
IPSec 封装前后执行
display ipsec statistics
如果乱序,可以在统计信息中看出来。
HRP_M<USG9000> display ipsec statistics
dropped security packet detail:
packet header wrong: 0, memory apply fail: 0
can't find SA: 0, wrong SA: 0
authentication: 0, replay: 0
- 有可能是当访问外网服务器时,HTTP 业务在 IPSec 封装前是不分片的,在进行 IPSec 封装后,报文超过 MTU,报文分片导致性能降低。
多方确认网络中的 MTU 值。
基站 ----PE----MPLS 网络 -----MX960----- 防火墙 -----MX960-----UGW----VII 网络 ----- 因特网网关 ----- 因特网
其中基站、PE(接入侧)、MX960、UGW、VII 网络网元和因特网网关所设置的接口 MTU 值都是 1500 字节。
MPLS 网络网元接口(公网侧)MTU 值都是 4470 字节。
防火墙上下行接口 MTU 值设置为 1610 字节。
在 UGW 网元上将 TCP-MSS 值改小后,HTTP 业务速率慢问题得到解决。HTTP 业务在 IPSec 封装前是不分片的,恰巧进行 IPSec 封装后,报文增加了开销,大小超过了 MTU,报文分片导致性能降低。
处理过程
将网络中网元的 TCP-MSS 值改小。
建议与总结
在经过 IPSec 的 ESP 协议封装后,报文开销增大的计算方法如下。
加密算法采用 DES 或者 3DES
20(IP 头)+4(SPI)+4(SeqNum)+8(IV)+12(校验和)+2~9(填充)=50~57 字节
加密算法采用 AES
20(IP 头)+4(SPI)+4(SeqNum)+16(IV)+12(校验和)+2~17(填充)=58~73 字节
如果经过 NAT 穿越,再加上 4 字节的 UDP 头开销。
如果不使用 MD5/SHA1 验证算法,只进行加密,就不需要 12 字节的校验和。
其中填充字节是变化的,主要是需要填充一个合适的分组长度:
如果加密算法采用 DES 或者 3DES,那么分组长度是 8 字节。如果加密数据是 100,先需要加上 2 字节(1 字节为下层协议号,1 字节为填充长度),这样有 102 字节,可以分成 13 个 8 字节分组还少 2 字节,所以还需要加上 2 字节,这样一共加了 4 字节
如果加密算法采用 AES,那么分组长度是 16 字节。算法与上面一样。
本组网中,因为是 AES 算法,所以分组长度是 16 字节,其 TCP-MSS 的合理数值计算如下:
加密有效数据长度 = TCP-MSS+TCP 头 + IP 头 + GTP + UDP 头 + IP 头 = TCP - MSS + 20 + 20 + 8 + 8 + 20 = TCP - MSS + 76
报文总长度 = 20(新 IP 头)+ 4(SPI)+ 4(SeqNum)+ 16(IV)+12(校验和)+ 加密有效数据长度 + 填充 + 2 (填充长度和下层协议号)=56 + 加密有效数据长度 + 填充 + 2
如果加密有效数据长度 + 填充 + 2=91*16=1456,那么报文总长度 = 1456 + 56 = 1512 >1500,这样就会导致报文分片。
如果加密有效数据长度 + 填充 + 2=90*16=1440,报文总长度 = 1440 + 56 = 1496 <1500,报文不会分片。这样加密有效数据长度 + 0(填充)+2=1440=> 加密有效数据长度 = 1438=TCP-MSS+76=>TCP-MSS=1438-76=1362。
所以,1362 是理论计算的 TCP-MSS 的最大值。
此外,防火墙开启先分片后加密功能,也可以解决这个问题。但是此功能会导致防火墙处理性能降低,在防火墙高负载的情况下,不推荐开启此功能。
由于 TCP-MSS 配置过大导致上网慢
发布时间:2019-07-03
文档编号:EKB1000052671
问题描述
组网结构:
用户使用 GE0/0/0 进行 PPPoE 拨号上线,上线后反映网页打开较慢。
处理过程
在 PPPoE 场景出现上网慢的情况时,首先检查设备当前的 MTU 以及 TCP-MSS 值。
了解一些基本概念:
1. MTU(Maximum Transmission Unit): 最大传输单元
EthernetII 帧的结构 DMAC+SMAC+Type+Data+CRC。
由于以太网传输电气方面的限制,每个以太网帧都有最小的大小 64 bytes,最大不能超过 1518 bytes,对于小于或者大于这个限制的以太网帧我们都可以视之为错误的数据帧,一般的以太网转发设备会丢弃这些数据帧。(注:小于 64 Bytes 的数据帧一般是由于以太网冲突产生的 “碎片” 或者线路干扰或者坏的以太网接口产生的,对于大于 1518 Bytes 的数据帧我们一般把它叫做 Giant 帧,这种一般是由于线路干扰或者坏的以太网口产生)
由于以太网 EthernetII 最大的数据帧是 1518 Bytes,这样,刨去以太网帧的帧头(DMAC 目的 MAC 地址 48 bit=6 Bytes+SMAC 源 MAC 地址 48 bit=6 Bytes+Type 域 2 bytes)14 Bytes 和帧尾 CRC 校验部分 4 Bytes(这个部分有时候大家也把它叫做 FCS),那么剩下承载上层协议的地方也就是 Data 域最大就只能有 1500 Bytes,这个值我们就把它称之为 MTU。
2. MSS(Maximum Segment Size): 最大分段大小
MSS 是 TCP 协议里面的一个概念。TCP 协议在三次握手阶段会协商 MSS 值,MSS 的值决定了每个 TCP 报文数据段的最大长度。
TCP 协议一般使用接口 MTU 来设置 MSS 的值,如果接口 MTU 为 1500,减去 20 字节 TCP 头,20 字节 IP 头,一般 MSS 取值为 1460。如下图报文。
当两台远程 PC 互联的时候,它们的数据需要穿过很多的路由器和各种各样的网络媒介才能到达对端,网络中不同媒介的 MTU 各不相同,就好比一长段的水管,由不同粗细的水管组成(MTU 不同),通过这段水管最大水量就要由中间最细的水管决定。
对于网络层的上层协议而言对水管粗细不在意,它们认为这是网络层的事情。网络层 IP 协议会检查每个从上层协议下来的数据包的大小,并根据本机 MTU 的大小决定是否作 “分片” 处理。
分片最大的坏处就是降低了传输性能,本来一次可以搞定的事情,分成多次搞定,所以在网络层更高一层(就是传输层)的实现中往往会对此加以注意!有些高层协议因为某些原因就会要求我这个报文不能分片,我要完整地报文,所以会在 IP 数据包包头里面加上一个标签:DF(Do not Fragment)。这样当这个 IP 数据包在一大段网络传输的时候,如果遇到 MTU 小于 IP 数据包的情况,转发设备就会根据要求丢弃这个数据包。然后返回一个错误信息给发送者。这样往往会造成某些通讯上的问题。
对于 UDP 协议而言,这个协议本身是无连接的协议,对数据包的到达顺序以及是否正确到达不甚关心,所以一般 UDP 应用对分片没有特殊要求。
对于 TCP 协议而言就不一样了,这个协议是面向连接的协议,对于 TCP 协议而言它非常在意数据包的到达顺序以及是否传输中有错误发生。所以有些 TCP 应用对分片有要求 — 不能分片(DF)。
回到问题的本身,相对于普通以太报文,PPPoE 报文多了 8 字节的 PPPoE 头,这样就导致了实际的 MTU 值变小(1500-8=1492),所以在 PPPoE 应用中 MSS 取值不能超过(1492-20-20=1452)。如果还有其他应用,比如 L3 VPN,IPSEC 等,MSS 取值还要小一些。
根因
PPPoE 场景,IP 报文长度大于 MTU,同时设置不分片标志(DF),导致设备丢弃报文,造成业务影响,通过调整防火墙 MSS 解决问题。
解决方案
调整防火墙的 TCP-MSS 小于 1452。
[USG] firewall tcp-mss 1400
实际现网使用过程中,并不一定是只有 PPPoE 场景,当网络中设备有报文长度限制也会碰到调整 TCP-MSS 可以解决上网慢的情况。
via:
什么是 MTU,如何检测和设置路由器 MTU 值_51CTO 博客_路由器 mtu 值怎么设置
https://blog.51cto.com/u_15754466/5590821【MTU】关于 MTU size| MTU size, PMTUD 和分段 - bdy - 博客园
https://www.cnblogs.com/bandaoyu/p/16752232.html为什么 TCP/IP 协议会拆分数据?
https://draveness.me/whys-the-design-tcp-segment-ip-packet一次由于 MTU 设置不当导致的网络访问超时
https://weibo.com/ttarticle/p/show?id=2309404140904511340923设置 MSS 调整 MTU
http://www.easynetworks.com.cn/forum/topic/detail/id/19防火墙外网口如何改 MTU 和 TCP MSS 值
https://zhiliao.h3c.com/Theme/details/152025已沉寂,可以访问 https://post.smzdm.com/p/a5xz60qk/合理设置操作系统网卡的 MTU 值
https://www.cnblogs.com/linuxprobe19/articles/11344000.htmlpppoe 环境下的 mtu 和 mss 的配合问题
https://www.cnblogs.com/chenxiaomeng/p/12739395.htmlHTTPS Websites not reachable - “Ignored Unknown Record” in WireShark
https://www.sonicwall.com/support/knowledge-base/https-websites-not-reachable-ignored-unknown-record-in-wireshark/170505539088634How can I determine the MTU size of WAN interfaces to optimize throughput?
https://www.sonicwall.com/support/knowledge-base/how-can-i-determine-the-mtu-size-of-wan-interfaces-to-optimize-throughput/170504812146650防止 MTU 设置不合理导致的链路不通问题
https://www.itdaan.com/blog/2014/06/30/8662574b43227368b681cd618506b2bd.htmlROS修改MTU和MSS解决上网慢和页面显示不全问题 – 蛋疼实验室
https://danteng.org/ros-change-mtu-mss-solve-page-problems/由于报文经 IPSec 隧道封装后超过 MTU 值导致 HTTP 业务变慢 - 华为
https://support.huawei.com/enterprise/zh/knowledge/EKB1000052816由于 TCPMSS 配置过大导致上网慢 - 华为
https://support.huawei.com/enterprise/zh/knowledge/EKB1000052671
—关于 MTU、IP MTU、TCP MSS 探讨与分析_51CTO 博客_mtu mss
https://blog.51cto.com/ciscoexpert/1714090关于 MTU、IP_MTU、TCP_MSS 探讨与分析 - 道客巴巴
https://www.doc88.com/p-9913773390904.html解决 GRE 和 IPsec 中的 IPv4 分段、MTU、MSS 和 PMTUD 问题 - Cisco
https://www.cisco.com/c/zh_cn/support/docs/ip/generic-routing-encapsulation-gre/25885-pmtud-ipfrag.html【tcp】MTU 设置不合理,导致的链路不通问题的排查处理 - 简书
https://www.jianshu.com/p/22417ebddf35ROS 修改 MTU 和 MSS 解决上网慢和页面显示不全问题 – 蛋疼实验室
https://danteng.org/ros-change-mtu-mss-solve-page-problems/MTU 中 jumbo frame 性能探讨 | DELL Technologies
https://www.dell.com/community/zh/conversations/综合讨论区/mtu中jumbo-frame性能探讨/647f3a8ef4ccf8a8de197912