簡述
Tcp的三次握手與四次揮手比較重要须喂,在網(wǎng)絡(luò)基礎(chǔ)中權(quán)重較大且特別愛問言蛇。下面我們就來簡單的扒一扒孵户。
TCP的三次握手
如上圖所示,在三次握手連接當(dāng)中憾股,我們可以清晰的看到核心報(bào)文交換內(nèi)容以及狀態(tài)轉(zhuǎn)換鹿蜀。
在TCP/IP協(xié)議中,TCP協(xié)議提供可靠的連接服務(wù)服球,采用三次握手建立一個(gè)連接
(1) 第一次握手:建立連接時(shí)茴恰,客戶端A發(fā)送SYN包(Seq Num=j)到服務(wù)器,并進(jìn)入SYN_SENT狀態(tài)斩熊,等待服務(wù)器確認(rèn)往枣。
(2) 第二次握手:服務(wù)器收到SYN包,必須確認(rèn)客戶端(Ack Num=j+1)粉渠,同時(shí)自己也發(fā)送一個(gè)SYN包(SYN=k)分冈,即SYN+ACK包,此時(shí)服務(wù)器B進(jìn)入SYN_RECV狀態(tài)霸株。
(3) 第三次握手:客戶端A收到服務(wù)器B的SYN+ACK包雕沉,向服務(wù)器B發(fā)送確認(rèn)包ACK(ACK=k+1),此包發(fā)送完畢去件,客戶端A和服務(wù)器B進(jìn)入ESTABLISHED狀態(tài)坡椒,完成三次握手。
需要關(guān)注的問題
三次握手建立連接時(shí)尤溜,發(fā)送方再次發(fā)送確認(rèn)的必要性倔叼?
主要是為了防止已失效的連接請求報(bào)文段突然又傳到了B,因而產(chǎn)生錯(cuò)誤。假定出現(xiàn)一種異常情況宫莱,即A發(fā)出的第一個(gè)連接請求報(bào)文段并沒有丟失缀雳,而是在某些網(wǎng)絡(luò)結(jié) 點(diǎn)長時(shí)間滯留了,一直延遲到連接釋放以后的某個(gè)時(shí)間才到達(dá)B梢睛,本來這是一個(gè)早已失效的報(bào)文段肥印。但B收到此失效的連接請求報(bào)文段后识椰,就誤認(rèn)為是A又發(fā)出一次 新的連接請求,于是就向A發(fā)出確認(rèn)報(bào)文段深碱,同意建立連接腹鹉。假定不采用三次握手,那么只要B發(fā)出確認(rèn)敷硅,新的連接就建立了功咒,這樣一直等待A發(fā)來數(shù)據(jù),B的許多資源就這樣白白浪費(fèi)了绞蹦。
關(guān)于SYN攻擊
問題描述
在三次握手過程中力奋,服務(wù)器發(fā)送SYN-ACK之后,收到客戶端的ACK之前的TCP連接稱為半連接(half-open connect).此時(shí)服務(wù)器處于Syn_RECV狀態(tài).當(dāng)收到ACK后幽七,服務(wù)器轉(zhuǎn)入ESTABLISHED狀態(tài).
Syn攻擊就是 攻擊客戶端 在短時(shí)間內(nèi)偽造大量不存在的IP地址景殷,向服務(wù)器不斷地發(fā)送syn包,服務(wù)器回復(fù)確認(rèn)包澡屡,并等待客戶的確認(rèn)猿挚,由于源地址是不存在的,服務(wù)器需要不斷的重發(fā)直 至超時(shí)驶鹉,這些偽造的SYN包將長時(shí)間占用未連接隊(duì)列绩蜻,正常的SYN請求被丟棄,目標(biāo)系統(tǒng)運(yùn)行緩慢室埋,嚴(yán)重者引起網(wǎng)絡(luò)堵塞甚至系統(tǒng)癱瘓办绝。
檢查方法
Syn攻擊是一個(gè)典型的DDOS攻擊。檢測SYN攻擊非常的方便姚淆,當(dāng)你在服務(wù)器上看到大量的半連接狀態(tài)時(shí)八秃,特別是源IP地址是隨機(jī)的,基本上可以斷定這是一次SYN攻擊.在Linux下可以如下命令檢測是否被Syn攻擊
netstat -n -p TCP | grep SYN_RECV //檢查所有半連接的TCP協(xié)議
防范方法
一般較新的TCP/IP協(xié)議棧都對這一過程進(jìn)行修正來防范Syn攻擊肉盹,修改tcp協(xié)議實(shí)現(xiàn)昔驱。主要方法有SynAttackProtect保護(hù)機(jī)制、SYN cookies技術(shù)上忍、增加最大半連接和縮短超時(shí)時(shí)間等.
但是不能完全防范syn攻擊骤肛。
為什么不能用兩次握手進(jìn)行連接?
我們知道窍蓝,3次握手完成兩個(gè)重要的功能腋颠,既要雙方做好發(fā)送數(shù)據(jù)的準(zhǔn)備工作(雙方都知道彼此已準(zhǔn)備好),也要允許雙方就初始序列號進(jìn)行協(xié)商吓笙,這個(gè)序列號在握手過程中被發(fā)送和確認(rèn)淑玫。
現(xiàn)在把三次握手改成僅需要兩次握手,死鎖是可能發(fā)生的。作為例子絮蒿,考慮計(jì)算機(jī)S和C之間的通信尊搬,假定C給S發(fā)送一個(gè)連接請求分組,S收到了這個(gè)分組土涝,并發(fā) 送了確認(rèn)應(yīng)答分組佛寿。按照兩次握手的協(xié)定,S認(rèn)為連接已經(jīng)成功地建立了但壮,可以開始發(fā)送數(shù)據(jù)分組冀泻。可是蜡饵,C在S的應(yīng)答分組在傳輸中被丟失的情況下弹渔,將不知道S 是否已準(zhǔn)備好,不知道S建立什么樣的序列號溯祸,C甚至懷疑S是否收到自己的連接請求分組肢专。在這種情況下,C認(rèn)為連接還未建立成功您没,將忽略S發(fā)來的任何數(shù)據(jù)分 組,只等待連接確認(rèn)應(yīng)答分組胆绊。而S在發(fā)出的分組超時(shí)后氨鹏,重復(fù)發(fā)送同樣的分組。這樣就形成了死鎖压状。
TCP的四次揮手
我們先來看張圖
由于TCP連接是全雙工的仆抵,因此每個(gè)方向都必須單獨(dú)進(jìn)行關(guān)閉。這個(gè)原則是當(dāng)一方完成它的數(shù)據(jù)發(fā)送任務(wù)后就能發(fā)送一個(gè)FIN來終止這個(gè)方向的連接种冬。收到一個(gè) FIN只意味著這一方向上沒有數(shù)據(jù)流動(dòng)镣丑,一個(gè)TCP連接在收到一個(gè)FIN后仍能發(fā)送數(shù)據(jù)。首先進(jìn)行關(guān)閉的一方將執(zhí)行主動(dòng)關(guān)閉娱两,而另一方執(zhí)行被動(dòng)關(guān)閉莺匠。
(1)客戶端A發(fā)送一個(gè)FIN,用來關(guān)閉客戶A到服務(wù)器B的數(shù)據(jù)傳送,此時(shí)客戶端A由ESTABLISHED狀態(tài)進(jìn)入FIN_WAIT_1狀態(tài)
(2)服務(wù)器B收到這個(gè)FIN十兢,它發(fā)回一個(gè)ACK趣竣,確認(rèn)序號為收到的序號加1。服務(wù)器端由ESTABLISHED進(jìn)入CLOSE_WAIT狀態(tài)
(3)服務(wù)器B關(guān)閉與客戶端A的連接旱物,發(fā)送一個(gè)FIN給客戶端A遥缕。服務(wù)器端由CLOSE_WAIT轉(zhuǎn)為LAST_ACK狀態(tài)
(4)客戶端A發(fā)回ACK報(bào)文確認(rèn),并將確認(rèn)序號設(shè)置為收到序號加1宵呛〉ハ唬客戶端進(jìn)入TIME_WAIT狀態(tài)
關(guān)注問題
為什么建立連接協(xié)議是三次握手,而關(guān)閉連接卻是四次握手呢?
這是因?yàn)榉?wù)端的LISTEN狀態(tài)下的SOCKET當(dāng)收到SYN報(bào)文的連接請求后户秤,它可以把ACK和SYN(ACK起應(yīng)答作用码秉,而SYN起同步作用)放在一個(gè)報(bào)文里來發(fā)送。但關(guān)閉連接時(shí)虎忌,當(dāng)收到對方的FIN報(bào)文通知時(shí)泡徙,它僅僅表示對方?jīng)]有數(shù)據(jù)發(fā)送給你了;但未必你所有的數(shù)據(jù)都全部發(fā)送給對方了膜蠢,所以你可能未必會(huì)馬上會(huì)關(guān)閉SOCKET,也即你可能還需要發(fā)送一些數(shù)據(jù)給對方之后堪藐,再發(fā)送FIN報(bào)文給對方來表示你同意現(xiàn)在可以關(guān)閉連接了,所以它這里的ACK報(bào)文和FIN報(bào)文多數(shù)情況下都是分開發(fā)送的挑围。
為什么TIME_WAIT狀態(tài)還需要等2MSL后才能返回到CLOSED狀態(tài)礁竞?
(1)可靠的實(shí)現(xiàn)TCP全雙工鏈接的終止。
這是因?yàn)殡m然雙方都同意關(guān)閉連接了杉辙,而且握手的4個(gè)報(bào)文也都協(xié)調(diào)和發(fā)送完畢模捂,按理可以直接回到CLOSED狀態(tài)(就好比從SYN_SEND狀態(tài)到ESTABLISH狀態(tài)那樣);但是因?yàn)槲覀儽仨氁傧刖W(wǎng)絡(luò)是不可靠的蜘矢,你無法保證你最后發(fā)送的ACK報(bào)文會(huì)一定被對方收到狂男,因此對方處于LAST_ACK狀態(tài)下的SOCKET可能會(huì)因?yàn)槌瑫r(shí)未收到ACK報(bào)文,而重發(fā)FIN報(bào)文品腹,所以這個(gè)TIME_WAIT狀態(tài)的作用就是用來重發(fā)可能丟失的ACK報(bào)文岖食。
(2)允許老的重復(fù)的分節(jié)在網(wǎng)絡(luò)中消逝。
假設(shè)在12.106.32.254的1500端口和206.168.1.112.219的21端口之間有一個(gè)TCP連接舞吭。我們關(guān)閉這個(gè)鏈接泡垃,過一段時(shí)間后在 相同的IP地址和端口建立另一個(gè)連接。后一個(gè)鏈接成為前一個(gè)的化身羡鸥。因?yàn)樗鼈兊腎P地址和端口號都相同蔑穴。TCP必須防止來自某一個(gè)連接的老的重復(fù)分組在連 接已經(jīng)終止后再現(xiàn),從而被誤解成屬于同一鏈接的某一個(gè)某一個(gè)新的化身惧浴。為做到這一點(diǎn)存和,TCP將不給處于TIME_WAIT狀態(tài)的鏈接發(fā)起新的化身。既然 TIME_WAIT狀態(tài)的持續(xù)時(shí)間是MSL的2倍衷旅,這就足以讓某個(gè)方向上的分組最多存活msl秒即被丟棄哑姚,另一個(gè)方向上的應(yīng)答最多存活msl秒也被丟棄。 通過實(shí)施這個(gè)規(guī)則芜茵,我們就能保證每成功建立一個(gè)TCP連接時(shí)叙量。來自該鏈接先前化身的重復(fù)分組都已經(jīng)在網(wǎng)絡(luò)中消逝了。