到底什么时候执行PMTUD?(路径MTU发现)


21

在由于该站点其他问题而引发的讨论中,我意识到我对何时执行路径MTU发现(PMTUD)并不了解。

我知道什么它-发现从客户端到服务器的路径上的最低MTU)。
我知道它是如何做到的–设置“ Do n't Fragment”位为1,逐渐发送较大的数据包,并查看不经过“ ICMP Need Fragment”错误即可获得的数据包大小。

我的问题是,主机何时会执行PMTUD?

我正在寻找具体案例。不仅像“当主机想要发现路径MTU时”这样的通用名称。如果您可以提供执行此操作的主机的数据包捕获,或提供生成此类数据包捕获的说明,则可以加分。

另外,我专门指的是IPv4。我知道在IPv6中,瞬态路由器不是造成碎片的原因,并且可以想象PMTUD发生得更为普遍。但是现在,我正在寻找IPv4中PMTUD的特定示例。 (尽管如果您可以将PMTUD放在一起的唯一数据包捕获是在IPv6中,我仍然很乐意看到它)


PMTUD是从支持的最低MTU到最高的MTU吗?还是执行PMTUD的设备先尝试最大的MTU,然后以较大的增量递减,直到数据包通过,然后以较小的增量递增,然后来回交替,直到最终确定为止?
cpt_fink 2014年

@cpt_fink,有一些策略。ICMP碎片需要消息的现代实现在ICMP有效负载本身中包括需要碎片的链路的MTU。这很容易,因为启动主机会立即知道MTU的路径。较早的实现必须使用各种策略来“搜索”要使用的正确MTU。RFC1191的第5节中概述了这些策略。这些策略的范围从自动默认为IP Minimum(576),到使用“通用” MTU的表来更有效地搜索(请参阅RFC1191第7.1节)。
艾迪

2
这是个有趣的问题。我在对PMTUD进行一些挖掘后发现了这一点。即使它很旧,我还是决定回答,因为我有完全相同的问题,经过几个小时的研究,我可以得出一个相当不错的答案(我想)。如果可能的话,我将在明天尝试通过捕获数据包来更新和支持我的答案。
FilipeGonçalves2015年

Answers:


15

答案很简单:只要主人高兴即可。真。就这么简单。

由于IPv6消除了路由器中的碎片(强制主机始终处理碎片和MTU发现),因此以下说明假定仅使用IPv4的环境。

没有严格的规则可以控制主机何时(或什至)执行“路径MTU发现”。PMTUD浮出水面的原因是,由于各种原因,碎片被认为是有害的。为了避免数据包碎片,PMTUD的概念作为一种变通方法而得以实现。当然,一个好的操作系统应该使用PMTUD来最大程度地减少碎片。

因此,自然地,何时使用PMTUD的确切语义取决于发送方的操作系统-尤其是套接字实现。我只能说Linux的特定情况,但是其他UNIX变体可能差别不大。

在Linux中,PMTUD由IP_MTU_DISCOVER套接字选项控制。您可以getsockopt(2)通过指定级别IPPROTO_IPIP_MTU_DISCOVER选项来检索其当前状态。此选项仅对SOCK_STREAM套接字有效(SOCK_STREAM套接字是双向的,面向连接的可靠套接字;实际上,它是一个TCP套接字,尽管其他协议也是可能的),并且设置后,Linux将完全按照RFC中的定义执行PMTUD 1191。

请注意,实际上,PMTUD是一个连续的过程。数据包以DF位置1发送,包括三向握手数据包,您可以将其视为连接属性(尽管实现可能愿意在某个时候接受一定程度的分段并停止使用DF发送数据包位设置)。因此,PMTUD只是该连接上的所有内容都通过DF发送的事实的结果。

如果您不设置IP_MTU_DISCOVER怎么办?

有一个默认值。默认情况下,IP_MTU_DISCOVERSOCK_STREAM套接字上启用。可以通过读取来读取或更改/proc/sys/net/ipv4/ip_no_pmtu_disc。零值表示IP_MTU_DISCOVER默认情况下在新套接字中启用;非零表示相反。

无连接插座呢?

这很棘手,因为无连接,不可靠的套接字不会重新传输丢失的段。将数据打包成MTU大小的块是用户的责任。另外,如果Message太大错误,则要求用户进行必要的重新传输。因此,基本上用户代码必须重新实现PMTUD。不过,如果您准备好迎接挑战,可以通过将IP_PMTUDISC_DO标志传递到来强制DF位setsockopt(2)

底线

  • 主机决定何时(以及是否)使用PMTUD
  • 当它使用PMTUD时,就像一个连接属性,它会连续发生(但是在任何时候实现都可以停止这样做)
  • 不同的操作系统使用不同的方法,但是通常,可靠的,面向连接的套接字默认情况下执行PMTUD,而不可靠的无连接套接字则不会

4

通常,每当主机认为数据包由于太大而被丢弃时,就会发生路径最大传输单位发现(PMTUD)。

这可能是对所需的ICMP分段响应(类型3,代码4)的响应,该响应明确指示数据包已丢弃。在典型的实践中,所有IPv4数据包都设置有“不要分段”(DF)标志,因此,任何超出MTU的数据包都会引发这种响应。IPv6根本不支持分段。

某些路由器或主机防火墙经常丢弃所有ICMP,因为天真的管理员认为ICMP存在安全风险。或者,某些链路聚合方案可能会中断ICMP传递。在RFC4821中,提出了一种不依赖于ICMP的发现MTU的替代机制。

tracepath是我最喜欢的用于探测MTU的Linux工具。这是来自局域网上具有9001 MTU的主机的示例,但该主机必须遍历IPsec VPN才能达到10.33.32.157:

$ tracepath -n 10.33.32.157
 1?: [LOCALHOST]                                         pmtu 9001
 1:  10.1.22.1                                             0.122ms pmtu 1500
 1:  169.254.3.1                                           1.343ms pmtu 1422
 1:  10.255.254.61                                        23.790ms 
 2:  no reply
^C [this host won't return an ICMP port unreachable, so tracepath won't terminate]

使用以下命令可以观察到ICMP错误tcpdump

$ sudo tcpdump -p -ni eth0 'icmp and icmp[0] == 3 and icmp[1] == 4'
14:46:57.313690 IP 10.1.22.1 > 10.1.22.194: ICMP 10.33.32.157 unreachable - need to frag (mtu 1500), length 36
14:46:57.315080 IP 169.254.3.1 > 10.1.22.194: ICMP 10.33.32.157 unreachable - need to frag (mtu 1422), length 556

MTU发现被缓存。在Linux中,可以观察到并清除它ip(注意Linux 3.6之后更改):

$ ip route get 10.33.32.157
10.33.32.157 via 10.1.22.1 dev eth0  src 10.1.22.194 
    cache  expires 591sec mtu 1422
$ sudo ip route flush cache
$ ip route get 10.33.32.157
10.33.32.157 via 10.1.22.1 dev eth0  src 10.1.22.194 
    cache

对于TCP,作为连接设置的一部分,可以避免超过MTU。每一端发送的SYN中都包含最大段大小(MSS)。TCP报头(20字节,不包括options)和IP报头(20字节)意味着MSS和MTU之间相差40字节。

这是使用以下文件传输大文件时这两个主机之间建立连接的示例scp

$ sudo tcpdump -p -ni eth0 'host 10.33.32.157 and tcp[13]&2 == 2'
IP 10.1.22.194.45853 > 10.33.32.157.22: Flags [S], seq 634040018, win 26883, options [mss 8961,sackOK,TS val 10952240 ecr 0,nop,wscale 7], length 0
IP 10.33.32.157.22 > 10.1.22.194.45853: Flags [S.], seq 1371736848, ack 634040019, win 26847, options [mss 1379,sackOK,TS val 10824267 ecr 10952240,nop,wscale 7], length 0

在第一个数据包中,本地主机提议的MSS为8961。这是配置的9001 MTU,少40个字节。返回的SYN / ACK的MSS为1379,表示MTU为1419。我碰巧知道在该网络中,远程主机也发送了8961,但是该值已由路由器修改,因为它知道该路径包括Internet路径( MTU 1500)来自IPsec隧道的开销。该路由器还修改了我们发送的8961的MSS,使其在另一台主机上显示为1419。这称为MSS夹紧

因此从某种意义上讲,PMTUD一直在发生。实际上,如果MSS钳制到位并且所有流量都通过TCP进行,或者没有一个路由器的MTU小于端点上配置的MTU,则它可能永远不会发生。即使没有MSS限制,当缓存过期时,它也很少发生。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.