一、IP分片原理
1.1 基本原理
- IP包長(zhǎng)計(jì)算
??IP 包全長(zhǎng)由頭部中的 total length 字段決定,該字段共 16 位,因此一個(gè) IP 包最大可達(dá) 2^16-1 ,即 65535 字節(jié)。除去頭部 20字節(jié)(無Options字段),IP 包最多可承載65535-20,即 65515 字節(jié)的數(shù)據(jù)。 - MTU計(jì)算
??MTU是最大傳輸單元( Maximum Transmission Unit)的縮寫,指一個(gè)接口無需分片所能發(fā)送的數(shù)據(jù)包的最大字節(jié)數(shù)。
??MTU范圍在46 ~ 1500字節(jié),默認(rèn)一般都是1500(7字節(jié)前導(dǎo)碼+1字節(jié)幀開始定界符+6字節(jié)的目的MAC+6字節(jié)的源MAC+2字節(jié)的幀類型+1500字節(jié)IP頭及數(shù)據(jù)+4字節(jié)的 FCS = 1526字節(jié)。抓包軟件抓到的是去掉前導(dǎo)碼、幀開始定界符、FCS之外的數(shù)據(jù),其最大值是 6+6+2+1500=1514) - 產(chǎn)生IP分片的原因
??IP分片發(fā)生在IP層,不僅源端主機(jī)會(huì)進(jìn)行分片,中間的路由器也有可能分片,因?yàn)椴煌木W(wǎng)絡(luò)的MTU是不一樣的,如果傳輸路徑上的某個(gè)網(wǎng)絡(luò)的MTU比源端網(wǎng)絡(luò)的MTU要小,路由器就可能對(duì)IP數(shù)據(jù)報(bào)再次進(jìn)行分片。而分片數(shù)據(jù)的重組只會(huì)發(fā)生在目的端的IP層。
1.2 與分片相關(guān)的IP頭部字段

標(biāo)識(shí)符( identification ),IP 包的 ID ,全局自增,短時(shí)間內(nèi)不會(huì)重復(fù),可唯一標(biāo)識(shí)一個(gè) IP 包;
-
標(biāo)志位( flags ),包括兩個(gè)用于控制和識(shí)別分片的標(biāo)志位;
- DF 標(biāo)志位禁止中間路由對(duì)該包進(jìn)行分片;
- MF 標(biāo)志位表明該包之后還有其他分片;
偏移量( fragment offset ),表示一個(gè)分片相對(duì)于原始 IP 包開頭的偏移量,以8字節(jié)為單位;
-
分片大小計(jì)算
??假設(shè)主機(jī)①出口 MTU 是 1500 ,它準(zhǔn)備發(fā)一個(gè)長(zhǎng)度為 4000 字節(jié)的 IP包給主機(jī)②。這個(gè)包必須分片
分片
??如上圖,原包長(zhǎng)達(dá) 4000 字節(jié),其中頭部 20 字節(jié),數(shù)據(jù)部分為 3980 字節(jié)。分片包最大長(zhǎng)度為 1500 ,除去頭部的 20 字節(jié),數(shù)據(jù)部分只剩 1480 。這意味著,原包 3980 字節(jié)至少需要分為 3 片。
??由于偏移量字段以 8 字節(jié)為單位,因此每個(gè)分片的數(shù)據(jù)長(zhǎng)度必須為 8 的倍數(shù),最后一片除外。由于 1480 剛好可以被 8 整除,因此分片數(shù)據(jù)長(zhǎng)度可以選擇 1480 。 片偏移計(jì)算
??第一個(gè)分片,包含原包前 1480 字節(jié)數(shù)據(jù),因此偏移量 offset=0(數(shù)據(jù)的首個(gè)字節(jié)離原始IP頭部距離為0) ;而 MF=1 表示后面還有其他分片。第二個(gè)分片,包含原包緊接著的 1480 字節(jié)數(shù)據(jù),偏移量offset=(1480+1480)/8=185 ;同樣 MF=1 表示后面還有其他分片。最后一個(gè)分片,包含原包最后 1020 字節(jié)數(shù)據(jù),偏移量(1480*2)/8=370 ;而 MF=0 表示它是最后一片了。-
分片重組
??分片到達(dá)目標(biāo)主機(jī)后,系統(tǒng)根據(jù)包頭中的源地址、目的地址、標(biāo)識(shí)符、偏移量等字段,將它們重組合成原包。
??實(shí)際上,系統(tǒng)會(huì)分配一塊內(nèi)存作為重組分片的緩沖區(qū)。一個(gè)分片包首個(gè)分片達(dá)到后,系統(tǒng)將其移入到該緩沖區(qū),等待其他分片達(dá)到:
分片重組
后續(xù)分片達(dá)到后,系統(tǒng)先根據(jù)源地址、目的地址和標(biāo)識(shí)符確定它屬于哪個(gè)包;再根據(jù)偏移量確定它屬于原包的哪個(gè)部分;最后將分片數(shù)據(jù)拼接到原包中。
二、實(shí)現(xiàn)IP分片
2.1實(shí)驗(yàn)拓?fù)?/h2>
實(shí)驗(yàn)拓?fù)淙缦?,linux向R2發(fā)送IP分片,并在R2接口上抓包。

2.2 Python手動(dòng)制作分片
- Python腳本
#!/usr/bin/python3.4
# -*- coding=utf-8 -*-
from kamene.all import *
#嚴(yán)重注意ICMP的校驗(yàn)和是整ICMP頭部和數(shù)據(jù)部分一起計(jì)算的?。?!
#flags="MF"或flags=1表示后面有分片,flags=0表示為最后一個(gè)分片,flags="DF"或flag=2表示不分片
#frag一位表示8字節(jié),因此frag數(shù)值乘以8,才是真正的偏移量字節(jié)數(shù)!第一個(gè)分片需加上ICMP首部8字節(jié)。
send(IP(flags="MF",frag=0,id=1,dst='172.16.10.2')/ICMP(chksum=0x7932)/b'Farst Hello Word!!!!!!!!')
send(IP(flags=1,frag=4,id=1,proto=1,dst='172.16.10.2')/(b'second Hello Word!!!!!!!'))
send(IP(flags=0,frag=7,id=1,proto=1,dst='172.16.10.2')/(b'third Hello Word!!'))
-
執(zhí)行效果
執(zhí)行效果如下:
分片
抓包結(jié)果如下,發(fā)送三個(gè)數(shù)據(jù)包,前兩包MF位置1.
分片1
分片2
分片3
2.2.1 ICMP校驗(yàn)和計(jì)算
??ICMP包校驗(yàn)和是連通頭部信息加數(shù)據(jù)本身一起進(jìn)行校驗(yàn)(ip包只需要校驗(yàn)頭部信息)而Scapy自動(dòng)添加ICMP校驗(yàn)和時(shí)只會(huì)計(jì)算第一分片的數(shù)據(jù),當(dāng)三個(gè)分片到達(dá)目標(biāo)主機(jī)進(jìn)行重組后校驗(yàn)不通過,將重組后的數(shù)據(jù)包丟棄;因此在手動(dòng)設(shè)置IP分片時(shí),需要手動(dòng)將校驗(yàn)和添加入ICMP首部中。
由于手動(dòng)計(jì)算校驗(yàn)和過程較復(fù)雜,可通過wireshark抓包,可以獲取到正確的校驗(yàn)和。

2.3 Scapy自動(dòng)分片
- python腳本
#!/usr/bin/python3.4
# -*- coding=utf-8 -*-
from kamene.all import *
##############################自動(dòng)制造Fragment################################
frags = fragment(IP(dst='172.16.10.2')/ICMP()/(b"Hello Word"*300))
#產(chǎn)生每一個(gè)分片,可以對(duì)分片就行修改?。。?!
send(frags)
#正常發(fā)包,系統(tǒng)會(huì)自動(dòng)進(jìn)行分片處理!?。?!
#send(IP(dst='172.16.10.2')/ICMP()/(b"Hello Word"*300))
抓包結(jié)果如下,由于單個(gè)數(shù)據(jù)包長(zhǎng)度超過MTU,系統(tǒng)自動(dòng)將ICMP request包分片發(fā)送,同樣的ICMP reply系統(tǒng)也進(jìn)行了分片。

三、網(wǎng)絡(luò)路徑MTU探測(cè)
3.1 基本原理
??當(dāng)主機(jī)發(fā)送分組的長(zhǎng)度超過MTU又不可以分片(IP flags位DF置1),則這個(gè)分組丟棄,并用ICMP差錯(cuò)報(bào)文向主機(jī)報(bào)告。
3.2 具體實(shí)現(xiàn)
-
實(shí)驗(yàn)拓?fù)?br> 實(shí)驗(yàn)拓?fù)淙缦拢诼酚善鞒鼋涌谠O(shè)置不同的MTU值。
MTU路徑 - Python腳本
#!/usr/bin/python3.4
# -*- coding=utf-8 -*-
from kamene.all import *
import time
import re
def ping_df(dst,mtu):
pyload = b'v'*(int(mtu) - 28) #28為20字節(jié)IP頭部和8字節(jié)ICMP頭部的長(zhǎng)度
ping_one_reply = sr1(IP(dst=dst,flags='DF')/ICMP()/pyload, timeout = 1, verbose=False)
#發(fā)送DF位的數(shù)據(jù)包
try:
if ping_one_reply.getlayer(ICMP).type == 3 and ping_one_reply.getlayer(ICMP).code == 4:
#如果返回ICMP不可達(dá)信息,就返回1和當(dāng)前的mtu
MTU=ping_one_reply.getlayer(ICMP).unused#獲取經(jīng)過設(shè)備出接口的MTU值
print("中間設(shè)備出接口MTU值為:", MTU)
return 1
elif ping_one_reply.getlayer(ICMP).type == 0 and ping_one_reply.getlayer(ICMP).code == 0:
#如果返回ICMP echo reply,就返回2和當(dāng)前的mtu
return 2, mtu
except Exception as e:
if re.match('.*NoneType.*',str(e)):
return None #如果測(cè)試失敗,就返回None
def discover_path_mtu(dst):
mtu = 1500 #mtu從1500開始向下減
while True:
Result = ping_df(dst,mtu)
if Result == None: #如果測(cè)試失敗就打印信息,并且跳出循環(huán)
print('目標(biāo): ' + dst + '不可達(dá)!')
break
elif Result[0] == 2: #如果PING測(cè)試成功,就打印信息,并且跳出循環(huán)
print('目標(biāo): ' + dst + '的Path MTU為: ' + str(Result[1]))
break
elif Result[0] == 1: #如果得到不可達(dá)信息,就較少M(fèi)TU,打印消息,并且繼續(xù)循環(huán)
mtu = mtu - 50
time.sleep(1)
if __name__ == '__main__':
dest=input("目標(biāo)IP>>>")
discover_path_mtu(dest)
-
執(zhí)行效果
執(zhí)行結(jié)果如下,返回經(jīng)過的中間設(shè)備出接口的MTU值,如此則可得知路徑中最小的MTU值。
MTU探測(cè)
抓包結(jié)果如下:
request包中Flags DF置1,不允許分片。
request
由于分組長(zhǎng)度超過了該設(shè)備出接口的MTU值,故返回一個(gè)ICMP差錯(cuò)報(bào)文告知分組長(zhǎng)度超過MTU,并將下一跳的MTU值返回。
ICMP 不允許分片
參考:(https://fasionchan.com/network/ip/fragmentation/)
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 一、IP報(bào)文首部格式 字段解釋Version4:表示為IPV4;6:表示為IPV6。IHL首部長(zhǎng)度,如果不帶Opt...
- 網(wǎng)絡(luò)層 一、指引 負(fù)責(zé)在不同網(wǎng)絡(luò)之間盡力轉(zhuǎn)發(fā)數(shù)據(jù)包,基于數(shù)據(jù)包的IP地址轉(zhuǎn)發(fā),不負(fù)責(zé)丟失重傳,如果前面處理不過來,...
- 2019 iOS面試題大全---全方面剖析面試 2019 iOS面試題-----網(wǎng)絡(luò)相關(guān)之HTTP協(xié)議 2019 ...
- 在Android網(wǎng)絡(luò)編程-計(jì)算機(jī)網(wǎng)絡(luò)基礎(chǔ)一文中得知,IP協(xié)議屬于網(wǎng)絡(luò)層,TCP、UDP協(xié)議屬于傳輸層。IP協(xié)議是T...
- 推薦閱讀:備戰(zhàn)2020——iOS全新面試題總結(jié) 之前有說到OSI七層協(xié)議中的應(yīng)用層(HTTP協(xié)議)、傳輸層(TCP...









