1. 程式人生 > >TCP-連線管理

TCP-連線管理

本文主要內容:

  1. TCP連線的建立與終止
  2. TCP引數選項
  3. TCP的路徑最大傳輸單元發現
  4. TCP狀態轉換
  5. 重置報文段
  6. TCP伺服器選項
  7. 與TCP連線管理相關的攻擊

1.TCP的狀態機

其實網路上的傳輸,是沒有具體的連線的。而TCP的連線其實是在兩端維護的一種連線連線,使兩端看起來好像連線著一樣。所以TCP的狀態轉變是非常重要的。

下圖是TCP連線的狀態機的變化圖。包括TCP的連線、斷開、傳輸資料的對照圖,另外,下面這兩個圖非常非常的重要,你一定要記牢。
這裡寫圖片描述

這裡寫圖片描述

經常被問到的是,TCP的連線為什麼需要三次握手,斷開需要四次揮手:

對於建連結的3次握手:
主要是要初始化Sequence Number 的初始值。通訊的雙方要互相通知對方自己的初始化的Sequence Number(縮寫為ISN:Inital Sequence Number)——所以叫SYN,全稱Synchronize Sequence Numbers。也就上圖中的 x 和 y。這個號要作為以後的資料通訊的序號,以保證應用層接收到的資料不會因為網路上的傳輸的問題而亂序(TCP會用這個序號來拼接資料)。

對於4次揮手:
其實你仔細看是2次,因為TCP是全雙工的,所以,傳送方和接收方都需要Fin和Ack。只不過,有一方是被動的,所以看上去就成了所謂的4次揮手。如果兩邊同時斷連線,那就會就進入到CLOSING狀態,然後到達TIME_WAIT狀態。下圖是雙方同時斷連線的示意圖(你同樣可以對照著TCP狀態機看):

這裡寫圖片描述

對於4次揮手:

TCP狀態轉換圖中:ESTABLISHED是通訊雙方雙向傳輸資料的狀態。FIN_WAIT_1、FIN_WAIT_2以及TIME_WAIT狀態用一個虛線方款括起來表示主動關閉。圖中總共有11種狀態:

  1. CLOSED:關閉狀態,沒有連線活動或正在進行;
  2. LISTEN:監聽狀態,伺服器正在等待連線進入;
  3. SYN_RCVD:收到一個連線請求,尚未確認;
  4. SYN_SENT:已經發出連線請求,等待確認;
  5. ESTABLISHED:連線建立,正常資料傳輸狀態;
  6. FIN_WAIT 1:(主動關閉)已經發送關閉請求,等待確認;
  7. FIN_WAIT 2:(主動關閉)收到對方關閉確認,等待對方關閉請求;
  8. TIME_WAIT:完成雙向關閉,等待所有分組死掉;
  9. CLOSING:雙方同時嘗試關閉,等待對方確認;
  10. CLOSE_WAIT:(被動關閉)收到對方關閉請求,已經確認;
  11. LAST_ACK:(被動關閉)等待最後一個關閉確認,並等待所有分組死掉。

TCP半關閉

由於TCP的連線與資料傳輸是雙向的,所以TCP支援半關閉狀態,也就是A->B的通道關閉之後,B還可以向A傳輸資料。不過TCP的半關閉特性在實際應用中很少使用,當我們呼叫系統呼叫函式close()函式的時候,都是指直接關閉兩個方向的連線。

同時開啟和關閉

TCP中對於同時開啟:它僅建立一條連線而不是兩條連線,狀態變遷圖如下:同時傳送SYN包,然後收到進行確認直接進入ESTABLISHED狀態,可以看到同時開啟需要連線建立需要4個報文段,比三次握手多一次!
這裡寫圖片描述

TCP的同時關閉和正常關閉是一樣報文,只是在於報文是順序的還是交叉的。

TCP的初始序列號

在一個端到端的連線中TCP報文段在經過網路路由後,可能會存在延遲抵達和排序混亂的情況,為了解決這一個問題需要仔細選擇初始序列號。

在傳送用於建立連線的SYN之前通訊雙方會選擇一個初始序列號,初始序列號會隨時間而改變,因此每一個連線都擁有不同的初始序列號。在TCP標準中初始序列號可被視為一個32位的計數器,該計數器數值每4微秒增加1。

TCP連線超時

當Server斷開的時候,Client會不斷重試傳送SYN訊號企圖建立連線。連線的時間差以一種指數回退的方式。

關於建連線時SYN超時

試想一下,如果server端接到了clien發的SYN後回了SYN-ACK後client掉線了,server端沒有收到client回來的ACK,那麼,這個連線處於一箇中間狀態,即沒成功,也沒失敗。於是,server端如果在一定時間內沒有收到的TCP會重發SYN-ACK。在Linux下,預設重試次數為5次,重試的間隔時間從1s開始每次都翻售,5次的重試時間間隔為1s, 2s, 4s, 8s, 16s,總共31s,第5次發出後還要等32s都知道第5次也超時了,所以,總共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 2^6 -1 = 63s,TCP才會把斷開這個連線。

2.TCP選項

TCP的頭部除了固定header還有多個選項,常用的選項有:
MSS:最大段大小選項
SACK:選擇確認選項
WSOPT:視窗縮放選項
TSOPT:時間戳選項
UTO:使用者超時選項

最大段大小選項MSS

最大段大小指TCP協議所允許的從對方接收到的最大報文段,因此這也是傳送方在傳送資料時所能夠使用的最大報文段。當建立一個TCP連線時候,通訊的每一方都要在SYN報文段裡面的MSS選項中說明自己允許的最大段大小。預設536位元組。

SACK

SACK(Selective ACK)是TCP選項,它使得接收方能告訴傳送方哪些報文段丟失,哪些報文段重傳了,哪些報文段已經提前收到等資訊。根據這些資訊TCP就可以只重傳哪些真正丟失的報文段。需要注意的是隻有收到失序的分組時才會可能會發送SACK,TCP的ACK還是建立在累積確認的基礎上的。

3. TCP的路徑最大傳輸單元MTU

如果在IP層要傳輸一個數據報比鏈路層的MTU還大,那麼IP層就會對這個資料報進行分片。一個數據報會被分為若干片,每個分片的大小都小於或者等於鏈路層的MTU值。當同一網路上的主機互相進行通訊時,該網路的MTU對通訊雙方非常重要。但當主機間要通過很多網路才能通訊時,對通訊雙方最重要的是通訊路徑中最小的MTU,因為在通訊路徑上不同網路的鏈路層MTU不同。通訊路徑中最小的MTU被稱為路徑MTU。

MTU=MSS+TCP Header+IP Header.

TIME_WAIT狀態

TIME_WAIT狀態也稱為2MSL等待狀態。MSLuejiushi最大段生存週期,也就是一個IP資料包能在網際網路上生存的最長時間,超過這個時間將在網路中消失。

當TCP執行一個主動關閉併發送最終的ACK時候,Client的連線必須處於TIME_WAIT狀態,並保持兩倍的MSL時間,這樣就能夠讓TCP重新發送最終ACK以避免出現丟失情況。重發ACK不是因為TCP重傳了ACK,而是因為另一方重發了FIN資料段,事實上Server總是重傳FIN直到收到一個最終的ACK。

1)為什麼 TIME_WAIT 狀態需要保持 2MSL 的時間?
因為如果 TIME_WAIT 狀態保持時間不足夠長 ( 比如小於 2MSL) ,第一個連線就正常終止了。 第二個擁有相同相關五元組的連接出現,而第一個連線的重複報文到達,干擾了第二個連線。 TCP 實現必須防止某個連線的重複報文在連線終止後出現,所以讓 TIME_WAIT 狀態保持時間足夠長 (2MSL) ,連線相應方向上的 TCP 報文要麼完全響應完畢,要麼被丟棄。建立第二個連線的時候,不會混淆。

2)IME_WAIT狀態的作用?
主動關閉的Socket端會進入TIME_WAIT狀態,並且持續2MSL時間長度,MSL就是maximum segment lifetime(最大分節生命期),這是一個IP資料包能在網際網路上生存的最長時間,超過這個時間將在網路中消失。MSL在RFC標準上建議是2分鐘,而源自berkeley的TCP實現傳統上使用30秒,因而,TIME_WAIT狀態一般維持在1-4分鐘。

3)TIME_WAIT狀態存在的理由?
a)可靠地實現TCP全雙工連線的終止
b)允許老的重複分節在網路中消逝

5.重置報文段RST

RST是TCP頭部的RST位欄位。 如果一個報文報將該欄位置位就表示是一個重置報文段。下面主要梳理一下會發送RST報文段的場景

1)針對不存在埠的連線請求
當一個連線請求到本地卻沒有相關程序在目的埠監聽就會產生一個重置報文段RST

2)半開連線:在未告知另一端的情況下通訊的另一端關閉或則終止連線,就認為該條TCP連線處於半開狀態。這種情況一般發生在一方主機宕機情況下,只要不通過半開連線傳輸資料,正常工作一方不會監測出另一端已經崩潰。伺服器重啟之後會丟失之前所有連線記憶,TCP規定會回覆一個RST報文段作為響應,然後兩端的連線被關閉。

6. TCP伺服器選項

  • TCP埠號
  • 限制本地IP地址
  • 限制外部節點
  • 進入連線佇列

連線佇列(半連線佇列和全連線佇列)

半連線佇列主要儲存處於SYN_REVD狀態的連線;全連線佇列儲存處於ESTABLISHED狀態的佇列。

在Linux系統中:
1)當一個連線請求到達(SYN報文段)將會檢查系統的引數 net.ipv4.tcp_max_syn_backlog(預設1000)。如果處於SYN_RECV狀態的連線數超過了這個閾值,進入的連線就會被拒絕(這裡可用於攻擊手段)

2)每一個處於監聽狀態的節點都擁有一個固定長度連線佇列,其中的連線已經被TCP完全接受(完成三次握手),但是還沒被應用程式接受。稱為全連線佇列(backlog)、backlog的數目必須在0與系統指定的最大債之間,最大值是net.core.somaxconn(預設值128)。注意這裡的限制於應用程式已經建立的連線沒有任何關係。

3)如果佇列已經沒有足夠空間分配給新的連線,TCP會延遲對SYN的響應,從而給應用程式一個跟上節奏的機會直到超時。 LInux在這一方面堅持在能力允許範圍內不忽略進入的連線,但是如果系統變數net.ipv4.tcp_abort_on 已被鎖定新進入的連線會被重置報文段RST重置。

7. 與TCP連線管理相關的攻擊

SYN泛洪就是一種,這種攻擊產生一系列的TCP嘗試連線的攻擊(SYN報文段)。