網際網路筆記:TCP

TCP 內容太多了,單獨開一篇整理。

整個 TCP 的傳輸是由 RFC 793 定義,一般念書考試不會去讀、開發單個項目也不一定需要,根據我之前實作其他協議的經驗,大概做研究或從 0 開始做一個簡單的 TCP 連線才會需要好好讀完。 

 

TCP 的託運單(header) 

因為在下面條列讀起來太累了,我試著用 title 對每個欄位的意思做了註解,把滑鼠移上去就可以知道該欄位的用途。 

此外,下面的 header 範例是一種 pseudo-header,屬於一種概念,開發不一定也長這樣。 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Source address (來源 address) Destination address (目的地 address)
SN (序列號)
ACK (確認號)
Data offset 保留 N
S
C
W
R
E
C
E
U
R
G
A
C
K
P
S
H
R
S
T
S
Y
N
F
I
N
WIN
Checksum Urgent pointer

接下來還有 Options ,改天再更新吧。

 TCP header 一般會在 20~60 個 bytes (上面的表格中,一行為 32bits = 4 bytes),補上 option 後會洛在這個長度裡。

 

TCP 的 3 次握手 (建立連線) 

這邊會用到上面 header 中 SYN、ACK (flag)、SN、ACK (確認號,下面用小寫表示) 等資訊,忘記的話先拉上去複習一下。

下面的表把滑鼠移到箭頭那格等一會會有說明。 

Client (狀態)
Server (狀態)
close
listen
SYN-sent SYN=1, SN=x ---------->  
<---------- SYN=1, ACK=1, SN=y, ack=x+1 SYN-RCVD
  ACK=1, SN=x+1, ack=y+1 ---------->
established 開始傳送資料 established
  1. Client 發起連線,送出 SYN 封包,要求建立連線

  2. Server 收到 SYN 後回應,送出 SYN+ACK 封包,表示同意連線,並要求 Client 確認

  3. Client 收到 SYN+ACK 後,送出 ACK 封包確認,連線正式建立 

建立連線後,才能夠開始傳送資料。

中間如果封包丟失的情形(ex: Server 傳送了 SYN+ACK 封包,但 Client 卻沒送 ACK) ,通常會間隔一段時間再重送一次,間隔的時間通常會隨著重送次數指數成長(實際情形看發送方怎麼設定)。

SYN 洪水攻擊

發生原因:同時間有許多 Client 送 SYN 封包,Server 會回應 SYN+ACK 並用一個 queue 暫存狀態,等待客戶回 ACK。當今天 Client 是攻擊者的話,並不會回應 SYN+ACK,這就導致 Server 暫存的 queue 被佔滿,正常用戶無法連線。(和 DDoS 很像)

現行解法: 

  • 增加 queue

  • 覆寫掉 queue 裡最舊的

  • 使用 SYN Cookie
    不在 Server 馬上存進 queue,而是把必要的資訊()編到 SYN-ACK 的 初始序號(ISN, Initial Sequence Number) 裡。Client 回傳的 ACK 中會包含「Server 給的 ISN + 1」,Server 只要解析這段資訊就知道 Client 是不是之前有送過 SYN。

     

TCP 的資料傳輸

在完成三次握手後,TCP 連線正式進入傳輸階段 (Data Transfer)。

TCP 之所以能在網路環境中保證資料的正確性與順序,主要仰賴以下幾個機制(會使用到 header 中的對應參數):

  • SN (Sequence Number,序號)
    TCP 會為每個傳送的封包分配 SN。這讓接收端能根據序號將資料重新排序,即使封包在網路傳輸過程中發生亂序,也能組裝成正確的資料

  • ACK (Acknowledgment)
    每次收到封包,接收端會回傳一個 ACK 封包

  • 逾時重傳 (Timeout-based retransmission)
    封包送出後,傳送端會等一段時間看有沒有收到接收端傳來 ACK,若是沒有收到,傳送端就會再送一次封包,間隔的時間通常會隨著重送次數指數成長

  • checksum

    • 計算內容:Pseudo Header、TCP Header、TCP Data

    • 計算方法:把計算內容以兩個一組,做補數加法 (加法進位)

    • 驗證方法: 接收端用同樣方法計算一次,再和 checksum 比對

  •  Flow Control (流量控制)
    接收端會使用 header 中 WIN 的位置來回報傳送端目前可接收的大小

  • Congestion Control (擁塞控制) 
    整個擁塞控制的內容很多(維基百科可以另開一頁說明得多),這邊先不仔細說明如何實作、原理等,只列出機制:

    • Slow Start (慢啟動) 

    • Congestion Avoidance (擁塞避免) 

    • Fast Retransmit (快重傳)

    • Fast Recovery (快恢復)

 

TCP 的 4 次揮手 (終止連線)  

這邊會用到上面 header 中 FIN、ACK (flag)、SN、ACK (確認號,下面用小寫表示) 等資訊,忘記的話先拉上去複習一下。

Client (狀態)   Server (狀態)
established 傳送資料 established
FIN-WAIT-1 FIN=1, SN=x ---------->
<---------- ACK=1, SN=y, ack=x+1 CLOSE-WAIT
FIN-WAIT-2 <---------- FIN=1, SN=z
TIME-WAIT ACK=1, ack=z+1 ----------> LAST-ACK
  CLOSED
CLOSED    
  1. Client 發送結束訊息 FIN

  2. Server 收到訊息後轉變狀態為等待關閉,送出「收到 FIN 訊息」的封包

  3. Server 發送結束訊息 FIN,然後關閉

  4. Client 送出「收到 FIN 訊息」的封包,原地等一段時間後關閉 

比起箭頭上的備註,其實我更喜歡下面這種記法(?):

Client:我沒話要說了

Server:我知道了

Server:我也沒話要說了 (關掉連線)

Client: 我知道了 (等一段時間看 Server 有沒有再傳訊息過來,沒有就關掉連線)

為什麼建立連線只要 3 次,中斷連線卻要 4 次? 

這好像是常常被提到的問題(?),但原因其實不複雜。

Client 要結束,不代表 Server 也要結束了,Server 可能還有其他訊息要傳送,所以這時還不能斷開連線,必須要 Server 也表達「我要結束」之後才能結束。




Reference 

維基百科:TCP

SYN 洪水攻擊

網際網路期末考筆記 



留言