資訊科普系列(17)-網路封包結構

TCP & HTTP

曹仲辰
MODA IT
12 min readJan 4, 2024

--

TCP (Transmission Control Protocol)

TCP是一個面向連結(connection-oriented)、可靠的(reliable)、位元流式(byte stream)的傳輸協議。其使用三方交握來建立可靠的連接。TCP可以重新排序到達順序錯誤的分段,並重新傳送遺失的分段。

在 TCP 連接建立過程中,雙方通常會協商最大分段大小(MSS),這代表每個 TCP 資料段中可攜帶的最大位元數。MSS 的大小通常受到底層網路的MTU(Maximum Transmission Unit)限制,確保 TCP 資料段在傳輸過程中不需要分片,從而提高效率。

TCP/IP Illustrated, Volume 1: The Protocols

TCP Maximum Segment Size (MSS)

MSS 是網路裝置可以接收的最大 TCP 區段大小。MSS 以 bytes 為單位。

MTU -(TCP header+ IP header)= MSS

MSS 預設為 1,460 個位元組,因為MTU 為 1,500 bytes 而 TCP header 與 IP header 最大為20 bytes 。

封包欄位

TCP Header

  1. 來源 Port(16 bits): 來源/應用程式 的 port 號
  2. 目的地 Port (16 bits): 應用程式的 port 號,有助於將資料發送到適當的應用程式。
  3. 序列號 (32 bits): 標示了TCP封包中第一个byte在對應方向的傳輸中對應的序號
  4. 確認號(32 bits): 用來通知發送端已經成功接收到資料。
  5. 資料偏移(4 bits): 包含TCP header 大小,與告知資料從哪裏開始
  6. 控制標記 (9 bits): TCP使用一些控制標記來調節連線。一些重要的標誌包括:SYN:建立一個連結、ACK:確認接收到的資料、FIN:結束一個連結、RST(重置):發生錯誤時重置連接。
  7. 窗口大小 (16 bits): 接收方通知發送方它目前能夠接收多少字節的資料,而不需要等待確認。用於TCP的流量控制。
  8. 檢驗和 (16 bits): 用來檢查 header 或 data 是否受損。
  9. 緊急指針 (16 bits): 控制標記URG才會啟動,允許在正常資料流中插入一些具有高優先級的訊息。
  10. Options: 長度不定,但長度必須以是32bits的整數倍。常見的選項包括MSS、SACK、Timestamp等等。

三方交握

https://medium.com/@kusal95/tcp-3-way-handshake-process-1fd9a056a2f4
  1. client 向 server 發出連接請求的封包,其 header 中的帶有 SYN = 1,初始序列號 seq = m,說明傳送封包時的第一個位元序號是 m。
  2. server 收到SYN封包後,回覆封包會帶有SYN =1 與ACK = 1 ,而確認號ack會等於m+1,自己選擇的序號 seq = n 。
  3. client 收到此封包後向 server 給出確認 ACK =1,還會帶有ack = n + 1
  4. 雙方都會在收到確認通知其上層應用程式 TCP 連接已經建立,之後就會進入連線狀態開始交換資料。

一般來說上面用來建立連接的初始序列號ISN(即m和n)的值是隨機選取的。RFC1948提出了一個ISN隨機生成的演算法

ISN = M + F(localhost, localport, remotehost, remoteport)

其中M是一个計時器,每隔4毫秒加1。F是一个Hash演算法,根據來源IP、目的地IP、來源 port、目的地 port 生成一个隨機數。

四次揮手

https://xvpn.io/blog/what-is-tcp-and-how-tcp-works
  1. client 關閉TCP連接時, 連接釋放封包的標記位 會帶有 FIN = 1,ACK=1,其序號seq = x,確認號ack=y,等待 server 確認。
  2. server 收到 client 的FIN封包後,發出確認,確認號 ack = x + 1,而這個封包的序列號 seq = y。
  3. 當 client 收到 server 的ACK確認封包後,A進入FIN_WAIT_2狀態 。
    若 server 已經沒有要向 client 發送的數據,其應用程式就通知 TCP 釋放連接。server 傳送連接釋放封包,FIN=1,ACK=1,封包序列號 seq= z,確認號ack=x+1。
  4. A 收到連接釋放封包後,必須發出確認,在確認封包中 ACK = 1,確認號 ack = z + 1,自己的序號 seq = x + 1。 client 經過2MSL時間後就進入關閉狀態,在 server 接收到 client 的確認封包後,立即進入關閉狀態。兩者都進入關閉狀態後整個TCP連接釋放。

MSL ( Maximum Segment Lifetime ),是指封包在網路上存在的的最長時間,超過這個時間封包將被丟棄。RFC793定義了MSL為2分鐘,Linux設定成了30s。

HTTP ( HyperText Transfer Protocol )

是一種用於分佈式、協作式和超媒體訊息系統的應用層協定。由 client 發送 HTTP Request 到 server,然後 server 返回 HTTP Response 。

HTTP-message = Request | Response

HTTP-message 會包含以下內容:

  1. URL 和參數
  2. 一個 HTTP method
  3. HTTP header
  4. Message Body

HTTP method

表示 HTTP request 期待伺服器執行的動作。

  1. GET:向指定的資源發出請求。
  2. POST:向指定資源提交資料,可在Body中帶資料。
  3. PUT:取代指定的資源。
  4. DELETE:刪除指定的資源。
  5. HEAD:與GET相似,但只會取得 header 與HTTP status。
  6. CONNECT:通常用在Proxy。
  7. OPTIONS:回傳這個伺服器支援的所有 HTTP Method。
  8. TRACE:回傳收到的請求內容。

header 欄位

header 欄位根據用途被分為以下類型:

  • General Header Fields-在請求訊息和回應訊息都適用的欄位
  • Request Header Fields-允許 client 傳遞有關請求以及有關 client 自身附加訊息給 server。
  • Response Header Fields-允許 server 傳遞有關回應的額外訊息,這些訊息無法放在 Status-Line 中。這些 header 字段提供有關 server 以及Request-URI 資源的訊息。
  • Entity Header Fields-請求和回應訊息在不受 request method 或 status code 限制的情況下,可能傳輸一個實體。一個實體包括實體 Header 和實體主體。

Request

在 client 發送到 server 的 request message 的第一行中,會有應用於該資源的方法、資源的識別碼,以及使用的協定版本。

Request-Line = Method SP Request-URI SP HTTP-Version

Request-URI = "*" | absoluteURI | abs_path | authority

ex.

  1. OPTIONS * HTTP/1.1
  2. GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1
  3. GET /pub/WWW/TheProject.html HTTP/1.1 Host: www.w3.org

必須使用以下規則來確定對 HTTP/1.1 request 所請求的資源

  1. 如果 Request-URI 是 absoluteURI,則 HOST 是 Request-URI 的一部分。在 request 中的任何 Host header field 必須被忽略。
  2. 如果 Request-URI 不是 absoluteURI,並且請求包括 Host header field,則HOST 由Host header field 決定。
  3. 如果由規則1或2確定的 HOST 在 server 上不是有效的主機,則回應必須是400(Bad Request)。

Response

在接收並解釋 request 後,server 會回覆一個 response。

response-message 的第一行是Status-Line,包括協定版本,後面是狀態碼及其相應的敘述。

Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase

Status-Code

是試圖理解並滿足 request 的3位數號碼,Reason-Phrase旨在提供Status-Code的簡短文字描述。

- 1xx: 資訊回應 - 請求已收到,正在處理

- 2xx: 成功回應 - 該操作已成功接收、理解並接受

- 3xx: 重定向 - 需要進一步採取行動以完成 request

- 4xx: Client Error - request 包含不良的語法或無法滿足

- 5xx: Server Error - server 未能滿足一個明顯有效的 request
https://medium.com/@guptadiksha88/how-to-validate-rest-api-request-response-using-rest-assured-41a57cc3630a

封包傳遞

client 與 server 進行通信時,過程如下:

  1. 域名解析: client 會透過 DNS ,將對方的 Domain 解析為 IP 。
  2. ARP 解析: client 使用目標 IP 查詢本地的 ARP table,獲取對應的MAC。如果找不到,則需要進行ARP解析,發送ARP請求到網路以獲取目標的MAC。
  3. 資料傳輸: 在開始通信之前,client 和 server 會透過三方交握建立一個通信連接。一旦連接建立,資料就可以在 client 和 server 之間傳輸。

在兩個設備中傳輸的封包會帶上接收端 router 的 MAC 在讓我們可以傳封包過去,再透過 router 解析出來的 IP 將封包丟到指定的位置,在指定的位置組合TCP封包,再將資料傳給應用程式。

參考資料

https://www.cloudflare.com/zh-tw/learning/network-layer/what-is-mss/

https://medium.com/fcamels-notes/tcp-maximum-segment-size-%E6%98%AF%E4%BB%80%E9%BA%BC%E4%BB%A5%E5%8F%8A%E6%98%AF%E5%A6%82%E4%BD%95%E6%B1%BA%E5%AE%9A%E7%9A%84-b5fd9005702e

--

--