1. 程式人生 > >TCP三次握手建立連線

TCP三次握手建立連線

因為我個人向左C++相關方向的開發,所以面試時TCP三次握手也是一個被經常問到的知識點。今天在這裡就對TCP三次握手的過程進行總結,分析。如果有哪些知識點沒有總結到位,還望各位大神提點。我們假設一個client向server傳送TCP連線請求

1、TCP三次握手的圖示過程


2、TCP三次握手描述

這裡客戶端要使用伺服器上的某個基於TCP的服務,這裡就說下三次握手建立連線的過程。

第一次握手:客戶端向伺服器端傳送一個連線請求報文。這個報文的主要資訊為SYN=1,ACK=0,seq=X,mss=1024

                client--------------SYN=1,ACK=0,seq=X,mss=1024-------------------->server


第二次握手:伺服器端收到連線請求報文後給客戶端返回一個請求+確認報文,這個報文中SYN=1,ACK=1,seq=Y,ack=X+1,mss=1024

               client<-------------SYN=1,ACK=1,seq=Y,ack=X+1,mss=1024---------------------server


第三次握手:客戶端收到伺服器端的報文後給客戶端返回一個確認報文,完成TCP三次握手。通訊雙方連線建立完成。

                client---------------------SYN=0,ACK=1,ack=Y+1---------------------------->server


注意:TCP連線通訊雙發是全雙工的。在每個SYN=1的報文的選項欄位中有一個mss(最大報文段長度)值,用於告訴對方自己的能夠傳送的最大報文段長度。最終以兩者最小值作為mss,兩次SYN報文以“協商”的方式來獲取本次通訊過程中TCP報文的mss。

3、TCP三次握手過程中出現的問題

Q1:為什麼要使用三次握手,而不是兩次握手?

答:簡單的說是為了防止已經失效的連線請求到達伺服器端。

SYN連線請求報文從客戶端到達伺服器端所經過的網路路徑是非常複雜的,每一次傳輸路徑都是不確定的(由具體的路由器,網路擁堵情況決定)。當客戶端發出一個連線請求報文後會啟動一個定時器,如果網路傳送擁塞,當在規定時間內客戶端沒有收到SYN+ACK報文的話就認為之前傳送的SYN報文段在傳輸過程中丟失了,客戶端會使用“超時重傳”機制重新發送一個新SYN連線請求報文段。但是實際上之前那個連線請求報文沒有失效,只不過是在網路中滯留的時間比較長,一段時間後這個報文還是會到達伺服器端。然後伺服器端收到這個報文後會返回一個SYN+ACK應答報文,但是客戶端認為這個我並沒有傳送這個請求報文(因為這個報文已經失效了,通過報文段的序列號可以知道並沒有傳送這個報文的連線請求),因此不會理會這個應答報文。

如果採用兩次握手的話,客戶端收到一個應答報文就相當於建立了TCP連線。那麼就不能處理網路中很多失效的報文。

Q2:什麼是SYN攻擊?

答:在三次握手過程中,當伺服器端傳送SYN+ACK報文(第二次握手)後,而客戶端傳送ACK報文(第三次握手)之前,這被稱為“半連線”狀態。

在每個伺服器端都有一個“連線請求佇列”,如果伺服器端正在處理某個請求,那麼新來的請求就要先暫存在連線請求佇列中。這個佇列的長度也是有限的。

所謂“SYN攻擊”就是攻擊程式虛擬出多個不同IP的客戶端,不斷的向伺服器端傳送SYN報文。伺服器端收到SYN報文後,就會給目的IP標示的客戶端返回SYN+ACK報文,並且等待收到客戶端的ACK報文。但是這些客戶端的IP都是惡意程式虛擬出來的,實際並不存在,這會造成伺服器端因為不能收到客戶端的確認報文而不斷地超時重發SYN+ACK報文。這使得正常請求報文的因為連線請求佇列滿而被丟棄,從而引發網路阻塞甚至癱瘓。

檢測SYN攻擊也是比較簡單的,即當server端有大量的半連線狀態,並且源IP地址都是隨機的,可以確定伺服器端遭受了SYN攻擊。

linux下檢測SYN攻擊的命令為:netstat -n -p TCP | grep SYN_RECV