TCP的連接和關(guān)閉

由問題驅(qū)動几缭,看一下TCP連接的本質(zhì)吧慰技。

tcp報文頭.png

1. TCP如何保證消息的有序和不丟包贵少?

Sequence Number就是SYN——包的序號,用來解決網(wǎng)絡(luò)包亂序(reordering)問題铆惑。
Acknowledgement Number就是ACK——用于確認(rèn)收到范嘱,用來解決不丟包的問題。

2. 三次握手的目的员魏?

為了建立可靠的數(shù)據(jù)傳輸丑蛤,TCP通信雙方相互告知初始化序列號(ISN),并確定對方已經(jīng)收到ISN的(使用ACK機(jī)制)撕阎。

3. 三次握手的過程受裹?

  1. 客戶端發(fā)送一個SYN段,并指明客戶端的初始序列號闻书,即ISN(c).
  2. 服務(wù)端發(fā)送自己的SYN段作為應(yīng)答名斟,同樣指明自己的ISN(s)脑慧。為了確認(rèn)客戶端的SYN魄眉,將ISN(c)+1作為ACK數(shù)值。這樣闷袒,每發(fā)送一個SYN坑律,序列號就會加1. 如果有丟失的情況,則會重傳囊骤。
  3. 為了確認(rèn)服務(wù)器端的SYN晃择,客戶端將ISN(s)+1作為返回的ACK數(shù)值。
三次握手的過程.png

4. 為什么不能用兩次握手進(jìn)行連接也物?

三次握手的目的就是為了建立可靠的連接宫屠,TCP通信雙方都必須維護(hù)一個序列號,以標(biāo)識發(fā)送的包哪些是被對方收到的滑蚯。三次握手的過程中通信雙方要相互告知初始化序列號浪蹂,并確定對方已經(jīng)收到抵栈。

如果只是兩次握手,至多只有連接發(fā)起方的初始化序列號(ISN)能夠被確認(rèn)坤次,另一方的序列化得不到確認(rèn)古劲。

三次握手.png

5. 為什么建立連接是三次握手,而關(guān)閉連接卻是四次揮手呢缰猴?

四次揮手.png

四次揮手過程:

  1. 主機(jī)A發(fā)送FIN后产艾,進(jìn)入終止等待狀態(tài),服務(wù)器B收到主機(jī)A連接的釋放報文滑绒,就立即給主機(jī)A發(fā)送ACK闷堡。然后服務(wù)器B就進(jìn)入了close-wait狀態(tài)。

  2. 并且服務(wù)器B再次發(fā)送FIN通知主機(jī)A關(guān)閉連接疑故,服務(wù)器B進(jìn)入最后確定狀態(tài)缚窿。

  3. 主機(jī)A收到服務(wù)器BFIN請求后,會發(fā)送一個ACK告訴服務(wù)器B收到焰扳,于是客戶端和服務(wù)器都關(guān)閉了倦零。

FIN —— 該報文段的發(fā)送方已經(jīng)結(jié)束向?qū)Ψ桨l(fā)送數(shù)據(jù)。

這是因為服務(wù)端在LISTEN狀態(tài)下吨悍,收到建立連接請求的SYN報文后扫茅,把ACK和SYN放在一個報文里發(fā)送給客戶端。而關(guān)閉連接時育瓜,當(dāng)收到對方的FIN報文時葫隙,僅僅表示對方不再發(fā)送數(shù)據(jù)了但是還能接收數(shù)據(jù),己方是否現(xiàn)在關(guān)閉發(fā)送數(shù)據(jù)通道躏仇,需要上層應(yīng)用來決定恋脚,因此,己方ACK和FIN一般都會分開發(fā)送焰手。

一句話總結(jié):是否關(guān)閉通道糟描,是上層應(yīng)用決定的的,TCP無權(quán)將FIN和ACK一同發(fā)送书妻。

6. 三次握手建立連接時SYN超時船响?

server端接到了clien發(fā)的SYN后回了SYN-ACK后client掉線了,server端沒有收到client回來的ACK躲履,那么见间,這個連接處于一個中間狀態(tài),即沒成功工猜,也沒失敗米诉。于是,server端如果在一定時間內(nèi)沒有收到的TCP會重發(fā)SYN-ACK篷帅。在Linux下史侣,默認(rèn)重試次數(shù)為5次汗销,重試的間隔時間從1s開始每次都翻售,5次的重試時間間隔為1s, 2s, 4s, 8s, 16s抵窒,總共31s弛针,第5次發(fā)出后還要等32s都知道第5次也超時了,所以李皇,總共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 2^6 -1 = 63s削茁,TCP才會把斷開這個連接。

一句話總結(jié):服務(wù)器未收到客戶端的確定ACK掉房,便會一直重試茧跋。

7. 關(guān)于SYN攻擊?

我們說過卓囚,在建立連接時瘾杭,server未收到client端的ACK通知,便開始了長達(dá)63s的重試機(jī)制哪亿。

7.1 什么叫做SYN Flood:
一些惡意的人就為此制造了SYN Flood攻擊——給服務(wù)器發(fā)了一個SYN后粥烁,就下線了,于是服務(wù)器需要默認(rèn)等63s才會斷開連接蝇棉,這樣讨阻,攻擊者就可以把服務(wù)器的syn連接的隊列耗盡,讓正常的連接請求不能處理篡殷。

7.2 妥協(xié)版的TCP協(xié)議:synccookies:
于是钝吮,Linux下給了一個叫tcp_syncookies的參數(shù)來應(yīng)對這個事——當(dāng)SYN隊列滿了后,TCP會通過源地址端口板辽、目標(biāo)地址端口和時間戳打造出一個特別的Sequence Number發(fā)回去(又叫cookie)奇瘦,如果是攻擊者則不會有響應(yīng),如果是正常連接劲弦,則會把這個 SYN Cookie發(fā)回來耳标,然后服務(wù)端可以通過cookie建連接(即使你不在SYN隊列中)。請注意瓶您,請先千萬別用tcp_syncookies來處理正常的大負(fù)載的連接的情況麻捻。因為纲仍,synccookies是妥協(xié)版的TCP協(xié)議呀袱,并不嚴(yán)謹(jǐn)。

7.3 對于正常的請求郑叠,你應(yīng)該調(diào)整三個TCP參數(shù)可供你選擇:
第一個是:tcp_synack_retries 可以用他來減少重試次數(shù)夜赵;
第二個是:tcp_max_syn_backlog,可以增大SYN連接數(shù)乡革;
第三個是:tcp_abort_on_overflow 處理不過來干脆就直接拒絕連接了寇僧。

8. 如何設(shè)置ISN的值摊腋?

三次握手的一個重要功能是客戶端和服務(wù)端交換ISN(Initial Sequence Number), 以便讓對方知道接下來接收數(shù)據(jù)的時候如何按序列號組裝數(shù)據(jù)。
如果ISN是固定的嘁傀,攻擊者很容易猜出后續(xù)的確認(rèn)號兴蒸。
ISN = M + F(localhost, localport, remotehost, remoteport)
M是一個計時器,每隔4微秒加1细办。 F是一個Hash算法橙凳,根據(jù)源IP、目的IP笑撞、源端口岛啸、目的端口生成一個隨機(jī)數(shù)值。要保證hash算法不能被外部輕易推算得出茴肥。

一句話總結(jié):ISN不能是固定不變的坚踩,一般是計時器(每4微妙+1)+隨機(jī)hash值設(shè)置的,防止被攻擊瓤狐。

9瞬铸、序列號回繞

因為ISN是隨機(jī)的,所以序列號容易就會超過2^31-1. 而tcp對于丟包和亂序等問題的判斷都是依賴于序列號大小比較的础锐。此時就出現(xiàn)了所謂的tcp序列號回繞(sequence wraparound)問題赴捞。怎么解決?

內(nèi)核代碼:

/** The next routines deal with comparing 32 bit unsigned ints
 * and worry about wraparound (automatic with unsigned arithmetic).*/
static inline int before(__u32 seq1, __u32 seq2){
    return (__s32)(seq1-seq2) < 0;}

序列號發(fā)生回繞后郁稍,序列號變小赦政,相減之后,把結(jié)果變成有符號數(shù)了耀怜,因此結(jié)果成了負(fù)數(shù)恢着。

假設(shè)seq1=255, seq2=1(發(fā)生了回繞)财破。
seq1 = 1111 1111 seq2 = 0000 0001
我們希望比較結(jié)果是
 seq1 - seq2=
 1111 1111
-0000 0001
————————————
 1111 1110

由于我們將結(jié)果轉(zhuǎn)化成了有符號數(shù)掰派,由于最高位是1,因此結(jié)果是一個負(fù)數(shù)左痢,負(fù)數(shù)的絕對值為
 0000 0001 + 1 = 0000 0010 = 2
因此seq1 - seq2 < 0

文章參考:

TCP 為什么三次握手而不是兩次握手(正解版)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末俊性,一起剝皮案震驚了整個濱河市略步,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌定页,老刑警劉巖趟薄,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異典徊,居然都是意外死亡杭煎,警方通過查閱死者的電腦和手機(jī)恩够,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來羡铲,“玉大人蜂桶,你說我怎么就攤上這事∫睬校” “怎么了屎飘?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長贾费。 經(jīng)常有香客問我钦购,道長,這世上最難降的妖魔是什么褂萧? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任押桃,我火速辦了婚禮,結(jié)果婚禮上导犹,老公的妹妹穿的比我還像新娘唱凯。我一直安慰自己,他們只是感情好谎痢,可當(dāng)我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布磕昼。 她就那樣靜靜地躺著,像睡著了一般节猿。 火紅的嫁衣襯著肌膚如雪票从。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天滨嘱,我揣著相機(jī)與錄音峰鄙,去河邊找鬼。 笑死太雨,一個胖子當(dāng)著我的面吹牛吟榴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播囊扳,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼吩翻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了锥咸?” 一聲冷哼從身側(cè)響起狭瞎,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎她君,沒想到半個月后脚作,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡缔刹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年球涛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片校镐。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡亿扁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鸟廓,到底是詐尸還是另有隱情从祝,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布引谜,位于F島的核電站牍陌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏员咽。R本人自食惡果不足惜毒涧,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贝室。 院中可真熱鬧契讲,春花似錦、人聲如沸滑频。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽峡迷。三九已至银伟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绘搞,已是汗流浹背枣申。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留看杭,地道東北人忠藤。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像楼雹,于是被迫代替她去往敵國和親模孩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,044評論 2 355