天天看點

【TCP】連接配接管理

TCP連接配接管理

  本節将介紹一條TCP連接配接是如何建立和拆除的。此處假設客戶機A上面的一個程序想要和服務

器B上的一個程序建立一條TCP連接配接。本文前面介紹的是比較正常的連接配接和拆除,特殊的會在後面介紹。

TCP連接配接建立

        

【TCP】連接配接管理

第一步

客戶機A的TCP會向伺服器的TCP發送一個不包含應用層資料的資料的TCP封包段。該封包段中首部标志位S YN被置為1,此封包段也被叫做SYN封包段。并且A會随機地選擇一個初始序号(client_isn),将其填入首部中的序号字段(注意為了避免某些安全性的攻擊,此處的随機化選擇有着不少研究,後面會補充)。然後,該封包被封裝進IP資料報,發送給伺服器。

第二步

一旦TCP SYN封包段的IP資料包到達伺服器後,伺服器就會從IP資料包中提取出TCP SYN封包段,為該TCP連接配接配置設定TCP緩存和變量,并向客戶機發送允許TCP連接配接的封包段,這個封包段也不包含應用層資料。(這裡需要注意如果在完成三次握手的第三步之前配置設定緩存和變量會使得TCP易受到稱為

SYN洪泛

的拒絕服務攻擊服務)

在發送的封包中,标志位SYN被置為1,确認序号被置為client_isn+1,

伺服器也會選用一個初始序号将其放入封包中的序号字段。這個封包有時也會被稱為SYNACK封包段(SYNACK segment)。

第三步

在收到SYNACK封包段後,客戶也要給這個連接配接配置設定緩存和變量。然後,客戶機A會向伺服器發送對允許連接配接

封包的确認,完成連接配接的建立。此時封包中,SYN置為0,确認序号為sever_isn+1。在此封包段中也可以攜帶客戶機到伺服器的資料了。

完成這三個步驟後,客戶機和伺服器就可以互相發送包含資料的封包段啦。在以後的每個封包中SYN都為0。

建立連接配接需要發送三個封包,是以這個過程也叫

3次握手(three-way shakehand)

那麼問題也出來了。為什麼需要三次握手,隻交換兩次封包不可以嗎?

可以簡單地解釋下,客戶發送确認伺服器發送的接收連接配接封包是為了防止以前的連接配接請求即失效連接配接請求發送到伺服器而造成錯誤。

TCP連接配接釋放

有連接配接必然就有釋放的時候。釋放的過程可以見下圖。

   

【TCP】連接配接管理

                   TCP連接配接釋放示意圖

客戶程序發出關閉TCP連接配接指令。客戶TCP便會向伺服器程序發送标志位FIN=1的封包段,便進入FIN_WAIT_1階段。伺服器TCP收到該封包段後就向客戶機發送确認封包段并通知上層應用程式該TCP連接配接即将關閉,然後,伺服器進入CLOSE_WAIT階段。

客戶機TCP收到确認封包,然後進入FIN_WAIT_2階段,等待來自伺服器的含有FIN=1的封包段。

伺服器在這段時間還是可以向客戶機發送含上層應用程式資料的封包段,客戶機接收并發送确認封包

。最後,伺服器TCP向客戶機發送含FIN=1的封包段,便進入LASE_ACK階段。

客戶機TCP收到含FIN=1的封包段向伺服器發出确認封包,便進入TIME_WAIT階段,等待2MSL後便釋放所有連接配接所占資源。如果客戶給伺服器發送的确認封包丢失,那麼在這段時間内,便可進行重傳操作。這段時間一過,客戶将釋放所有連接配接所占資源。

伺服器TCP收到客戶機的确認ACK後便釋放連接配接所占資源。

附圖兩張客戶機和伺服器在整個TCP連接配接期間的狀态序列

【TCP】連接配接管理
【TCP】連接配接管理

SYN洪泛攻擊

記得在前面說過伺服器收到一個SYN後,會配置設定緩存并初始化一些相關變量。然後向客戶發送SYNACK進行響應,并等待來自客戶的ACK封包段。如果某個客戶不發送ACK完成三次握手的第三步,最終(通常在一分多鐘後)伺服器将終止該半開連接配接并回收資源。

這種TCP連接配接管理協定為經典的DoS攻擊即SYN洪泛攻擊(SYN flood attack)提供了環境。在這種攻擊中,攻擊者發送大量的TCP SYN封包段,而不完成三次握手中的第三步,伺服器為大量的這種半開連接配接配置設定資源,最終将導緻伺服器的連接配接資源殆盡。

好的是,現在有一種有效的防禦系統——SYN cookie [RFC 4987],其工作方式可以描述如下:

  • 當伺服器接收到一個SYN封包時,不為該封包段生成一個半開連接配接 。相反, 伺服器為其生成一個初始TCP序列号,該序列号是用SYN封包段的源和目的IP位址與端口号以及僅有該伺服器知道的秘鑰生成的散列函數值

    。這個初始序列号也被叫做"cookie"。伺服器向發出連接配接請求的客戶發送TCP序号字段為這個初始序号的SYNACK分組 。

    但是最要的是,

    伺服器并不記憶該初始序号和其他有關這個SYN封包段的資訊
  • 如果客戶是合法的,那麼它會發送一個ACK封包段。當伺服器收到該ACK後,需要驗證該ACK是與前面發送的某些SYN相對應。

    伺服器将使用在SYNACK封包段中的源和目的IP位址與端口号和秘鑰運作相同的散列函數,

    計算該ACK封包段的散列函數值。如果散列函數值加1等同于客戶發來的這個ACK中确認号字段的值 ,那麼,伺服器就認為該ACK封包段對應于較早的SYN封包段,是以它是合法的。然後,伺服器生成一個具有套接字的全開連接配接!

    以上是正常的連接配接和釋放的過程,下面會對上面進行一些補充。

TCP連接配接建立和釋放的特殊情況

TCP半關閉

TCP支援半關閉操作,如前描述的釋放連接配接第二步中,客戶機發送了一個FIN封包給伺服器,伺服器發送了确認後,客戶機這邊就進入半關閉狀态,但是仍然可以接收來自伺服器發送的資料

。即“我完成了資料的發送工作,并發送了一個FIN給對方,但是我任然希望收到來自對方的資料直到它發送給一個FIN給我”。在伺服器未發送FIN的這段時間裡,它可以傳任意數量的封包段給客戶。當伺服器發送FIN然後FIN被确認,那麼整個連接配接将完全被關閉。

同時打開與關閉

兩個應用程式同時主動打開連接配接可能不大可能,但是在特定安排的情況下還有可能實作。這要求通信雙方收到對方SYN之前必須先發送一個SYN,兩個SYN必須經網絡到達對方,并要求通信雙方告知對方其IP位址和端口号。伺服器始終未被動打開,是以不會出現這種情況。

與正常連接配接相比,多了一個封包段。資料包的SYN将置位直到接收到一個ACK資料包為止。

  

【TCP】連接配接管理

同時關閉與前面的正常關閉并沒有太大的差別。在通信中,雙方都會主動發送FIN,然後進行關閉。

同時關閉和正常關閉是相同數量的封包段。兩者真正的差別在于封包段序列是交叉的還是順序的。

【TCP】連接配接管理

重置封包段

将TCP首部RST字段置位的封包段被稱為“重置封包段”或者“重置”。一般來說,當發現一個到達的封包段對于相關連接配接而言不正确時,TCP會發送一個重置封包段。(此處,

相關連接配接

是指由重置封包段的TCP與IP首部的四元組所指定的連接配接)。

針對不存在的端口的連接配接請求

通常,當一個連接配接請求到達本地卻沒有相關程序在目的端口偵聽時就會産生重置封包段。

UDP協定中規定,當一個資料報到達不能使用的目的端口時就會生成一個ICMP目的地不可達(端口不可達)的消息。

TCP則是使用重置封包段來代替相關工作。

對于被TCP重置的封包段而言,它的ACK位字段必須被置位,并且ACK号字段的數值必須在正确視窗範圍内。這樣有助于防止他人攻擊。

終止一條連接配接

終止一條正常連接配接的方法是由通信一方發送FIN。這種方法也被稱為

有序釋放

。在這種情況下,TCP緩存中所有排隊的資料都被發送,通常沒有資料丢失。

然而,在任何時刻,我們都可以通過發送一個重置封包段替代FIN來終止一條連接配接。這種方式也被稱為

終止釋放

終止一條連接配接為應用程式提供兩大特性:

  • 任何排隊的資料都将被發送出去,一個重置封包段會被立即發送出去
  • 重置封包段的接收方會說明通信另一端采用可終止的方法而不是一次正常的關閉。
需要注意:

重置封包段不會被通信另外一端做出任何響應,即它不會被确認。接收重置封包段的另一段會終止連接配接并通知應用程式目前連接配接已被重置。

半開連接配接

如果在未告知另一端的情況下通信的一端關閉或者終止連接配接,那麼就認為該TCP連接配接處于

半開狀态

。這種情況一般發生在通信一方的主機崩潰。隻要不嘗試通過半開連接配接傳輸資料,正常工作的一端不會檢測另一端已經崩潰。産生半開連接配接的另外一個共同原因是某台主機的電源被切斷而非正常關機。

時間等待錯誤

設計TIME_WAIT狀态的目的是允許任何受制于一條關閉連接配接的資料報被丢棄。在這段期間,等待TCP通常不需要做任何操作,它隻需要維持目前狀态直到2MSL的計時結束。然而,如果它在這段時間内收到任何關于這條連接配接的一些封包段,或者是更加特殊的重置封包,它将被破壞。這種情況被稱為

時間等待錯誤(TIME-WAIT Assaaination TWA RFC[1337])

為解決這個問題,許多系統規定當處于TIME-WAIT狀态時不對重置封包做出反應。

每天進步一點點,不要停止前進的腳步~

繼續閱讀