TCP簡(jiǎn)述

前言

  • 首先,我們需要知道,我們程序的數(shù)據(jù)首先會(huì)打到TCP的Segment中,然后TCP的Segment會(huì)打到IP的Packet中,然后再打到以太網(wǎng)Ethernet的Frame中,傳到對(duì)端后,各個(gè)層解析自己的協(xié)議,然后把數(shù)據(jù)交給更高層的協(xié)議處理。
  • 網(wǎng)絡(luò)上的傳輸是沒(méi)有連接的,包括TCP也是一樣的。而TCP所謂的“連接”,其實(shí)只不過(guò)是在通訊的雙方維護(hù)一個(gè)“連接狀態(tài)”,讓它看上去好像有連接一樣。所以,TCP的狀態(tài)變換是非常重要的。

TCP的特性

  • TCP提供一種面向連接的、可靠的字節(jié)流服務(wù)
  • 在一個(gè)TCP連接中,僅有兩方進(jìn)行彼此通信。廣播和多播不能用于TCP
  • TCP使用校驗(yàn)和,確認(rèn)和重傳機(jī)制來(lái)保證可靠傳輸
  • TCP使用累積確認(rèn)
  • TCP使用滑動(dòng)窗口機(jī)制來(lái)實(shí)現(xiàn)流量控制,通過(guò)動(dòng)態(tài)改變窗口的大小進(jìn)行擁塞控制

TCP頭格式

Paste_Image.png
  • TCP的包是沒(méi)有IP地址的,那是IP層上的事。但是有源端口和目標(biāo)端口。
  • 一個(gè)TCP連接需要四個(gè)元組來(lái)表示是同一個(gè)連接(src_ip, src_port, dst_ip, dst_port)準(zhǔn)確說(shuō)是五元組,還有一個(gè)是協(xié)議。但因?yàn)檫@里只是說(shuō)TCP協(xié)議,所以,這里我只說(shuō)四元組。
  • 注意上圖中的四個(gè)非常重要的東西:
  • Sequence Number是包的序號(hào),用來(lái)解決網(wǎng)絡(luò)包亂序(reordering)問(wèn)題。
  • Acknowledgement Number就是ACK——用于確認(rèn)收到,用來(lái)解決不丟包的問(wèn)題。
  • Window又叫Advertised-Window,也就是著名的滑動(dòng)窗口(Sliding Window),用于解決流控的。
  • TCP Flag ,也就是包的類型,主要是用于操控TCP的狀態(tài)機(jī)的。

TCP狀態(tài)機(jī)

Paste_Image.png

Paste_Image.png

很多人會(huì)問(wèn),為什么建鏈接要3次握手,斷鏈接需要4次揮手?

  • 對(duì)于建鏈接的3次握手,主要是要初始化Sequence Number 的初始值。通信的雙方要互相通知對(duì)方自己的初始化的Sequence Number(縮寫(xiě)為ISN:Inital Sequence Number)——所以叫SYN,全稱Synchronize Sequence Numbers。也就上圖中的 x 和 y。這個(gè)號(hào)要作為以后的數(shù)據(jù)通信的序號(hào),以保證應(yīng)用層接收到的數(shù)據(jù)不會(huì)因?yàn)榫W(wǎng)絡(luò)上的傳輸?shù)膯?wèn)題而亂序(TCP會(huì)用這個(gè)序號(hào)來(lái)拼接數(shù)據(jù))。
  • 對(duì)于4次揮手,其實(shí)你仔細(xì)看是2次,因?yàn)門(mén)CP是全雙工的,所以,發(fā)送方和接收方都需要Fin和Ack。只不過(guò),有一方是被動(dòng)的,所以看上去就成了所謂的4次揮手。如果兩邊同時(shí)斷連接,那就會(huì)就進(jìn)入到CLOSING狀態(tài),然后到達(dá)TIME_WAIT狀態(tài)。下圖是雙方同時(shí)斷連接的示意圖(你同樣可以對(duì)照著TCP狀態(tài)機(jī)看):


    Paste_Image.png

三次握手與四次揮手###

  • 所謂三次握手(Three-way Handshake),是指建立一個(gè) TCP 連接時(shí),需要客戶端和服務(wù)器總共發(fā)送3個(gè)包。
    三次握手的目的是連接服務(wù)器指定端口,建立 TCP 連接,并同步連接雙方的序列號(hào)和確認(rèn)號(hào),交換 TCP 窗口大小信息。在 socket 編程中,客戶端執(zhí)行 connect() 時(shí)。將觸發(fā)三次握手。
  • 第一次握手(SYN=1, seq=x):

客戶端發(fā)送一個(gè) TCP 的 SYN 標(biāo)志位置1的包,指明客戶端打算連接的服務(wù)器的端口,以及初始序號(hào) X,保存在包頭的序列號(hào)(Sequence Number)字段里。

發(fā)送完畢后,客戶端進(jìn)入 SYN_SEND 狀態(tài)。

  • 第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1):

服務(wù)器發(fā)回確認(rèn)包(ACK)應(yīng)答。即 SYN 標(biāo)志位和 ACK 標(biāo)志位均為1。服務(wù)器端選擇自己 ISN 序列號(hào),放到 Seq 域里,同時(shí)將確認(rèn)序號(hào)(Acknowledgement Number)設(shè)置為客戶的 ISN 加1,即X+1。
發(fā)送完畢后,服務(wù)器端進(jìn)入 SYN_RCVD 狀態(tài)。

  • 第三次握手(ACK=1,ACKnum=y+1)

客戶端再次發(fā)送確認(rèn)包(ACK),SYN 標(biāo)志位為0,ACK 標(biāo)志位為1,并且把服務(wù)器發(fā)來(lái) ACK 的序號(hào)字段+1,放在確定字段中發(fā)送給對(duì)方,并且在數(shù)據(jù)段放寫(xiě)ISN的+1

發(fā)送完畢后,客戶端進(jìn)入 ESTABLISHED 狀態(tài),當(dāng)服務(wù)器端接收到這個(gè)包時(shí),也進(jìn)入 ESTABLISHED 狀態(tài),TCP 握手結(jié)束。

三次握手的過(guò)程的示意圖如下:

Paste_Image.png
  • TCP的連接的拆除需要發(fā)送四個(gè)包,因此稱為四次揮手(Four-way handshake),也叫做改進(jìn)的三次握手。客戶端或服務(wù)器均可主動(dòng)發(fā)起揮手動(dòng)作,在 socket 編程中,任何一方執(zhí)行 close() 操作即可產(chǎn)生揮手操作。
  • 第一次揮手(FIN=1,seq=x)
    假設(shè)客戶端想要關(guān)閉連接,客戶端發(fā)送一個(gè) FIN 標(biāo)志位置為1的包,表示自己已經(jīng)沒(méi)有數(shù)據(jù)可以發(fā)送了,但是仍然可以接受數(shù)據(jù)。
    發(fā)送完畢后,客戶端進(jìn)入 FIN_WAIT_1 狀態(tài)。
  • 第二次揮手(ACK=1,ACKnum=x+1)
    服務(wù)器端確認(rèn)客戶端的 FIN 包,發(fā)送一個(gè)確認(rèn)包,表明自己接受到了客戶端關(guān)閉連接的請(qǐng)求,但還沒(méi)有準(zhǔn)備好關(guān)閉連接。
    發(fā)送完畢后,服務(wù)器端進(jìn)入 CLOSE_WAIT 狀態(tài),客戶端接收到這個(gè)確認(rèn)包之后,進(jìn)入 FIN_WAIT_2 狀態(tài),等待服務(wù)器端關(guān)閉連接。
  • 第三次揮手(FIN=1,seq=y)
    服務(wù)器端準(zhǔn)備好關(guān)閉連接時(shí),向客戶端發(fā)送結(jié)束連接請(qǐng)求,F(xiàn)IN 置為1。
    發(fā)送完畢后,服務(wù)器端進(jìn)入 LAST_ACK 狀態(tài),等待來(lái)自客戶端的最后一個(gè)ACK。
  • 第四次揮手(ACK=1,ACKnum=y+1)
    客戶端接收到來(lái)自服務(wù)器端的關(guān)閉請(qǐng)求,發(fā)送一個(gè)確認(rèn)包,并進(jìn)入 TIME_WAIT狀態(tài),等待可能出現(xiàn)的要求重傳的 ACK 包。
    .
    服務(wù)器端接收到這個(gè)確認(rèn)包之后,關(guān)閉連接,進(jìn)入 CLOSED 狀態(tài)。
    .
    客戶端等待了某個(gè)固定時(shí)間(兩個(gè)最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,沒(méi)有收到服務(wù)器端的 ACK ,認(rèn)為服務(wù)器端已經(jīng)正常關(guān)閉連接,于是自己也關(guān)閉連接,進(jìn)入 CLOSED 狀態(tài)。

四次揮手的示意圖如下:

Paste_Image.png

SYN攻擊

  • 什么是 SYN 攻擊(SYN Flood)?
    在三次握手過(guò)程中,服務(wù)器發(fā)送 SYN-ACK 之后,收到客戶端的 ACK 之前的 TCP 連接稱為半連接(half-open connect)。此時(shí)服務(wù)器處于 SYN_RCVD 狀態(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包將長(zhǎng)時(shí)間占用未連接隊(duì)列,正常的SYN請(qǐng)求被丟棄,導(dǎo)致目標(biāo)系統(tǒng)運(yùn)行緩慢,嚴(yán)重者會(huì)引起網(wǎng)絡(luò)堵塞甚至系統(tǒng)癱瘓。
    SYN 攻擊是一種典型的 DoS/DDoS 攻擊。
  • 如何檢測(cè) SYN 攻擊?
    檢測(cè) SYN 攻擊非常的方便,當(dāng)你在服務(wù)器上看到大量的半連接狀態(tài)時(shí),特別是源IP地址是隨機(jī)的,基本上可以斷定這是一次SYN攻擊。在 Linux/Unix 上可以使用系統(tǒng)自帶的 netstats 命令來(lái)檢測(cè) SYN 攻擊。

  • 如何防御 SYN 攻擊?
    SYN攻擊不能完全被阻止,除非將TCP協(xié)議重新設(shè)計(jì)。我們所做的是盡可能的減輕SYN攻擊的危害,常見(jiàn)的防御 SYN 攻擊的方法有如下幾種:

  • 縮短超時(shí)(SYN Timeout)時(shí)間

  • 增加最大半連接數(shù)

  • 過(guò)濾網(wǎng)關(guān)防護(hù)

  • SYN cookies技術(shù)

第一步:
客戶端TCP向服務(wù)端TCP發(fā)送一個(gè)特殊的TCP報(bào)文段,不包含應(yīng)用層數(shù)據(jù),但在報(bào)文段首部的SYN標(biāo)志位被設(shè)為1,表示建立連接的報(bào)文段,因此被稱為SYN報(bào)文段。另外,客戶端會(huì)選擇一個(gè)初始序號(hào)client_isn,記錄在此報(bào)文段的序列號(hào)seq中。該報(bào)文段會(huì)封裝在一個(gè)IP數(shù)據(jù)報(bào)中被發(fā)送到服務(wù)器端。這個(gè)報(bào)文段表達(dá)的就是希望建立的信息。
第二步:
一旦包含SYN報(bào)文段的IP數(shù)據(jù)報(bào)到達(dá)服務(wù)器主機(jī),服務(wù)器從IP數(shù)據(jù)報(bào)中提取出TCP SYN報(bào)文段,為該TCP連接分配需要的緩存和變量,并向客戶端發(fā)送表示允許連接的報(bào)文段。這個(gè)允許連接的報(bào)文段也不包含任何應(yīng)用層數(shù)據(jù),但包含三個(gè)重要的信息:首先,SYN被置為1,其次,該報(bào)文段的確認(rèn)號(hào)ack被置為client_isn+1,表示下一個(gè)希望接受的序列號(hào)為client_isn+1,最后,服務(wù)器選擇自己的初始序號(hào)server_isn,記錄在序列號(hào)seq中。這個(gè)報(bào)文表達(dá)的就是允許建立該連接,我自己的初始序號(hào)是server_isn。有時(shí)也被成為SYNACK報(bào)文段。
第三步:
在收到SYNACK報(bào)文段之后,客戶端也要給該連接分配緩存和變量,客戶端向服務(wù)器再發(fā)送一個(gè)報(bào)文段,對(duì)允許連接的報(bào)文段進(jìn)行了確認(rèn),其ack被置為server_isn+1,表示下一個(gè)希望從服務(wù)器獲得的報(bào)文段的序列號(hào)為此。并且由于連接已經(jīng)建立了,SYN標(biāo)志位被置為0,并且已經(jīng)可以攜帶被傳送到服務(wù)器的應(yīng)用層數(shù)據(jù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1、TCP狀態(tài)linux查看tcp的狀態(tài)命令:1)、netstat -nat 查看TCP各個(gè)狀態(tài)的數(shù)量2)、lso...
    北辰青閱讀 9,509評(píng)論 0 11
  • 個(gè)人認(rèn)為,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記,這雖然只是...
    貳零壹柒_fc10閱讀 5,092評(píng)論 0 8
  • 1.這篇文章不是本人原創(chuàng)的,只是個(gè)人為了對(duì)這部分知識(shí)做一個(gè)整理和系統(tǒng)的輸出而編輯成的,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,133評(píng)論 6 174
  • 18.1 引言 TCP是一個(gè)面向連接的協(xié)議。無(wú)論哪一方向另一方發(fā)送數(shù)據(jù)之前,都必須先在雙方之間建立一條連接。本章將...
    張芳濤閱讀 3,425評(píng)論 0 13
  • 傳輸層-TCP, TCP頭部結(jié)構(gòu) ,TCP序列號(hào)和確認(rèn)號(hào)詳解 TCP主要解決下面的三個(gè)問(wèn)題 1.數(shù)據(jù)的可靠傳輸...
    抓兔子的貓閱讀 4,545評(píng)論 1 46