更好閱讀體驗:《理解 TCP 和 UDP》— By Gitbook
TCP 的整個交流過程可以總結(jié)為:先建立連接,然后傳輸數(shù)據(jù),最后釋放鏈接。
三次握手,建立連接
TCP 連接建立要解決的首要問題就是:要使每一方能夠確知對方的存在姨涡。
三次握手就像,在一個黑暗的森林吧慢,你知道前方十點鐘方向好像有人涛漂。
你喊了一句:Hello?I'am JerryC检诗,Who are you匈仗?
對面回了一句:Hi! I'am David, and nice to meet you!
然后你回了一句:Nice to meet you too!
......(自此,你們才算真正認識了雙方逢慌,開始了后面省略3000字的談話)
所以說悠轩,兩個人需要交朋友(兩個端點需要建立連接),至少需要三次的通話(握手)
其實攻泼,網(wǎng)絡(luò)上的傳輸是沒有連接的火架,TCP 也是一樣的。
而 TCP 所謂的「連接」忙菠,其實只不過是在通信的雙方維護一個「連接狀態(tài)」何鸡,讓它看上去好像有連接一樣。
連接建立過程
TCP 連接的建立采用客戶服務(wù)器方式只搁,主動發(fā)起連接建立的一方叫客戶端(Client)音比,被動等待連接建立的一方叫服務(wù)器(Server)。
最初的時候氢惋,兩端都處于 CLOSED 的狀態(tài),然后服務(wù)器打開了 TCP 服務(wù)稽犁,進入 LISTEN 狀態(tài)焰望,監(jiān)聽特定端口,等待客戶端的 TCP 請求已亥。
第一次握手:
客戶端主動打開連接熊赖,發(fā)送 TCP 報文,進行第一次握手虑椎,然后進入 SYN_SEND 狀態(tài)震鹉,等待服務(wù)器發(fā)回確認報文俱笛。
這時首部的同步位 SYN = 1,同時初始化一個序號 Sequence Number = J传趾。
TCP 規(guī)定迎膜,SYN 報文段不能攜帶數(shù)據(jù),但會消耗一個序號浆兰。
第二次握手:
服務(wù)器收到了 SYN 報文磕仅,如果同意建立連接,則向客戶端發(fā)送一個確認報文簸呈,然后服務(wù)器進入 SYN_RCVD 狀態(tài)榕订。
這時首部的 SYN = 1,ACK = 1蜕便,而確認號 Acknowledgemt Number = J + 1劫恒,同時也為自己初始化一個序號 Sequence Number = K。
這個報文同樣不攜帶數(shù)據(jù)轿腺。
第三次握手:
客戶端收到了服務(wù)器發(fā)過來的確認報文两嘴,還要向服務(wù)器給出確認,然后進入 ESTABLISHED 狀態(tài)吃溅。
這時首部的 SYN 不再置為 1溶诞,而 ACK = 1,確認號 Acknowledgemt Number = K + 1决侈,序號 Sequence Number = J + 1螺垢。
第三次握手,一般會攜帶真正需要傳輸?shù)臄?shù)據(jù)赖歌,當服務(wù)器收到該數(shù)據(jù)報文的時候枉圃,就會同樣進入 ESTABLISHED 狀態(tài)。
此時庐冯,TCP 連接已經(jīng)建立孽亲。
對于建立連接的三次握手,主要目的是初始化序號 Sequence Number展父,并且通信的雙方都需要告知對方自己的初始化序號返劲,所以這個過程也叫 SYN。
這個序號要作為以后的數(shù)據(jù)通信的序號栖茉,以保證應(yīng)用層接收到的數(shù)據(jù)不會因為網(wǎng)絡(luò)上的傳輸問題而亂序篮绿,因為TCP 會用這個序號來拼接數(shù)據(jù)。
利用連接設(shè)計缺陷實施 TCP Flood 攻擊
知道了 TCP 建立一個連接吕漂,需要進行三次握手亲配。
但如果你開始思考「三次握手的必要性」的時候,就會知道,其實網(wǎng)絡(luò)是很復(fù)雜的吼虎,一個信息在途中丟失的可能性是有的犬钢。
如果數(shù)據(jù)丟失了,那么思灰,就需要重新發(fā)送玷犹,這時候就要知道數(shù)據(jù)是否真的送達了。
這就是三次握手的必要性官辈。
但是再向深一層思考箱舞,你給我發(fā)信息,我收到了拳亿,我回復(fù)晴股,因為我是君子。
如果是小人肺魁,你給我發(fā)信息电湘,我就算收到了,我也不回復(fù)鹅经,你就一直等我著我的回復(fù)寂呛。
那么很多小人都這樣做,你就要一直記住你在等待著小人1號瘾晃、小人2號贷痪、小人3號......直到你的腦容量爆棚,燒壞腦袋蹦误。
黑客就是利用這樣的設(shè)計缺陷劫拢,實施 TCP Flood 攻擊,屬于 DDOS 攻擊的一種强胰。
想了解更多 SYN Flood 攻擊請看:SYN flood - wiki
四次揮手舱沧,釋放連接
TCP 有一個特別的概念叫做半關(guān)閉,這個概念是說偶洋,TCP 的連接是全雙工(可以同時發(fā)送和接收)的連接熟吏,因此在關(guān)閉連接的時候,必須關(guān)閉傳送和接收兩個方向上的連接玄窝。
客戶端給服務(wù)器發(fā)送一個攜帶 FIN 的 TCP 結(jié)束報文段牵寺,然后服務(wù)器返回給客戶端一個 確認報文段,同時發(fā)送一個 結(jié)束報文段恩脂,當客戶端回復(fù)一個 確認報文段 之后缸剪,連接就結(jié)束了。
釋放連接過程
在結(jié)束之前东亦,通信雙方都是處于 ESTABLISHED 狀態(tài),然后其中一方主動斷開連接。
下面假如客戶端先主動斷開連接典阵。
第一次揮手:
客戶端向服務(wù)器發(fā)送結(jié)束報文段奋渔,然后進入 FIN_WAIT_1 狀態(tài)。
此報文段 FIN = 1壮啊, Sequence Number = M嫉鲸。
第二次揮手:
服務(wù)端收到客戶端的結(jié)束報文段,然后發(fā)送確認報文段歹啼,進入 CLOSE_WAIT 狀態(tài)玄渗。
此報文段 ACK = 1, Sequence Number = M + 1狸眼。
客戶端收到該報文藤树,會進入 FIN_WAIT_2 狀態(tài)。
第三次揮手:
同時服務(wù)端向客戶端發(fā)送結(jié)束報文段拓萌,然后進入 LAST_ACK 狀態(tài)岁钓。
此報文段 FIN = 1,Sequence Number = N微王。
第四次揮手:
客戶端收到服務(wù)端的結(jié)束報文段屡限,然后發(fā)送確認報文段,進入 TIME_WAIT 狀態(tài)炕倘,經(jīng)過 2MSL 之后钧大,自動進入 CLOSED 狀態(tài)。
此報文段 ACK = 1, Sequence Number = N + 1罩旋。
服務(wù)端收到該報文之后啊央,進入 CLOSED 狀態(tài)。
關(guān)于 TIME_WAIT 過渡到 CLOSED 狀態(tài)說明:
從 TIME_WAIT 進入 CLOSED 需要經(jīng)過 2MSL瘸恼,其中 MSL 就叫做 最長報文段壽命(Maxinum Segment Lifetime)劣挫,根據(jù) RFC 793 建議該值這是為 2 分鐘,也就是說需要經(jīng)過 4 分鐘东帅,才進入 CLOSED 狀態(tài)压固。