IP數據報分片-fragmentation和重組html
在TCP/IP分層中,數據鏈路層用MTU(Maximum Transmission Unit,最大傳輸單元)來限制所能傳輸的數據包大小,MTU是指一次傳送的數據最大長度,不包括數據鏈路層數據幀的幀頭,如以太網的MTU爲1500字節,實際上數據幀的最大長度爲1512字節,其中以太網數據幀的幀頭爲12字節。編程
當發送的IP數據報的大小超過了MTU時,IP層就須要對數據進行分片,不然數據將沒法發送成功。安全
MTU (最大傳輸單元)決定 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分片。
對於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層分片的數據報文後,首先根據分片標誌中的 MF(More Fragment)位 (MF位爲1表示當前數據報還有更多的分片,爲0表示當前分片是該數據報最後一個分片。)判斷是不是最後一個分片報文,若是是,則根據分片偏移量計算各個分片報文在原始數據報中的位置,進行重組。若是不是最後一個分片,則需等待全部分片到達後再完成重組。
分片帶來的問題:
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===============