TCP三次握手和四次揮手以及缺陷

建立TCP需要三次握手才能建立,而斷開連接則需要四次握手。整個(gè)過程如下圖所示:

1、TCP連接建立——三次握手

幾個(gè)概念:

【1】seq:序號(hào),占4個(gè)字節(jié),范圍[0,4284967296],由于TCP是面向字節(jié)流的,在一個(gè)1個(gè)TCP連接中傳送字節(jié)流中的每一個(gè)字節(jié)都按照順序編號(hào),此外序號(hào)是循環(huán)使用的。

【2】ACK: 僅當(dāng)ACK=1時(shí)確認(rèn)字段才有效,當(dāng)ACK=0時(shí)確認(rèn)字段無效,并且TCP規(guī)定,在連接建立后所有的傳送報(bào)文段都必須要把ACK置為1。

【3】SYN:同步序列號(hào),用來發(fā)起一個(gè)連接。當(dāng)SYN=1而ACK=0時(shí)表明這是一個(gè)請(qǐng)求報(bào)文段;若對(duì)方同意連接,則響應(yīng)報(bào)文中SYN=1,ACK=1。

【4】FIN :用來釋放一個(gè)連接,當(dāng)FIN=1表示此報(bào)文段的發(fā)送方已經(jīng)發(fā)送完畢。并要求釋放鏈接。

1.1、3次握手過程

服務(wù)端的TCP進(jìn)程先創(chuàng)建傳輸控制塊TCB,準(zhǔn)備接受客戶端進(jìn)程的連接請(qǐng)求,然后服務(wù)端進(jìn)程處于LISTEN狀態(tài),等待客戶端的連接請(qǐng)求,如有,則作出響應(yīng)。

1、客戶端的TCP進(jìn)程也首先創(chuàng)建傳輸控制模塊TCB,然后向服務(wù)端發(fā)出連接請(qǐng)求報(bào)文段,該報(bào)文段首部中的SYN=1,ACK=0,同時(shí)選擇一個(gè)初始序號(hào) seq=i。TCP規(guī)定,SYN=1的報(bào)文段不能攜帶數(shù)據(jù),但要消耗掉一個(gè)序號(hào)。這時(shí),TCP客戶進(jìn)程進(jìn)入SYN—SENT(同步已發(fā)送)狀態(tài),這是 TCP連接的第一次握手。

2、服務(wù)端收到客戶端發(fā)來的請(qǐng)求報(bào)文后,如果同意建立連接,則向客戶端發(fā)送確認(rèn)。確認(rèn)報(bào)文中的SYN=1,ACK=1,確認(rèn)號(hào)ack=i+1,同時(shí)為自己 選擇一個(gè)初始序號(hào)seq=j。同樣該報(bào)文段也是SYN=1的報(bào)文段,不能攜帶數(shù)據(jù),但同樣要消耗掉一個(gè)序號(hào)。這時(shí),TCP服務(wù)端進(jìn)入SYN—RCVD(同步收到)狀態(tài),這是TCP連接的第二次握手。

3、TCP客戶端進(jìn)程收到服務(wù)端進(jìn)程的確認(rèn)后,還要向服務(wù)端給出確認(rèn)。確認(rèn)報(bào)文段的ACK=1,確認(rèn)號(hào)ack=j+1,而自己的序號(hào)為seq=i+1。 TCP的標(biāo)準(zhǔn)規(guī)定,ACK報(bào)文段可以攜帶數(shù)據(jù),但如果不攜帶數(shù)據(jù)則不消耗序號(hào),因此,如果不攜帶數(shù)據(jù),則下一個(gè)報(bào)文段的序號(hào)仍為seq=i+1。這時(shí),TCP連接已經(jīng)建立,客戶端進(jìn)入ESTABLISHED(已建立連接)狀態(tài)。這是TCP連接的第三次握手,可以看出第三次握手客戶端已經(jīng)可以發(fā)送攜帶數(shù)據(jù)的報(bào)文段了。

當(dāng)服務(wù)端收到確認(rèn)后,也進(jìn)入ESTABLISHED(已建立連接)狀態(tài)。

1.2、關(guān)于第三次握手的解釋

前倆比較容易理解,第三次握手看似多余其實(shí)不然,這主要是為了防止已失效的請(qǐng)求報(bào)文段突然又傳送到了服務(wù)端而產(chǎn)生連接的誤判。

比如:客戶端發(fā)送了一個(gè)連接請(qǐng)求報(bào)文段A到服務(wù)端,但是在某些網(wǎng)絡(luò)節(jié)點(diǎn)上長(zhǎng)時(shí)間滯留了,而后客戶端又超時(shí)重發(fā)了一個(gè)連接請(qǐng)求報(bào)文段B到該服務(wù)端,而后正常建立連接,數(shù)據(jù)傳輸完畢,并釋放了連接。但是請(qǐng)求報(bào)文段A延遲了一段時(shí)間后,又到了服務(wù)端,這本是一個(gè)早已失效的報(bào)文段,但是服務(wù)端收到后會(huì)誤以為客戶端又發(fā)出了一次連接請(qǐng)求,于是向客戶端發(fā)出確認(rèn)報(bào)文段,并同意建立連接。那么問題來了,假如這里沒有三次握手,這時(shí)服務(wù)端只要發(fā)送了確認(rèn),新的連接就建立了,但由于客戶端沒有發(fā)出建立連接的請(qǐng)求,因此不會(huì)理會(huì)服務(wù)端的確認(rèn),也不會(huì)向服務(wù)端發(fā)送數(shù)據(jù),而服務(wù)端卻認(rèn)為新的連接已經(jīng)建立了,并在一直等待客戶端發(fā)送數(shù)據(jù),這樣服務(wù)端就會(huì)一直等待下去,直到超出?;钣?jì)數(shù)器的設(shè)定值,而將客戶端判定為出了問題,才會(huì)關(guān)閉這個(gè)連接。這樣就浪費(fèi)了很多服務(wù)器的資源。而如果采用三次握手,客戶端就不會(huì)向服務(wù)端發(fā)出確認(rèn),服務(wù)端由于收不到確認(rèn),就知道客戶端沒有要求建立連接,從而不建立該連接。

2、 缺陷引起的SYN Flood

2.1、SYN Flood 攻擊

SYN-Flood攻擊是當(dāng)前網(wǎng)絡(luò)上最為常見的DDoS攻擊,也是最為經(jīng)典的拒絕服務(wù)攻擊,它就是利用了TCP協(xié)議實(shí)現(xiàn)上的一個(gè)缺陷,通過向網(wǎng)絡(luò)服務(wù)所在端口發(fā)送大量的偽造源地址的攻擊報(bào)文,就可能造成目標(biāo)服務(wù)器中的半開連接隊(duì)列被占滿,從而阻止其他合法用戶進(jìn)行訪問。這種攻擊早在1996年就被發(fā)現(xiàn),但至今仍然顯示出強(qiáng)大的生命力。很多操作系統(tǒng),甚至防火墻、路由器都無法有效地防御這種攻擊,而且由于它可以方便地偽造源地址,追查起來非常困難。它的數(shù)據(jù)包特征通常是,源發(fā)送了大量的SYN包,并且缺少三次握手的最后一步握手ACK回復(fù)。

原理:攻擊者首先偽造地址對(duì)服務(wù)器發(fā)起SYN請(qǐng)求,服務(wù)器回應(yīng)(SYN+ACK)包,而真實(shí)的IP會(huì)認(rèn)為,我沒有發(fā)送請(qǐng)求,不作回應(yīng)。服務(wù)器沒有收到回應(yīng),這樣的話,服務(wù)器不知 道(SYN+ACK)是否發(fā)送成功,默認(rèn)情況下會(huì)重試5次(tcp_syn_retries)。這樣的話,對(duì)于服務(wù)器的內(nèi)存,帶寬都有很大的消耗。攻擊者如果處于公網(wǎng),可以偽造IP的話,對(duì)于服務(wù)器就很難根據(jù)IP來判斷攻擊者,給防護(hù)帶來很大的困難。

2.2、SYN Flood 防護(hù)措施

2.2.1. 無效連接監(jiān)視釋放

這種方法不停的監(jiān)視系統(tǒng)中半開連接和不活動(dòng)連接,當(dāng)達(dá)到一定閾值時(shí)拆除這些連接,釋放系統(tǒng)資源。這種絕對(duì)公平的方法往往也會(huì)將正常的連接的請(qǐng)求也會(huì)被釋放掉,“傷敵一千,自損八百”。

2.2.2. 延緩TCB分配方法

SYN Flood關(guān)鍵是利用了,SYN數(shù)據(jù)報(bào)文一到,系統(tǒng)立即分配TCB資源,從而占用了系統(tǒng)資源,因此有倆種技術(shù)來解決這一問題。

Syn Cache技術(shù)

這種技術(shù)在收到SYN時(shí)不急著去分配TCB,而是先回應(yīng)一個(gè)ACK報(bào)文,并在一個(gè)專用的HASH表中(Cache)中保存這種半開連接,直到收到正確的ACK報(bào)文再去分配TCB。

Syn Cookie技術(shù)

Syn Cookie技術(shù)則完全不使用任何存儲(chǔ)資源,它使用一種特殊的算法生成Sequence Number,這種算法考慮到了對(duì)方的IP、端口、己方IP、端口的固定信息,以及對(duì)方無法知道而己方比較固定的一些信息,如MSS、時(shí)間等,在收到對(duì)方的ACK報(bào)文后,重新計(jì)算一遍,看其是否與對(duì)方回應(yīng)報(bào)文中的(Sequence Number-1)相同,從而決定是否分配TCB資源。

2.2.3. 使用SYN Proxy防火墻

原理:對(duì)試圖穿越的SYN請(qǐng)求進(jìn)行驗(yàn)證之后才放行。

3、經(jīng)歷狀態(tài)

3.1 Client端所經(jīng)歷的狀態(tài)

3.2 Server端所經(jīng)歷的狀態(tài)

確認(rèn)報(bào)文段

4、常見問題:

4.1、為什么連接的時(shí)候是三次握手,關(guān)閉的時(shí)候卻是四次握手?

答:因?yàn)楫?dāng)Server端收到Client端的SYN連接請(qǐng)求報(bào)文后,可以直接發(fā)送SYN+ACK報(bào)文。其中ACK報(bào)文是用來應(yīng)答的,SYN報(bào)文是用來同步的。但是關(guān)閉連接時(shí),當(dāng)Server端收到FIN報(bào)文時(shí),很可能并不會(huì)立即關(guān)閉SOCKET,所以只能先回復(fù)一個(gè)ACK報(bào)文,告訴Client端,”你發(fā)的FIN報(bào)文我收到了”。只有等到我Server端所有的報(bào)文都發(fā)送完了,我才能發(fā)送FIN報(bào)文,因此不能一起發(fā)送。故需要四步握手。

4.2、為什么存在TIME_WAIT狀態(tài)?

答:1、可靠的終止TCP連接

第一個(gè)原因很好理解。假設(shè)用于確認(rèn)服務(wù)端FIN報(bào)文段的客戶端ACK報(bào)文段丟失,那么服務(wù)器將重發(fā)FIN報(bào)文段。因此客戶端應(yīng)停留在某個(gè)狀態(tài)以處理重復(fù)收到的報(bào)文段(即向服務(wù)器重發(fā)ACK報(bào)文段)。否則,客戶端將以復(fù)位報(bào)文段來回應(yīng)服務(wù)器,服務(wù)器則認(rèn)為這是一個(gè)錯(cuò)誤,因?yàn)樗谕氖且粋€(gè)ACK確認(rèn)報(bào)文段。

2、保證讓遲來的TCP報(bào)文段有足夠的時(shí)間被識(shí)別并丟棄

4.3、TCP第三次握手失敗怎么辦?

在此,將《TCP/IP協(xié)議族》中每一個(gè)狀態(tài)的轉(zhuǎn)換偽代碼整理下:

可以看出當(dāng)失敗時(shí)服務(wù)器并不會(huì)重傳ack報(bào)文,而是直接發(fā)送RTS報(bào)文段,進(jìn)入CLOSED狀態(tài)。這樣做的目的是為了防止SYN洪泛攻擊。

4.4、為什么不能用兩次握手進(jìn)行連接

我們知道,3次握手完成兩個(gè)重要的功能,既要雙方做好發(fā)送數(shù)據(jù)的準(zhǔn)備工作(雙方都知道彼此已準(zhǔn)備好),也要允許雙方就初始序列號(hào)進(jìn)行協(xié)商,這個(gè)序列號(hào)在握手過程中被發(fā)送和確認(rèn)?,F(xiàn)在把三次握手改成僅需要兩次握手,死鎖是可能發(fā)生的。作為例子,考慮計(jì)算機(jī)S和C之間的通信,假定C給S發(fā)送一個(gè)連接請(qǐng)求分組,S收到了這個(gè)分組,并發(fā)送了確認(rèn)應(yīng)答分組。按照兩次握手的協(xié)定,S認(rèn)為連接已經(jīng)成功地建立了,可以開始發(fā)送數(shù)據(jù)分組??墒?,C在S的應(yīng)答分組在傳輸中被丟失的情況下,將不知道S是否已準(zhǔn)備好,不知道S建立什么樣的序列號(hào),C甚至懷疑S是否收到自己的連接請(qǐng)求分組。在這種情況下,C認(rèn)為連接還未建立成功,將忽略S發(fā)來的任何數(shù)據(jù)分組,只等待連接確認(rèn)應(yīng)答分組。而S在發(fā)出的分組超時(shí)后,重復(fù)發(fā)送同樣的分組。這樣就形成了死鎖。

5、小知識(shí)

a.默認(rèn)情況下(不改變socket選項(xiàng)),當(dāng)你調(diào)用close(or closeSocket,以下說close不再重復(fù))時(shí),如果發(fā)送緩沖中還有數(shù)據(jù),TCP會(huì)繼續(xù)把數(shù)據(jù)發(fā)送完。

b.發(fā)送了FIN只是表示這端不能繼續(xù)發(fā)送數(shù)據(jù)(應(yīng)用層不能再調(diào)用send發(fā)送),但是還可以接收數(shù)據(jù)。

c.應(yīng)用層如何知道對(duì)端關(guān)閉?通常,在最簡(jiǎn)單的阻塞模型中,當(dāng)你調(diào)用recv時(shí),如果返回0,則表示對(duì)端關(guān)閉。在這個(gè)時(shí)候通常的做法就是也調(diào)用close,那么TCP層就發(fā)送FIN,繼續(xù)完成四次握手。如果你不調(diào)用close,那么對(duì)端就會(huì)處于FIN_WAIT_2狀態(tài),而本端則會(huì)處于CLOSE_WAIT狀態(tài)。

d.在很多時(shí)候,TCP連接的斷開都會(huì)由TCP層自動(dòng)進(jìn)行,例如你CTRL+C終止你的程序,TCP連接依然會(huì)正常關(guān)閉。

6、TIME_WAIT狀態(tài)

a.從以上TCP連接關(guān)閉的狀態(tài)轉(zhuǎn)換圖可以看出,主動(dòng)關(guān)閉的一方在發(fā)送完對(duì)對(duì)方FIN報(bào)文的確認(rèn)(ACK)報(bào)文后,會(huì)進(jìn)入TIME_WAIT狀態(tài)。TIME_WAIT狀態(tài)也稱為2MSL狀態(tài)。

b.什么是2MSL?MSL即Maximum Segment Lifetime,也就是報(bào)文最大生存時(shí)間,引用《TCP/IP詳解》中的話:“它(MSL)是任何報(bào)文段被丟棄前在網(wǎng)絡(luò)內(nèi)的最長(zhǎng)時(shí)間。”那么,2MSL也就是這個(gè)時(shí)間的2倍。其實(shí)我覺得沒必要把這個(gè)MSL的確切含義搞明白,你所需要明白的是,當(dāng)TCP連接完成四個(gè)報(bào)文段的交換時(shí),主動(dòng)關(guān)閉的一方將繼續(xù)等待一定時(shí)間(2-4分鐘),即使兩端的應(yīng)用程序結(jié)束。

c.為什么需要2MSL?根據(jù)《TCP/IP詳解》和《The TCP/IP Guide》中的說法,有兩個(gè)原因:

其一,保證發(fā)送的ACK會(huì)成功發(fā)送到對(duì)方,如何保證?我覺得可能是通過超時(shí)計(jì)時(shí)器發(fā)送。這個(gè)就很難用代碼演示了。

其二,報(bào)文可能會(huì)被混淆,意思是說,其他時(shí)候的連接可能會(huì)被當(dāng)作本次的連接。直接引用《The TCP/IP Guide》的說法:The second is to provide a“buffering period” between the end of this connection and any subsequent ones. If not for this period, it is possible that packets from different connections could be mixed, creating confusion.

d.TIME_WAIT狀態(tài)所帶來的影響:

當(dāng)某個(gè)連接的一端處于TIME_WAIT狀態(tài)時(shí),該連接將不能再被使用。事實(shí)上,對(duì)于我們比較有現(xiàn)實(shí)意義的是,這個(gè)端口將不能再被使用。某個(gè)端口處于TIME_WAIT狀態(tài)(其實(shí)應(yīng)該是這個(gè)連接)時(shí),這意味著這個(gè)TCP連接并沒有斷開(完全斷開),那么,如果你bind這個(gè)端口,就會(huì)失敗。對(duì)于服務(wù)器而言,如果服務(wù)器突然crash掉了,那么它將無法再2MSL內(nèi)重新啟動(dòng),因?yàn)閎ind會(huì)失敗。解決這個(gè)問題的一個(gè)方法就是設(shè)置socket的SO_REUSEADDR選項(xiàng)。這個(gè)選項(xiàng)意味著你可以重用一個(gè)地址。

7、各種狀態(tài)解析

FIN_WAIT_1: FIN_WAIT_1和FIN_WAIT_2狀態(tài)的真正含義都是表示等待對(duì)方的FIN報(bào)文。而這兩種狀態(tài)的區(qū)別是: FIN_WAIT_1狀態(tài)實(shí)際上是當(dāng)SOCKET在ESTABLISHED狀態(tài)時(shí),它想主動(dòng)關(guān)閉連接,向?qū)Ψ桨l(fā)送了FIN報(bào)文,此時(shí)該SOCKET即進(jìn)入到FIN_WAIT_1狀態(tài)。而當(dāng)對(duì)方回應(yīng)ACK報(bào)文后,則進(jìn)入到FIN_WAIT_2狀態(tài),當(dāng)然在實(shí)際的正常情況下,無論對(duì)方何種情況下,都應(yīng)該馬上回應(yīng)ACK報(bào)文,所以FIN_WAIT_1狀態(tài)一般是比較難見到的,而FIN_WAIT_2狀態(tài)還有時(shí)常常可以用netstat看到。(主動(dòng)方)

FIN_WAIT_2:上面已經(jīng)詳細(xì)解釋了這種狀態(tài),實(shí)際上FIN_WAIT_2狀態(tài)下的SOCKET,表示半連接,也即有一方要求close連接,但另外一方告訴對(duì)方,我暫時(shí)還有點(diǎn)數(shù)據(jù)需要傳送給你(ACK信息),稍后再關(guān)閉連接。(主動(dòng)方)

TIME_WAIT: 表示收到了對(duì)方的FIN報(bào)文,并發(fā)送出了ACK報(bào)文,就等2MSL后即可回到CLOSED可用狀態(tài)了。如果FIN_WAIT_1狀態(tài)下,收到了對(duì)方同時(shí)帶FIN標(biāo)志和ACK標(biāo)志的報(bào)文時(shí),可以直接進(jìn)入到TIME_WAIT狀態(tài),而無須經(jīng)過FIN_WAIT_2狀態(tài)。(主動(dòng)方)

CLOSING(比較少見): 這種狀態(tài)比較特殊,實(shí)際情況中應(yīng)該是很少見,屬于一種比較罕見的例外狀態(tài)。正常情況下,當(dāng)你發(fā)送FIN報(bào)文后,按理來說是應(yīng)該先收到(或同時(shí)收到)對(duì)方的 ACK報(bào)文,再收到對(duì)方的FIN報(bào)文。但是CLOSING狀態(tài)表示你發(fā)送FIN報(bào)文后,并沒有收到對(duì)方的ACK報(bào)文,反而卻也收到了對(duì)方的FIN報(bào)文。什么情況下會(huì)出現(xiàn)此種情況呢?其實(shí)細(xì)想一下,也不難得出結(jié)論:那就是如果雙方幾乎在同時(shí)close一個(gè)SOCKET的話,那么就出現(xiàn)了雙方同時(shí)發(fā)送FIN報(bào)文的情況,也即會(huì)出現(xiàn)CLOSING狀態(tài),表示雙方都正在關(guān)閉SOCKET連接。

CLOSE_WAIT: 這種狀態(tài)的含義其實(shí)是表示在等待關(guān)閉。怎么理解呢?當(dāng)對(duì)方close一個(gè)SOCKET后發(fā)送FIN報(bào)文給自己,你系統(tǒng)毫無疑問地會(huì)回應(yīng)一個(gè)ACK報(bào)文給對(duì)方,此時(shí)則進(jìn)入到CLOSE_WAIT狀態(tài)。接下來呢,實(shí)際上你真正需要考慮的事情是查看你是否還有數(shù)據(jù)發(fā)送給對(duì)方,如果沒有的話,那么你也就可以close這個(gè)SOCKET,發(fā)送FIN報(bào)文給對(duì)方,也即關(guān)閉連接。所以你在CLOSE_WAIT狀態(tài)下,需要完成的事情是等待你去關(guān)閉連接。(被動(dòng)方)

LAST_ACK: 這個(gè)狀態(tài)還是比較容易好理解的,它是被動(dòng)關(guān)閉一方在發(fā)送FIN報(bào)文后,最后等待對(duì)方的ACK報(bào)文。當(dāng)收到ACK報(bào)文后,也即可以進(jìn)入到CLOSED可用狀態(tài)了。(被動(dòng)方)

CLOSED: 表示連接中斷。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本篇結(jié)構(gòu): 前言 TCP報(bào)文首部格式 三次握手 四次揮手 wireshark抓包三次握手 wireshark抓包四...
    w1992wishes閱讀 8,453評(píng)論 0 57
  • 最近在惡補(bǔ)計(jì)算機(jī)網(wǎng)絡(luò)方面的知識(shí),之前對(duì)于TCP的三次握手和四次分手也是模模糊糊,對(duì)于其中的細(xì)節(jié)更是渾然不知,最近看...
    微醺歲月閱讀 9,667評(píng)論 4 128
  • 男人四十一朵花,時(shí)光飛逝刷刷刷。 往事如煙嘩嘩嘩,老大不小莫再耍。 趕緊快把今日抓,三畝薄土種點(diǎn)瓜。 不是王婆我自...
    長(zhǎng)風(fēng)孤嘯閱讀 355評(píng)論 0 0
  • 昨天是墨村主創(chuàng)丟子和檀燒的大喜之日。微博上祝福一片。 這已經(jīng)是古風(fēng)圈第二對(duì)有名的夫妻檔了。上一對(duì)兒阿杰和翼哥的千金...
    連看客都不是閱讀 1,174評(píng)論 6 10
  • 每到周五心情就會(huì)格外的愉悅,周末對(duì)于忙碌一周的我們來說是難得放松修養(yǎng)的日子! 原本周五晚上早點(diǎn)發(fā)班車可以早點(diǎn)回...
    救贖的公牛閱讀 165評(píng)論 0 0

友情鏈接更多精彩內(nèi)容