相信有接觸過網路通訊、封包監控的讀者來說,對於封包的內容一定都不陌生
但是若有需要做到封包監控與封包過濾的話,讀懂每一個 Byte勢必是必經之路。
因為,只有真正讀懂每一個 Byte 在做什麼,才能夠透過程式進行過濾以及解析。
在文章開始之前,首先需要先請各位記住一個很重要的觀念:
每一層的Data欄位都是下一層以後的內容。
每一層的Data欄位都是下一層以後的內容。
每一層的Data欄位都是下一層以後的內容。
這句話非常的重要,所以講了三遍來強調,因為懂了這個概念之後,會有助於我們日後可以寫程式去解析。
接下來的每一個部分,都會拆成各個章節來為各位做介紹:
TCP/IP五層架構
在了解網路封包時,我們需要先知道TCP/IP的五層網路架構到底是分為哪五層,而每一層到底又做哪些事情。
這樣我們才能夠更快速地取得我們想要的資料。
筆者整理了以下表格方便讓大家快速看懂:
TCP/IP層 | 介紹 | 網路設備 | 通訊協定 |
應用層 | 任何的通訊協定、功能都會在此被定義 | 無 | 所有應用層的通訊協定在此定應 |
傳輸層 | 提供端點之間的Port用來做連結與確認 | Switch | TCP、UDP |
網路層 | 用來定義兩端點的IP位置 | Router |
IP、ICMP |
資料連結層 | 定義兩端點的MAC地址 |
ARP、RARP |
|
實體層 | 又稱物理層,走光電訊號(硬體) |
|
從上表當中,我簡單為讀者做個說明:
實體層:由於走的是光電訊號,較偏硬體設備通訊,因此不在此討論。
資料連結層:主要是用來定義來源/目的的MAC地址,以及所使用的協定為何(IPV4/IPV6)
網路層:主要是負責處理將封包由來源電腦傳給目的電腦之間的路徑選擇問題,因此會在此定義該封包需要送往哪一個IP位置。
傳輸層:主要提供系統間資料的傳輸更高階的控制,為了確保本層保證所有的資料都是以正確的順序送達,因此紀錄來源/目的Port位置,此外亦會給每一個封包追蹤號碼,並在目的地進行檢查。
而在上方筆者用紅字標示的部分當中我們可以了解到每一層所執行的功能。當來源/目的的MAC地址、IP位置、Port號都被定義後,就能將封包正確的送往目的地。
封包解析
當我們用像是WireShark等其他軟體側錄封包內容時,大概會看到以下內容:
這是一大長串的內容,裡面的內容都是採十六進位顯示,那我們該從何讀起呢?
其實Wireshark有很貼心的服務,當你點選封包上方的每一層時,它都會即時標示這一層的內容是從哪裡開始,到哪裡結束,並用藍底Mark起來。
資料連結層封包區段:
網路層封包區段:
傳輸層封包區段:
應用層封包區段:
眼尖的讀者們應該可以了解到,當逐層標示完後,最後一層也就是到封包的結尾做結束。
這也就是呼應了我們最一開始開頭的那句話:「每一層的Data欄位都是下一層以後的內容。」
對於每一層來說,它只管自己這一層所定義的欄位內容,其餘看不懂的、無法解析的,都會被視為是「資料」,
讓下一層看得懂的來去解析他。
一直到解析至傳輸層後,剩下的Data它看不懂了,那就輪到最後一層「應用層」來去做解析,也就是我們的Data資料。
因此不管是各位常見到的HTTP
、FTP
、Telent
,甚至是工業控制系統常見的Modbus
協定,都會被儲存在這最後一層,因為那就是我們所要的資料。
而到底每一層的封包的欄位各代表什麼意思呢?筆者上圖的封包作為範例,讓讀者能夠快速看懂。
下面的這個封包主要是一個Modbus TCP的封包,是我從工控系統中所側錄得到的。
但不管是何種通訊協定的封包,對於傳輸層來講,都只是data而已,所以並不影響。
另外,若是要取得封包內容,除了可以自己寫程式去側錄封包外,也可以利用像Wireshark等封包監控軟體進行側錄。
00 18 23 3c 86 c6 00 18 23 3c d7 fb 08 00 45 00
00 3b 58 ac 00 00 ff 06 eb 0b c0 a8 7b 5a c0 a8
7b 59 35 81 01 f6 18 73 eb a1 52 d0 28 e7 50 18
02 00 b2 34 00 00 d7 fb 00 00 00 0d 01 10 10 03
00 03 06 09 cb 10 7e 03 94
而在整個封包當中,是不包含實體層(L1)的內容的,因此我們從資料連結層(L2)開始介紹起。
資料連結層(L2)封包內容
首先,對於資料傳輸層(L2)的封包,有以下內容:
00 18 23 3c 86 c6 00 18 23 3c d7 fb 08 00
其中,前8個Byte是來源MAC,後8個Byte是目的地MAC,最後兩個Byte則是定義採用哪一種網路協定,IPv4/IPv6
因此表格由以下呈現,而資料連結層固定為14Byte。
來源MAC | 目的MAC | Type |
00 18 23 3c 86 c6 | 00 18 23 3c d7 fb | 08 00 |
網路層(L3)封包內容
首先,對於網路層(L3的封包,有以下內容:
45 00 00 3b 58 ac 00 00 ff 06 eb 0b c0 a8 7b 5a c0 a8
7b 59
在維基百科中,有表格闡述每一個Byte在做什麼。注:下圖內的數字是以bit來顯示
表格由以下呈現,而長度為不固定,需要透過Header來計算。
Type&Header | Service | 封包總長 | 識別碼 | 可否切割 | 存活時間 | 協定 | Check Sum | 來源IP | 目的IP | Data |
45 | 00 | 00 3b | 58 ac | 00 00 | ff | 06 | eb 0b | c0 a8 7b 5a | c0 a8 7b 59 |
接下來為各位解說常用的一些欄位在做什麼:
Type&Header:該欄位佔1 Byte,主要由兩個欄位組成(Type、Header)。
- Type 欄位占4bit,通訊雙方使用的Type必須一致。其中若使用IPv4,欄位的值是4。
- Header欄位占4bit,用來定義網路層封包長度,但由於網路層的封包長度不固定,因此該欄位最小值為5,最大值為15,其中長度的計算為5*4=20 (Byte) 即網路層長度為20
Service:該欄位佔1 Byte,一般的情況下都不使用這個欄位。只有在使用VoIP時才會被指用,因此預設值為 0 0 。
封包總長:該欄位佔2 Byte,用來表示整個封包長度(但不含 資料連結層 L2 ),即L3~L5的長度。
識別碼:該欄位佔 2 Byte,用來識別該連線的唯一識別碼(或是有過大的封包會被切割時,可以用該識別碼 識別切割的封包有哪些)。
可否切割:該欄位佔 2 Byte,若封包過大時,則會定義該封包可否被切格為等量的小封包進行傳送。
存活時間:該欄位佔 2 Byte,為了避免封包在網路中永遠存在(例如陷入路由環路),封包經過的每個路由器都將此欄位減1,當此欄位為0時,封包不再向下傳送並被丟棄,最大值是255。
協定:該欄位占 1 Byte,用來定義了該封包資料區使用的協定。
傳輸層(L4)封包內容
首先,對於傳輸層(L4)的封包,有以下內容:
35 81 01 f6 18 73 eb a1 52 d0 28 e7 50 18
02 00 b2 34 00 00
在維基百科中,有表格闡述每一個Byte在做什麼。注:下圖內的數字是以bit來顯示
表格由以下呈現,而長度為不固定,需要透過flag來計算。
來源Port | 目的Port | 序列號 | 確認碼 | flag | window size | check sum | 緊急指標 |
35 81 | 01 f6 | 18 73 eb a1 | 52 d0 28 e7 | 50 18 | 02 00 | b2 34 | 00 00 |
接下來為各位解說常用的一些欄位在做什麼:
序列號:用來識別該連線的編號,每增加一條連線,該序號就會+1
確認碼:期望收到的資料的開始序列號。也即已經收到的資料的位元組長度加1。
flag:該欄位由三個值組成。
- 第一個數值為定義整個傳輸層(L4)的封包長度,其中長度的計算為5*4=20 (Byte) 即網路層長度為20。
- 資料偏移(4位元長)—以4位元組為單位計算出的資料段開始位址的偏移值。
- 保留(3位元長)—須置0
- 標誌符(9位元長)
- NS—ECN-nonce。
- CWR—Congestion Window Reduced。
- ECE—ECN-Echo有兩種意思,取決於SYN標誌的值。
- URG—為1表示高優先級封包,緊急指標欄位有效。
- ACK—為1表示確認號欄位有效
- PSH—為1表示是帶有PUSH標誌的資料,指示接收方應該儘快將這個報文段交給應用層而不用等待緩衝區裝滿。
- RST—為1表示出現嚴重差錯。可能需要重現建立TCP連接。還可以用於拒絕非法的報文段和拒絕連接請求。
- SYN—為1表示這是連接請求或是連接接受請求,用於建立連接和使順序號同步
- FIN—為1表示傳送方沒有資料要傳輸了,要求釋放連接
應用層(L5)封包
而到最後一層,傳輸層解析不懂的內容,也就是我們所謂的「應用層」,在應用層當中,我們可以看到我們常見到的協定,如 HTTP
、Telnet
、FTP
等,甚至是工業控制系統中的ModbusTCP
協定,都會在這一層當中顯現。
至於該怎麼解析,那就必須交由該協定來去做定義。以上述範例來說,我擷取的是ModbusTCP的完整封包,因此最後解析下來的,就會是剩下ModbusTCP的部分。
因此接下來就必須要去找ModbusTCP的協定來去讀懂每個欄位所定義的內容了。
至於該如何解析並看懂ModbusTCP的封包,筆者有另外寫一篇文章作介紹,有興趣的讀者們可以參考看看。
封包分層解析
最後,當我們了解完每一層的封包欄位資訊後,再來就是需要透過程式的方式,去分析這一整包的資料,也同時針對整包的資料分層做解析。
但就像上文所說,網路層與傳輸層的大小並不固定,因此要如何確切的取得每一層的內容,可以參考以下方法:
首先當我們拿到整包封包資料後,我們需要先知道,只有資料連結層(L2),固定為14Byte,其餘為不固定,因此我們需要透過「減法」的方式取得:
資料連結層(L2):固定為14Byte,因此直接取前14Byte資料即可
網路層(L3):由於資料長度不固定,但是我們可以透過Header欄位,我們將該欄位*4之後,即可得知L3長度為何。 (EX:最小值是5,因此5*4=20,可得知長度為20 Byte)
傳輸層(L4):由於資料長度不固定,但是我們可以透過flag欄位,我們將該欄位的第一個數字*4之後,即可得知L4長度為何。 (EX:最小值是5,因此5*4=20,可得知長度為20 Byte)
應用層(L5):最後一層的資料,也就是各位要解析的「資料」內容,我們可以透過「減法」方式進行計算,將總長度減去 L2、L3、L4的長度,剩餘的資料就是應用層的資料了。
而至於為什麼要採用減法的方式來去將整個封包進行分層的原因,主要是因為從L2開始的封包,長度大小就不固定了,另外因為最終我們所想要監控到的資料,都是存在應用層(L5),
因此裡面的不見得都是固定的長度,也不見得會有定義整個應用層的長度大小。
所以會建議採用減法的方式,將整個封包的內容,逐一將每一層的長度減去,那麼最終剩下的就會是應用層的內容。
以上就是整個封包監控的介紹,之後會再利用程式,再針對封包分析做更細部的介紹。
以上文章敘述如有錯誤及觀念不正確,請不吝嗇指教:)
有任何家教、案子 或技術相關問題 請都歡迎聯繫我