TCP/IP卷一:57---IP分片与重组、IP分片重组超时、IP分片和ARP/ND之间的交互

时间:2024-04-06 09:44:15

一、IP分片概述

  • 链路层通常对可传输的每个帧的最大长度有一个上限。为了保持IP数据报抽象与链路层细节的一致和分离,IP引人了分片和重组

IP分片原理:

  • 当IP层接收到一个要发送的IP数据报时,它会判断该数据报应该从哪个本地接口发送(通过查找一个转发表,见前面Internet文章)以及要求的MTU是多少。IP比较外出接口的MTU和数据的大小,如果数据报太大则进行分片(值得一提的是,数据报分片自身也可被分片
  • IPv4中的分片:可以在原始发送方主机和端到端路径上的任何中间路由器上进行
  • IPv6中的分片有些不一样:它只允许源主机进行分片(我们见过一个IPv6分片的例子)

二、例子:UDP/IPv4分片

  • 前言:
    • 使用UDP的应用程序如果想要避开IP层分片,可能就得琢磨它生成的结果IP数据报的大小了
    • 特别是,如果结果数据报的大小超过链路的MTU,那么IP数据报就要被分割成多个IP分组,这有可能导致性能问题,因为如果任何一个分片丢失了,整个数据报就丢失 了

图例

  • 下图描述了一个3023字节的UDP/IPv4数据报被分割成多个IPv4分组的情况

TCP/IP卷一:57---IP分片与重组、IP分片重组超时、IP分片和ARP/ND之间的交互

  • 我们看到原始UDP数据报包含了2992字节的应用程序数据(UDP负载)和8字节的UDP头部,结果产生一个总长度字段值为3020字节的IPv4数据报(回想一下,这个大小也包含了一个20字节的IPv4头部)
  • 当这个数据报被分片成三个分组时,产生40个额外字(每个新生成的IPv4分片头部20字节)。因此,总发送的字节数是3060,增加的IPv4开销大概是1.3%
  • 标识字段的值(由原始发送方设置)被复制到每个分片,同时当分片到达目的地时利用它来分成组
  • 分片偏移字段给出该分片负载字节中的第一个字节在原始IPv4数据中的偏移量(以8字节为单位)
    • 很明显,第一个分片的偏移总是0
    • 这里,我们看到第二个分片的偏移是185(185*8= 1480)。1480是第一个分片的大小减去IPv4头部的大小
    • 类似的分析可应用在第三个分片上
  • 最后,MF位字段指明该数据报后面是否还有更多的分组,只有最后一个分片才应置成0。当MF=0的分片被接收到时,重组程序才能确定原始数据报的长度,它等于分片偏移字段的值(乘以8)加上IPv4总长度字段的值(减去IPv4头部长度)。因为每个偏移字段都是相对原始数据报的,重组进程可以处理非顺序到达的分片。当一个数据报被分片后,每个IPv4头部中的总长度字段要被修改成该分片的总长度

三、分片导致的数据报丢失(避免分片)

  • 尽管IP分片看起来是透明的,但是一个刚才提到过的特征使得它不太理想:如果任何 一个分片丢失了,整个数据报就丢失了
  • 要理解为什么会这样,我们知道IP自身没有差错纠正机制。像超时和重传这些机制是更高层的责任。 (TCP有超时和重传操作,UDP则没有。 一些基于UDP的应用程序自已实现超时和重传,但这在UDP之上的某层进行。)当TCP报文段的一个分片丢失了,TCP会重传整个TCP报文段,这涉及整个IP数据报。只重发数据报的一个分片是不可能的。确实,如果分片由中间的路由器来做,而不是原始系统,那么原始系统就又不知道数据报是怎样被分片的了
  • 如此看来,通常是要避免分片的

四、分片演示案例

  • 使用UDP,产生IP分片是很简单的。 (后面我们将会看到TCP尽量避免分片,一个应 用程序强迫TCP发送比要求的分片要大得多的报文段几乎是不可能的。)我们可以使用sock 程序增加数据报的大小,直到分片出现。在一个以太网里,一帧的数据最大大小一般是1500 字节(见第3章),假设IPv4头部是20字节, UDP头部是8字节e,这就使得最大1472字 节的应用程序数据可避免分片。我们将
  • 以数据大小1471、 1472、 1473及1474字节来运行 sock程序。我们预想到最后两个会产生分片:

TCP/IP卷一:57---IP分片与重组、IP分片重组超时、IP分片和ARP/ND之间的交互

  • 下图显示了tcpdump输出(为了简洁,某些行已被整理)

TCP/IP卷一:57---IP分片与重组、IP分片重组超时、IP分片和ARP/ND之间的交互

  • 前两个UDP数据报(分组1和2)适合以太网帧(使用典型的“DIX”或“Ethemet” 封装)且没被分片。第三种情况,对应于应用程序写人的1473字节的IPv4数据报的长度是1501,这必须进行分片(分组3和4)。类似地,写人1474字节产生的数据报长度是1502字 节,同样也要分片(分组5和6)
  • 当捕获到一个分片数据报时, tCPdump打印了一些附加信息。首先,输出frag37671 (分 组3和4)和frag37672 (分组5和6)指明了IPv4头部中的标识字段。分片信息的下一个 数字(在分组4和6中的冒号和@字符之间)是IPv4分组大小,不包括IPv4头部。两个数 据报的第一个分片都包含了1480字节的数据‥ 8字节的UDP头部和1472字节的用户数据。 ( 20字节不带选项的IPv4头部使得分组恰好是1500字节。)第一个被分片的数据报的第二个 分片(分组3)包含1字节的数据(用户数据剩下的1个字节)。第二个被分片的数据报的第 二个分片(分组5)包含用户数据剩下的2个字节。分片要求除了最后一个分片之外的所有 分片的数据部分(即,除IPv4头部外的所有东西)应是8字节的倍数。本例中, 1480就是8 的倍数。 (相比于第5章的IPv6分片例子,那里1500字节的以太网MTU不能被充分利用。)
  • 跟随在@字符后的数字是指该分片的数据相对原始数据报开头的偏移量。每个新的被 分片的数据报的第一个分片都是以偏移0开始的(分组4和6),两个数据报的第二个分片都 是从偏移1480字节开始(分组3和5)。偏移量后的“+”字符代表还有组成这个数据报的 分片,对应IPv4头部里的3位的标志字段里的MF位字段被置成10
  • 一个令人意外的现象是:有更大偏移量的分片要比第一个分片优先投递。事实上,发 送方故意对这些分片进行了重新排序。经过思考,我们认为这样做是有好处的。如果最后一 个分片先被投递,接收主机就可以确定所需的缓存空间的最大值,以重组整个数据报。考 虑到反正重组进程重新排序是鲁棒的,这就不是什么问题了。另一方面,有些技术要利用 更高层的信息,这些信息从第一个分片可得到(包含UDP端口号),而后面的分片都没有 [KEwG96] 。
  • 最后,注意到分组3和5 (非第一个分片)遗漏了源和目的UDP端日号o tcpdump为了 能打印除了第一个分片外的分片的端日号,它不得不重组被分片的数据报以恢复只出现在第 一个分片(该分片没有遗漏源和目的端口号)的UDP头部中的端日号0

五、重组超时

  • 一个数据报的任何一个分片首先到达时,IP层就得启动一个计时器。如果不这样做的话,不能到达的分片(如下图可见)可能会最终导致接收方用尽缓存,留下一种攻击机会

演示说明

  • 下面的例子由一个特殊程序产生,该程序构造一个ICMPv4回显请求报文,并且以一定延迟只发送这个消息的前面两个分片,然后不再发送任何其他分片。下图显示了回复(为了简洁,某些行已被整理)

TCP/IP卷一:57---IP分片与重组、IP分片重组超时、IP分片和ARP/ND之间的交互

  • 这里我们看到第一个分片(的时间和序列空间)被发送,总长度是4000第二个分片20s 后被发送,但最后一个分片一直没被发送。接收到第一个分片30s后,目标机器回复一个ICMPv4超时(代码1)消息,告诉发送方数据报已丢失,包括第一个分片的拷贝。一般的 超时时间是30s或60so正如我们所见,收到任何一个分片时计时器就开始计时,且收到新 的分片也不会被重置。因此,计时器给出了同一数据报分片之间可被分隔的最大间隔时间的 限度
  • 注意:历史上,大多数衍生自Berkeley-Unix的IP实现方案从不产生这个错误。然 而这些实现确实用了计时器,也确实在计时器超时的时候丢弃了所有分片,但是却 从不产生ICMP错误。有时会碰到另一个细节:除非接收到了第一个分片(比如分片偏移字段为0的分片),否则没必要产生ICMP错误。原困是这些ICMP错误的接收者会困传输层头部不可用而无法知道哪个用户进程发送的数据报丢弃了。假设 更高层协议最终将会超时,并在必要时重传它

六、IP分片和ARP/ND之间的交互

  • 待续