TCP頭部字段詳解
1. 源端口和目的端口(各16位)
功能:標識發送和接收應用程序
范圍:0-65535(0-1023為知名端口)
技術細節:
客戶端通常使用臨時端口(1024-65535)
服務端使用固定端口(如HTTP=80, HTTPS=443)
支持端口復用(SO_REUSEPORT選項)
// Linux內核端口選擇算法 (net/ipv4/inet_connection_sock.c)
int inet_csk_get_port(struct sock *sk, unsigned short snum) {// ... 實現端口自動選擇和沖突處理
}
2. 序列號(32位)
功能:標識發送的數據字節流
初始序列號(ISN):基于時鐘的隨機算法(RFC 6528)
防止序列號預測攻擊
避免舊連接的報文干擾
內核實現:
// Linux ISN生成算法 (net/ipv4/tcp_ipv4.c) u32 secure_tcp_seq(__be32 saddr, __be32 daddr,__be16 sport, __be16 dport) {// 使用SipHash加密算法生成 }
回繞處理:當序列號達到2^32-1時回繞到0
3. 確認號(32位)
功能:期望收到的下一個字節的序列號
累積確認機制:確認號N表示所有小于N的字節已收到
選擇性確認(SACK):通過TCP選項實現非連續確認
4. 數據偏移(4位)
功能:指定TCP頭部長度(以4字節為單位)
計算:頭部長度 = 數據偏移 × 4
范圍:5(最小20字節)到15(最大60字節)
5. 保留位(4位)
必須置0,為未來協議擴展保留
實際使用中可能被實驗性協議使用(需IANA批準)
6. 控制標志(9位)
標志位 | 名稱 | 功能 | 應用場景 |
---|---|---|---|
URG | 緊急指針 | 指示緊急數據處理 | Telnet中斷命令 |
ACK | 確認 | 確認號字段有效 | 所有數據傳輸 |
PSH | 推送 | 要求立即交付數據 | 實時交互應用 |
RST | 重置 | 立即終止連接 | 端口掃描防御 |
SYN | 同步 | 建立連接同步序列號 | 三次握手 |
FIN | 結束 | 發送方完成數據發送 | 四次揮手 |
標志組合示例:
SYN+ACK:連接建立響應
FIN+ACK:正常連接終止
PSH+ACK:即時數據傳輸
7. 窗口大小(16位)
功能:接收方通告的可用緩沖區大小
流量控制機制:動態調整發送速率
窗口縮放選項:通過選項擴展窗口大小(最高1GB)
// Linux內核窗口縮放處理 (net/ipv4/tcp_input.c) void tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb) {// ... 處理窗口縮放選項 }
零窗口探測:當窗口為0時發送探測報文
8. 校驗和(16位)
10. 選項字段(可變長度)
選項結構:
+--------+--------+--------+--------+ | Kind | Length | Data... | +--------+--------+--------+--------+
核心選項詳解:
覆蓋范圍:TCP頭部+數據+偽頭部
偽頭部結構:
0 7 8 15 16 23 24 31 +--------+--------+--------+--------+ | source address | +--------+--------+--------+--------+ | destination address | +--------+--------+--------+--------+ | zero | PTCL | TCP length | +--------+--------+--------+--------+
計算算法:
uint16_t tcp_checksum(const void *buff, size_t len, in_addr_t src_addr, in_addr_t dest_addr) {uint32_t sum = 0;const uint16_t *ptr = buff;// 偽頭部計算struct pseudo_header psh = {src_addr, dest_addr, htons(IPPROTO_TCP), htons(len)};sum = calculate(&psh, sizeof(psh));// 數據計算while (len > 1) {sum += *ptr++;len -= 2;}if (len > 0) sum += (*ptr) & htons(0xFF00);// 折疊進位sum = (sum >> 16) + (sum & 0xFFFF);sum += (sum >> 16);return (uint16_t)(~sum); }
9. 緊急指針(16位)
功能:當URG=1時,指示緊急數據結束位置
計算:緊急數據結束 = 序列號 + 緊急指針
實際應用:SSH/Telnet的中斷命令(Ctrl+C)
Kind | 名稱 | 長度 | 功能 |
---|---|---|---|
0 | 選項結束 | 1 | 選項列表結束 |
1 | 無操作 | 1 | 選項填充 |
2 | 最大報文段 | 4 | 協商MSS(通常1460) |
3 | 窗口擴大因子 | 3 | 窗口縮放(2^14倍) |
4 | 選擇性確認 | 2 | 啟用SACK功能 |
5 | SACK塊 | 可變 | 非連續接收的數據塊 |
8 | 時間戳 | 10 | RTT測量和PAWS保護 |
28 | 用戶超時 | 4 | 連接超時設置 |
29 | 認證 | 可變 | TCP-AO安全認證 |
以超時重傳為例,假設客戶端(Client)向服務器(Server)發送數據包,但未收到ACK確認。
場景步驟:
Client發送數據包(初始傳輸):
- TCP頭部包含選項字段(如時間戳):
數據偏移 = 8(頭部總長32字節 = 8 × 4) 選項字段:時間戳(Timestamp)值 = T1 序列號(Seq) = 100 數據 = "Hello"
- 數據包結構:
| 20字節固定頭部 | 12字節選項(時間戳) | 數據 "Hello" |
Server未收到該包(可能因網絡擁塞丟失):
- Client在重傳超時(RTO)?后未收到ACK,觸發重傳。
Client重傳數據包
數據偏移 = 8(長度不變)
選項字段:時間戳值 = T2(T2 > T1)
序列號(Seq)仍為 100(相同數據)
數據 = "Hello"(不變)
關鍵點分析:
- 選項長度一致性:重傳時
數據偏移
值仍為8
,表明頭部長度未變(選項字段仍存在)。 - 選項內容變化:時間戳更新(
T1 → T2
),幫助計算RTT(往返時間)和重傳延遲。 - 接收方處理:Server通過
數據偏移=8
跳過32字節頭部,直接解析數據"Hello"。