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

IP数据报分片-fragmentation和重组html

在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位),协议栈应该保证来自同一个数据报的若干分片必须有同样的值。spa

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

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

操做系统内核协议栈(如下简称协议栈)只须要申请一块和原始数据报相同大小的内存空间,而后将这些数据报分片按照其偏移拷贝到指定的位置就能恢复出原先的数据报了。目前看起来一切都很清晰,不是么?但个人问题就出在这个判别数据报分片的方法上。由于标识符字段只有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===============

相关文章
相关标签/搜索