1. 程式人生 > >TCP 建立連接為什麽要握 3 次手?

TCP 建立連接為什麽要握 3 次手?

ans 建立連接 七層 計算機 如果 通信 註意 四次握手 三層

上次已經說過,沒有協議,不成方圓,計算機之間的通信更是依賴於協議。今天就重點分析一下 TCP 協議。

傳輸控制協議 TCP 是一種面向連接的、可靠的、基於字節流的傳輸層通信協議,由IETF的RFC 793定義。在簡化的計算機網絡 OSI 模型中,它完成第四層傳輸層所指定的功能,用戶數據包協議(UDP)是同一層內另一個重要的傳輸協議。

先來復習一下 OSI 的七層模型。

技術分享圖片

TCP 工作在 OSI 中的第四層——Transport 層,IP 在第三層——Network 層,ARP 在第二層——Data Link 層;在第二層上的數據,我們把它叫 Frame,在第三層上的數據叫 Packet,第四層的數據叫 Segment。 同時,我們需要知道,數據從應用層發下來,會在每一層都會加上頭部信息,進行封裝,然後再發送到數據接收端。

技術分享圖片

TCP 協議所涉及到的知識太多,沒有辦法兼顧,我主要想談談 3 次握手和 4 次揮手。TCP 的運行可以分為三個階段,建立連接、傳送數據、關閉連接。3 次握手 4 次揮手就對應著建立連接和關閉連接。

操作系統將 TCP 連接抽象為套接字表示的本地端點,作為編程接口給程序使用。在 TCP 連接的生命期內,本地端點要經歷一系列的狀態改變。我們經常會聽到面向 Socket 編程,這是後話了。

要想知道握手是怎樣進行了,我們先來看看 TCP 的報文結構。

技術分享圖片

有以下幾點需要說明

TCP 報文中沒有 IP 地址,有源端口和目的端口,IP 地址在網絡層中的 Packet 中。

Sequence Number(序號),用來標識從 TCP 發送端向 TCP 接收端發送的數據字節流,它表示在這個報文段中的的第一個數據字節在數據流中的序號;通信雙方要知道對方的初始化序號,這個號要作為以後的數據通信的序號,以保證應用層接收到的數據不會因為網絡上的傳輸的問題而亂序(TCP 會用這個序號來拼接數據)。

Acknowledgment Number(確認號)32 位確認序列號包含發送確認的一端所期望收到的下一個序號,因此,確認序號應當是上次已成功收到數據字節序號加 1。不過,只有當標誌位中的 ACK 標誌(下面介紹)為 1 時該確認序列號的字段才有效。主要用來解決不丟包的問題。

SYN,表示同步序號,用來建立連接。SYN 標誌位和 ACK 標誌位搭配使用,當連接請求的時候,SYN=1,ACK=0;連接被響應的時候,SYN=1,ACK=1。

這個標誌的數據包經常被用來進行端口掃描。掃描者發送一個只有 SYN 的數據包,如果對方主機響應了一個數據包回來 ,就表明這臺主機存在這個端口;但是由於這種掃描方式只是進行 TCP 三次握手的第一次握手,因此這種掃描的成功表示被掃描的機器不很安全,一臺安全的主機將會強制要求一個連接嚴格的進行 TCP 的三次握手。

ACK,TCP 協議規定,只有 ACK=1 時有效,也規定連接建立後所有發送的報文的 ACK 必須為 1 。

FIN,表示發送端已經達到數據末尾,也就是說雙方的數據傳送完成,沒有數據可以傳送了,發送 FIN 標誌位的 TCP 數據包後,連接將被斷開。這個標誌的數據包也經常被用於進行端口掃描。

技術分享圖片

三次握手的過程,即建立一個 TCP 連接的過程,在 Socket 編程中,這一過程由客戶端執行 connect 來觸發,整個流程如上圖所示。

第一次握手:Client 將標誌位 SYN 置為1,隨機產生一個值 seq=x,並將該數據包發送給 Server,Client 進入 SYN_SENT 狀態,等待 Server 確認。

第二次握手:Server 收到數據包後由標誌位 SYN=1 知道 Client 請求建立連接,Server 將標誌位 SYN 和 ACK 都置為1,ack=x+1,隨機產生一個值 seq=y,並將該數據包發送給 Client 以確認連接請求,Server 進入 SYN_RCVD 狀態。

第三次握手:Client 收到確認後,檢查 ack 是否為 x+1,ACK 是否為1,如果正確則將標誌位 ACK 置為1,ack=y+1,並將該數據包發送給 Server,Server 檢查 ack 是否為 y+1,ACK 是否為1,如果正確則連接建立成功,Client 和 Server 進入 ESTABLISHED 狀態,完成三次握手,隨後 Client 與 Server 之間可以開始傳輸數據了。

註意,不要搞混了 SYN、ACK 只是標誌位,seq 是序號,防止亂序,ack 是確認號,主要用來解決不丟包的問題。

四次揮手,即終止 TCP 連接,就是指斷開一個 TCP 連接時,需要客戶端和服務端總共發送4個包以確認連接的斷開。在 Socket 編程中,這一過程由客戶端或服務端任一方執行 close 來觸發。

由於 TCP 連接是全雙工的,因此,每個方向都必須要單獨進行關閉,這一原則是當一方完成數據發送任務後,發送一個 FIN 來終止這一方向的連接,收到一個 FIN 只是意味著這一方向上沒有數據流動了,即不會再收到數據了,但是在這個 TCP 連接上仍然能夠發送數據,直到對方也發送了 FIN。首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉。

第一次揮手:主機1(可以使客戶端,也可以是服務器端),設置Sequence Number 和 Acknowledgment Number,向主機2發送一個FIN報文段;此時,主機1進入FIN_WAIT_1狀態;這表示主機1沒有數據要發送給主機2了;

第二次揮手:主機2收到了主機1發送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number為Sequence Number加1;主機1進入FIN_WAIT_2狀態;主機2告訴主機1,我“同意”你的關閉請求;

第三次揮手:主機2向主機1發送FIN報文段,請求關閉連接,同時主機2進入LAST_ACK狀態;

第四次揮手:主機1收到主機2發送的FIN報文段,向主機2發送ACK報文段,然後主機1進入TIME_WAIT狀態;主機2收到主機1的ACK報文段以後,就關閉連接;此時,主機1等待2MSL後依然沒有收到回復,則證明 Server 端已正常關閉,那好,主機1也可以關閉連接了。

為什麽建立連接需要 3 次握手 ?

因為,TCP 協議要保證兩端數據的可靠傳輸,最少就要采取 3 次交互。三次是保證雙方互相明確對方能收能發的最低值。下面有個生活中的例子可以感受一下。

TCP之所以使用三次握手,完全是一種為了解決“兩軍問題”所采用的折衷的設計。所謂“兩軍問題”,就是紅軍想告訴藍軍明天下午一起對敵開火,那麽紅軍會派信使 1 號跑過去告訴藍軍,藍軍收到消息再派信使 2 號告訴紅軍收到,註意,這時藍軍並不知道紅軍是否收到藍軍的回復。因此需要紅軍收到回復再派信使 3 號告訴藍軍收到回復,而此時紅軍也不知道藍軍是否收到回復,因此藍軍收到信使 3 號的消息再派信使 4 號…

還有一個秒懂例子,看到這個真的笑死我了。但是這個例子不嚴謹哦,權當一樂就好。

三次握手:
“餵,你聽得到嗎?”
“我聽得到呀,你聽得到我嗎?”
“我能聽到你,今天balabala……”

兩次握手:
“餵,你聽得到嗎?”
“我聽得到呀”
“餵餵,你聽得到嗎?”
“草,我聽得到呀!!!!”
“你TM能不能聽到我講話啊!!餵!”
“……”

四次握手:
“餵,你聽得到嗎?”
“我聽得到呀,你聽得到我嗎?”
“我能聽到你,你能聽到我嗎?”
“……不想跟傻逼說話”

所以說,握手次數要保持剛剛好,2 次不夠,4 次多了。

SYN 攻擊

SYN 攻擊指的是,攻擊客戶端在短時間內偽造大量不存在的 IP 地址,向服務器不斷地發送 SYN 包,服務器回復確認包,並等待客戶的確認。由於源地址是不存在的,服務器需要不斷的重發直至超時,這些偽造的 SYN 包將長時間占用未連接隊列,正常的 SYN 請求被丟棄,導致目標系統運行緩慢,嚴重者會引起網絡堵塞甚至系統癱瘓。SYN 攻擊是一種典型的 DoS/DDoS 攻擊。

檢測 SYN 攻擊非常的方便,當你在服務器上看到大量的半連接狀態時,特別是源IP地址是隨機的,基本上可以斷定這是一次SYN攻擊。

如何防禦 SYN 攻擊 ?

SYN 攻擊不能完全被阻止,除非將 TCP 協議重新設計。我們所做的是盡可能的減輕 SYN 攻擊的危害,常見的防禦 SYN 攻擊的方法有如下幾種:

縮短超時(SYN Timeout)時間

增加最大半連接數

過濾網關防護

SYN cookies 技術

TCP 建立連接為什麽要握 3 次手?