重要的幾個概念:
-
SYN
: 發(fā)起新的連接 -
ACK
:確認(rèn)序號有效。 seq序號
-
ack序號
: 只有在ACK=1
的情況下有效肖揣,ack序號 = seq序號+ 1 -
FIN
: 釋放一個連接
三次握手協(xié)議
-
客戶端
發(fā)起SYN=1民假,表示需要新建連接,并且?guī)想S機數(shù)seq=x (Client進入SYN_SENT狀態(tài)) -
服務(wù)端
在收到數(shù)據(jù)包之后龙优,根據(jù)SYN=1知道客戶端
是希望建立新的連接羊异,所以服務(wù)端發(fā)送的信息里面SYN
和ACK
都置為1,并且對客戶端上傳上的seq序號=x
+1==>ack=x+1
,并且?guī)献约荷傻碾S機數(shù)seq=y
(Server進入SYN_RCVD) - 客戶端收到服務(wù)端返回的包后,
確認(rèn)ACK是否等于1
并且確認(rèn)ack是否等于x+1
,如果正確則將ACK=1,ack=y+1
(Client和Server進入ESTABLISHED) - 完成三次握手彤断,正確的連接建立成功野舶,服務(wù)端和客戶端可以開始傳輸數(shù)據(jù)了
為什么要用三次握手,而不是兩次握手呢宰衙?平道?
如果客戶端發(fā)送第一次握手之后,因為網(wǎng)絡(luò)不好供炼,消息在網(wǎng)絡(luò)中走的有點久一屋,等到消息到達服務(wù)端的時候窘疮,消息已經(jīng)失效了(但是這個時候服務(wù)端并不知曉),假設(shè)沒有第三次握手冀墨,服務(wù)端在收到消息做出響應(yīng)之后闸衫,就建立起新的連接,一直等待客戶端發(fā)送消息诽嘉,但是客戶端已經(jīng)認(rèn)為失效了楚堤。這樣就會導(dǎo)致服務(wù)端的資源被白白浪費。采用三次握手就是為了防止這種情況的發(fā)生含懊,server會因為收不到確認(rèn)的報文身冬,就知道client并沒有建立連接。這就是三次握手的作用岔乔。
SYN攻擊:
在三次握手過程中酥筝,Server發(fā)送SYN-ACK之后,收到Client的ACK之前的TCP連接稱為半連接(half-open connect)雏门,此時Server處于SYN_RCVD狀態(tài)嘿歌,當(dāng)收到ACK后芍躏,Server轉(zhuǎn)入ESTABLISHED狀態(tài)寞秃。SYN攻擊就是Client在短時間內(nèi)偽造大量不存在的IP地址,并向Server不斷地發(fā)送SYN包捌锭,Server回復(fù)確認(rèn)包募闲,并等待Client的確認(rèn)步脓,由于源地址是不存在的,因此浩螺,Server需要不斷重發(fā)直至超時靴患,這些偽造的SYN包將產(chǎn)時間占用未連接隊列,導(dǎo)致正常的SYN請求因為隊列滿而被丟棄要出,從而引起網(wǎng)絡(luò)堵塞甚至系統(tǒng)癱瘓鸳君。SYN攻擊時一種典型的DDOS攻擊,檢測SYN攻擊的方式非常簡單患蹂,即當(dāng)Server上有大量半連接狀態(tài)且源IP地址是隨機的或颊,則可以斷定遭到SYN攻擊了,使用如下命令可以讓之現(xiàn)行:#netstat -nap | grep SYN_RECV
四次揮手
-
客戶端
發(fā)送FIN=1
標(biāo)識需要釋放連接传于,并且?guī)献约旱碾S機數(shù)seq=u -
服務(wù)端
接收到FIN
后知道客戶端要釋放連接囱挑,做出響應(yīng)ACK=1
,并將ack=u+1
,最后帶上自己的隨機數(shù) seq=v -
服務(wù)端
向客戶端發(fā)送FIN
,用來關(guān)閉服務(wù)端
到客戶端
的數(shù)據(jù)傳輸,這里用到的ack也是=u+1
-
客戶端
收到FIN
后格了,進入TIME_WAIT狀態(tài)看铆,并對FIN的做出應(yīng)答 -
服務(wù)端
收到應(yīng)答后,進行CLOSE狀態(tài)
為什么建立連接是三次握手盛末,斷開連接確實四次揮手呢弹惦?
因為關(guān)閉連接時,A向B發(fā)送FIN否淤,僅僅表示A不再發(fā)送數(shù)據(jù)了,但是還是可以接收數(shù)據(jù)棠隐,此時B也未必已經(jīng)把所有數(shù)據(jù)都發(fā)送給A了石抡,所以B可以立即發(fā)送FIN做響應(yīng)關(guān)閉,也可以接著把未發(fā)完的數(shù)據(jù)發(fā)完了助泽,在發(fā)送FIN啰扛。
為什么客戶端會在發(fā)送完最后一個ACK后,還要等待2MSL.
因為客戶端返回的ACK可能在網(wǎng)絡(luò)傳輸中丟失嗡贺,服務(wù)端會超時重傳FIN隐解,客戶端就能在這2MSL的時間內(nèi)接收到這個FIN,再次做出ACK诫睬。