文档章节

IP数据报分片——Fragmentation和重组

秋风醉了
 秋风醉了
发布于 2015/07/23 23:35
字数 2541
阅读 3339
收藏 1

IP数据报分片-fragmentation和重组

在TCP/IP分层中,数据链路层用MTU(Maximum Transmission Unit,最大传输单元)来限制所能传输的数据包大小,MTU是指一次传送的数据最大长度,不包括数据链路层数据帧的帧头,如以太网的MTU为1500字节,实际上数据帧的最大长度为1512字节,其中以太网数据帧的帧头为12字节。

当发送的IP数据报的大小超过了MTU时,IP层就需要对数据进行分片,否则数据将无法发送成功。

MTU (最大传输单元)决定 IP报文是否分片。

 

IP分片

上图IP报文格式

如图所示,IP协议理论上允许的最大IP数据报为65535字节(16位来表示包总长)。但是因为协议栈网络层下面的数据链路层一般允许的帧长远远小于这个值,例如以太网的MTU(即Maximum Transmission Unit,最大传输单元)通常在1500字节左右。所以较大的IP数据包会被分片传递给数据链路层发送,分片的IP数据报可能会以不同的路径传输到接收主机,接收主机通过一系列的重组,将其还原为一个完整的IP数据报,再提交给上层协议处理。上图中的红色字段便是被设计用来处理IP数据包分片和重组的。

那么,这三个字段如何实现对分片进行表示呢?

首先是标识符(16位),协议栈应该保证来自同一个数据报的若干分片必须有一样的值。

其次是标志位3位分别是R(保留位,未使用)位、DF(Do not Fragment,不允许分段)位和MF(More Fragment)位。MF位为1表示当前数据报还有更多的分片,为0表示当前分片是该数据报最后一个分片。

最后是偏移量(13位),表示当前数据报分片数据起始位置在完整数据报的偏移,注意这里一个单位代表8个字节。即这里的值如果是185,则代表该分片在完整数据报的偏移是185*8=1480字节。

操作系统内核协议栈(以下简称协议栈)只需要申请一块和原始数据报相同大小的内存空间,然后将这些数据报分片按照其偏移拷贝到指定的位置就能恢复出原先的数据报了。目前看起来一切都很清晰,不是么?但我的问题就出在这个判别数据报分片的方法上。因为标识符字段只有16位,所以理论上只有65536个不同的表示。当一台拥有着超过65536个活跃连接用户的服务器时,理论上会出现重复的数据报分片。即使连接的客户没这么多,但是从概率上如果只用这个标示符的话,依旧会出现可能造成混乱的数据报分片。

 下面这行代码明确的指出了协议栈判断IP分片的依据:

hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);

ipqhashfn函数依靠(标示符、源地址、目标地址、协议)这个四元组来唯一的表示一个IP数据报分片,这就解决了单单依赖表示符无法确定一个数据报的问题。那么这个四元组怎么表示呢?查找的效率问题如何解决呢?答案就在ipqhashfn这个hash函数里,其代码如下(Linux-3.12.6)

static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
{
	return jhash_3words((__force u32)id << 16 | prot,
			    (__force u32)saddr, (__force u32)daddr,
			    ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1);
}

 

避免IP分片

在网络编程中,我们要避免出现IP分片,那么为什么要避免呢?原因是IP层是没有超时重传机制的 ,如果IP层对一个数据包进行了分片,只要有一个分片丢失了,只能依赖于传输层进行重传,结果是所有的分片都要重传一遍,这个代价有点大。由此可见,IP分片会大大降低传输层传送数据的成功率,所以我们要避免IP分片。

对于TCP协议,应用层就不需要考虑这个问题了,因为传输层已经帮我们做了。在建立连接的TCP三次握手的过程中,连接双方会相互通告MSS(Maximum Segment Size,最大报文段长度1460),MSS一般是MTU - IP首部(20) - TCP首部(20),每次发送的TCP数据都不会超过双方MSS的值,所以就保证了IP数据报不会超过MTU,避免了IP分片。

如果发送一段2000字节的TCP报文,那么会导致TCP分段,因为其超过了最大报文段的长度,一般是MTU - IP首部(20) - TCP首部(20)。

分段后的每一段TCP报文段再加上IP首部后的长度不可能超过MTU,因此也就不需要在网络层进行IP分片了。因此TCP报文段很少会发生IP分片的情况。

====================================================================

对于UDP包,我们需要在应用层去限制每个包的大小,一般不要超过1472字节,即以太网MTU(1500) - IP首部(20) - UDP首部(8)。

UDP数据报,由于UDP数据报不会自己进行分段,因此当长度超过了MTU时,会在网络层进行IP分片。

需要注意的,在分片的数据中,传输层的首部只会出现在第一个分片中,如下图所示。因为传输层的数据格式对IP层是透明的,传输层的首部只有在传输层才会有它的作用,IP层不知道也不需要保证在每个分片中都有传输层首部。所以,在网络上传输的数据包是有可能没有传输层首部的。

图:表示IP的分片

实例:从10.224.142.166向10.137.133.101发送3000字节的UDP数据,由于UDP数据报超过了MTU的大小,所以要在IP层分片。抓包的结果如下图。从图中可以看到这个UDP数据包被分成了3个IP片,从各IP分片的偏移量可以看出,3片包含的UDP数据大小分别是1480、1480、48(加上UDP首部8个字节),各分片加上IP首部的大小分别就是1500、1500、68,传送的总的UDP数据大小为3008,由此也看出只有一个分片包含UDP首部。

=====================================================================

 

IP分片重组

接收方在收到经过IP层分片的数据报文后,首先根据分片标志中的 MF(More Fragment)位 (MF位为1表示当前数据报还有更多的分片,为0表示当前分片是该数据报最后一个分片。)判断是否是最后一个分片报文,如果是,则根据分片偏移量计算各个分片报文在原始数据报中的位置,进行重组。如果不是最后一个分片,则需等待所有分片到达后再完成重组。

 

IP分片带来的问题

分片带来的问题:

1.分片带来的性能消耗

分片和重组会消耗发送方、接收方一定的CPU等资源,如果存在大量的分片报文的话,可能会造成较为严重的资源消耗;

分片对接收方内存资源的消耗较多,因为接收方要为接收到的每个分片报文分配内存空间,以便于最后一个分片报文到达后完成重组。

2.分片丢包导致的重传问题

如果某个分片报文在网络传输过程中丢失,那么接收方将无法完成重组,如果应用进程要求重传的话,发送方必须重传所有分片报文而不是仅重传被丢弃的那个分片报文,这种效率低下的重传行为会给端系统和网络资源带来额外的消耗。

3.分片攻击

黑客构造的分片报文,但是不向接收方发送最后一个分片报文,导致接收方要为所有的分片报文分配内存空间,可由于最后一个分片报文永远不会达到,接收方的内存得不到及时的释放(接收方会启动一个分片重组的定时器,在一定时间内如果无法完成重组,将向发送方发送ICMP重组超时差错报文,,只要这种攻击的分片报文发送的足够多、足够快,很容易占满接收方内存,让接收方无内存资源处理正常的业务,从而达到DOS的攻击效果。

4.安全隐患

由于分片只有第一个分片报文具有四层信息而其他分片没有,这给路由器、防火墙等中间设备在做访问控制策略匹配的时候带来了麻烦。

如果路由器、防火墙等中间设备不对分片报文进行安全策略的匹配检测而直接放行IP分片报文,则有可能给接收方带来安全隐患和威胁,因为黑客可以利用这个特性,绕过路由器、防火墙的安全策略检查对接收方实施攻击;

如果路由器、防火墙等中间设备对这些分片报文进行重组后在匹配其安全策略,那么又会对这些中间设备的资源带来极大的消耗,特别是在遇到分片攻击的时候,这些中间设备会在第一时间内消耗完其所有内存资源,从而导致全网中断的严重后果。

引用:

http://www.cnblogs.com/glacierh/p/3653442.html

http://support.huawei.com/ecommunity/bbs/10161111.html

http://blog.csdn.net/ns_code/article/details/30109789

===============END===============

本文转载自:

秋风醉了
粉丝 252
博文 532
码字总数 405694
作品 0
朝阳
程序员
私信 提问
IP数据报头详解

0x1:IP数据报头 IP报头如下所示,现在逐个分析一下各个字段。 4位版本字段:表示IPv4或者IPv6。 4位部首长度:表示IP部首的长度。 8位服务类型:服务类型(TOS)字段包括一个3 bit的优先权子...

wm1283
2015/04/14
0
0
UDP数据包大小的问题

在进行UDP编程的时候,我们最容易想到的问题就是,一次发送多少bytes好? 当然,这个没有唯一答案,相对于不同的系统,不同的要求,其得到的答案是不一样的,这里仅对像ICQ一类的发送聊天消息的情况...

长平狐
2012/09/03
434
0
网络基础 — 浅析IP/TCP协议分片

浅析IP/TCP协议分片 首先我们需要知道一个概念,MTU是链路层中的网络对数据帧的一个限制,以以太网为例,MTU为1500个字节. 一个IP数据报在以太网中传输,如果它 的长度大于该MTU值,就要进行分...

Dawn_sf
2018/01/31
0
0
Lwip IP包分片重组

1. 开发环境 操作系统:SylixOS 编程环境:RealEvo-IDE3.1 硬件平台:AT9x25开发板 2. 技术实现 SylixOS系统使用的网络协议栈是Lwip协议栈。Lwip是Light Weight (轻型)IP协议,有无操作系统的...

SeanPcWoo
2017/06/19
0
0
Linux 网络编程——IP 数据报格式详解

版权声明:本博客文章,大多是本人整理编写,或在网络中收集,转载请注明出处! https://blog.csdn.net/tennysonsky/article/details/44925123 IP 数据报首部 TCP/IP 协议定义了一个在因特网...

Mike__Jiang
2015/04/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Vue warn]: Computed property "activeNames" was assigned to but it has no setter.

在使用 vue,element-ui时,如下代码 <template> <el-form :model="numberValidateForm" ref="numberValidateForm"> <el-form-item> <el-tabs v-model="activeNames" @tab-cl......

牧云橙
15分钟前
2
0
重构-改善既有代码的设计-6.2内联函数

6.2内联函数 动机 本书经常以简短的函数表现动作意图,这样会使代码更清晰易读。但有时候你会遇到某些函数,其内部代码和函数名称同样清晰易读。也可能你充够了该函数的内部实现,使其内容和...

还仙
16分钟前
2
0
Less 混入

混合类似于编程语言中的函数。 Mixins 是一组CSS属性,允许我们将一个类的属性嵌套于另一个类,被嵌入的类可以看作是变量,并且包含类名作为其属性,也就是说我们可以用一个类定义样式然后把...

凌兮洛
19分钟前
3
0
频繁FGC的真凶原来是它

频繁FGC的真凶原来是它 上周排查了一个线上问题,主要现象是CPU占用过高,jvm old区占用过高,同时频繁fgc,我简单排查了下就草草收场了,但是过后我对这个问题又进行了复查,发现问题没有那...

每天晒白牙
19分钟前
3
0
简单的树形菜单如何写

业务需求 数据结构中含有图片、名称、children的树形结构,需要展示出每一级的图片名称和图片,找了些树形图的插件,都没有展示大的图片的,一般都是小图标,就自己试着写一个包含图的简单的...

tianyawhl
21分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部