1. 程式人生 > >Linux網絡編程--wireshark分析TCP包頭的格式

Linux網絡編程--wireshark分析TCP包頭的格式

一點 linux網絡編程 協議 相關 enter 流控 問題 如果 sum

摘要:

本文簡介了TCP面向連接理論知識,具體講述了TCP報文各個字段含義。並從Wireshark俘獲分組中選取TCP連接建立相關報文段進行分析。


一、概述

TCP是面向連接的可靠傳輸協議,兩個進程互發數據之前須要建立連接,這裏的連接僅僅只是是端系統中分配的一些緩存和狀態變量,中間的分組交換機不維護不論什麽連接狀態信息。

連接建立整個步驟例如以下(即三次握手協議):

首先,客戶機發送一個特殊的TCP報文段;

其次,server用還有一個特殊的TCP報文段來響應;

最後,客戶機再用第三個特殊報文段作為響應。

技術分享

圖1 三次握手協議示意圖[1]

二、TCP報文格式

2.1 概述

為了提供可靠的傳輸數據,TCP報文首部字段有較多的字段。TCP報文格式例如以下圖:

技術分享

圖2 TCP報文格式

源和目標port

用於多路復用/多路分解來自或送至上層應用的數據。能夠這樣理解。port用來標識同一臺計算機的不同進程。

序列號和確認號

這兩個字段是TCP可靠傳輸服務的關鍵部分,序列號是該報文段首字節的字節流編號(TCP把數據看成是有序的字節流,TCP隱式地對數據流的每一個字節進行編號)。這樣理解可能更直觀,當報文被分解成多個報文段時。序列號就是報文段首字節在整個報文的偏移量。確定號指定下一個期待的字節。TCP是全雙工的,如果從主機A接收到主機B的數據,則主機A填充進報文段的確認號是主機A期望從主機B收到的下一個字節序號。

還沒理清這兩者的關系?見下圖(三次握手):

技術分享

圖3 正常情況下TCP連接建立過程

首部長度(4位)

由於選項是不定長的,這就須要標識整個首部字段的長度(單位是32位字),即5+選項個數。4位,單位是32位字,所以首部最長是15*4=60字節,即選項最長是40字節(10個選項)。

標誌

URG

指示報文段裏存在著被發送方的上層實體標記為"緊急"數據,當URG=1時,其後的緊急指針指示緊急數據在當前數據段中的位置(相對於當前序列號的字節偏移量),TCP接收方必須通知上層實體。

ACK

當ACK=0時,表示該數據段不包括確認信息。當ACK=1時。表示該報文段包括一個對已被成功接收報文段的確認。

PSH

當PSH=1時。接收方在收到數據後馬上將數據交給上層,而不是直到整個緩沖區滿。

RST

用於重置一個已經混亂的連接(如主崩潰),也可用於拒絕一個無效的數據段或者拒絕一個連接請求。一般而言,假設你得到的數據段被設置了RST位。那說明你這一端有問題了。

SYN

用於建立連接過程,在連接請求中。SYN=1和ACK=0表示該數據段沒有使用捎帶的確認域,而連接應答捎帶一個確認。即SYN=1和ACK=1

註:捎帶是指對客戶機到server數據的確認被裝載在一個承載server到客戶機的數據報文段中。

FIN

用於釋放一個連接,表示發送方已經沒有數據要傳輸了。

此時,接收方可能繼續接收數據。好在SYN和FIN數據段都有序列號。從而保證了這兩種數據段以正確順序被處理。

窗體大小

用於流控制(確保連接的不論什麽一方都不會過快地發送過量的分組而淹沒還有一方),窗體大小指定了從被確認的字節算起能夠發送多少個字節。

校驗和

提供了額外可靠性。在計算檢驗和的時候,TCP的Checksum域設為0,假設數據域的字節數為奇數,則數據域填補一個額外的0字節。校驗和算法:將全部的16位字按1的補碼形式累加起來。取累加結果的補碼。因此,當接收方運行相同計算時(包含Checksum域),結果應該是0。

緊急指針

參考標誌字段的URG位。

選項

選項部分是為了適合復雜網絡環境和更好地服務於應用層設計的。

TCP選項最長是40字節。詳情見2.2。

數據

無不論什麽數據的TCP段也是合法的。通經常使用於確認和控制信息。

2.2 選項字段[2]

TCP選項部分非常好出如今已經建立連接的會話中。僅僅要出如今TCP連接建立階段,即三次握手。TCP選項部分實際運用有下面幾種:

(1)最大報文傳輸段(MMS, Maximum Segment Size)

用於發送發與接收方協商最大報文段長度(不過凈荷數據,不包含TCP首部字段)。TCP在三次握手中,每一方都會通告期望收到的MSS(MSS只出如今SYN數據包中),假設一方不接受還有一方的MSS值,則使用默認的536字節凈荷數據,即主機可以接受20+536字節的TCP報文段。

(2)窗體擴大選項(Window scaling)

TCP報文的窗體大小字段占16位。即最大值是65535,但隨著時延和帶寬比較大的通信產生(如衛星通信),須要更大的窗體滿足性能和吞吐率。這就是窗體擴大選項存在的意義。樣例見參考資料[2]。

Windows scaling占3個字節,最後一個字節是移位值(Shift count),即首部的窗體位數16向左移動,如移位值為14。則新的窗體最大值增大到65535*(2^14)。

窗體擴大選項是在TCP建立之初進行協商,假設已實現了窗體擴大。當不再須要擴大窗體時。發送移位值=0就能夠恢復到原窗體大小。即65535。

(3)選擇確認選項(SACK, Selective Acknowledgements)

考慮這樣情況,主機A發送報文段12345,主機B收到135且報文無差錯。SACK用來確保僅僅重傳缺少的報文段,而不是重傳全部報文段。

SACK選項須要2個功能字節。一個用來指明使用SACK選項(SACK Permission),還有一指明這個選項占多少字節。

那怎麽形容丟失的報文段2。說明2的左右邊界各自是1、3。TCP的數據報文是有字塊邊界的。而這樣的邊界是由序列號表示的。

最多能指明多少個字節塊的邊界信息呢?答案是4個。這是由於選項字段最大是40字節,去除2個功能字節。序列號是32位即4字節,而且須要左右邊界。所以(40-2)/8 = 4。

(4)時間戳選項(timestamps)

時間戳選項用來計算往返時間RTT,發送方在發送報文段時把當前時鐘的時間值放入時間戳字段,接收方將該時間戳字段的值拷貝到確認報文中,當接收方收到確認報文,對照確認報文的時間戳(等於發送方發送報文段的時間戳)和如今的時鐘,就可以算出RTT。

時間戳選項還可用於防止回繞序號PAWS。

序列號僅僅有32位,每2^32個序列號就會回繞(想想環形隊列)。採用時間戳選項非常easy區分同樣序列號的報文段。

(5)NOP(NO-Operation)

TCP的頭部必須是4字節的倍數,而大多數選項不是4字節倍數。不足的用NOP填充。

除此之外,NOP也用於切割不同的選項數據,如窗體擴大選項和SACK之間使用NOP隔離(以下的實例將看到這一點)。


三、實例解析

3.1 概述

還是以訪問百度首頁為例,首先用DNS協議將URL解析成IP地址,接著在客戶機和server間建立TCP連接。用Wireshark俘獲的分組例如以下圖:

技術分享

圖4 Wireshark俘獲建立TCP連接分組

你一看會認為有些奇怪,理論上應該是3個分組的,怎麽有6個分組?先不急。先把這6個報文收發示意圖作出來(結合時間和報文含義),例如以下:

技術分享

圖5 TCP連接建立實例

從圖可知,連接建立伊始。客戶機發了兩個報文段。這或許是為了更快建立連接(如果有個請求報文段丟失。也不至於要等一段時間,重發報文)。接下來。以19、21、22(上圖紅色線條所看到的)分析TCP連接建立過程。

3.1 第一次握手19

Wireshark俘獲TCP連接第一次握手的報文段例如以下:

技術分享

圖6 TCP連接第一次握手實例

這裏主要挑幾個字段分析:

標誌字段。SYN=1、ACK=0表示該數據段沒有使用捎帶的確認域。

最大報文段長度(MMS)1460是怎麽來的。鏈路層的以太網物理特性決定數據幀長度為1500(即MTU,最大傳輸單元),1460=1500-20(IP首部長度)-20(TCP首部長度)。不要被該報文首部長度32字節所迷惑,這僅僅是建立連接過程。MSS與MTU關系見下圖[2]:

技術分享

圖7 MSS與MTU關系

NOP字段。能夠作為不足4倍數字節填充,也可作為選項間分隔,該報文段出現了3個NOP,詳細功能見下圖:

技術分享

圖8 TCP報文NOP字段

3.3 第二次握手21

server響應clientTCP報文段,此時確認號為1了。SYN=1、ACK=1表明連接應答捎帶一個確認,Wireshark俘獲分組例如以下:

技術分享

圖9 TCP連接第二次握手實例

為什麽MSS是1452而不是1460?

這是由於使用PPPoE(Point-to-Point over Ethernet。能夠使以太網的主機通過一個簡單的橋接設備連到一個無端的接入集中器上[3])撥號上網。PPoP首部是8個字節,所以PPPoE的MTU是1492,MSS也就為1492-40=1452。

那麽,TCP連接建立後傳輸數據的MSS是多少呢,1460 or 1452 or 536 ?我的理解是默認值536,這樣理解對嗎?求指點!

3.4 第三次握手22

客戶機再次server的報文段,此時序列號和確認號都為1。沒有選項字段,Wireshark俘獲的分組信息例如以下:

技術分享

圖10 TCP連接第三次握手實例

值得註意的。由於窗體擴展大小協商未果,所以就不擴大窗體了,即窗體大小最大為65535。


如此,TCP連接建立:-)

Linux網絡編程--wireshark分析TCP包頭的格式