六種情境的封包往返流程:每個封包帶什麼旗標、序號怎麼走、兩端狀態如何轉換。從正常連線一路看到 RST 中斷與 ACK 掃描。點「播放」看動畫,或用上一步/下一步逐格講解。
| 場合 | 旗標組合 | tcp.flags | 意義 |
|---|---|---|---|
| 交握 1 | SYN | 0x002 | 請求建立連線,宣告初始序號(ISN)。 |
| 交握 2 | SYN, ACK | 0x012 | 同意建立,同時確認對方序號並送出自己的 ISN。全流程唯一同時帶 SYN 與 ACK 的封包。 |
| 交握 3 | ACK | 0x010 | 確認伺服器的 ISN,連線正式成立。 |
| 傳資料 | PSH, ACK | 0x018 | 攜帶資料並要求對方立即上交應用層。 |
| 純確認 | ACK | 0x010 | Len=0,只告訴對方已收到多少位元組。 |
| 揮手 1 / 3 | FIN, ACK | 0x011 | 我這方沒有資料要送了(單向關閉)。 |
| 揮手 2 / 4 | ACK | 0x010 | 確認對方的 FIN。 |
| 拒絕連線 | RST, ACK | 0x014 | 對 SYN 的拒絕。連接埠沒有服務在聽時的標準回應。 |
| 中斷連線 | RST | 0x004 | 單獨的 RST,用於拋棄一條不該存在的連線(如收到孤兒 ACK)。 |
| 隱匿掃描 | 無旗標 / FIN / FIN,PSH,URG | 0x000 / 0x001 / 0x029 | NULL、FIN、Xmas 掃描。合法流量不會出現這些組合,看到就是掃描。 |
Ack = 對方的 Seq + 收到的位元組數。SYN 與 FIN 雖然不帶資料,但各佔用 1 個序號,所以交握第二步的 Ack 是 1 而不是 0。
Wireshark 預設顯示相對序號(連線起點歸零)方便閱讀;要看線路上真正的隨機 ISN,改看 tcp.seq_raw,或在 Preferences → Protocols → TCP 取消「Relative sequence numbers」。
四向揮手常被壓成三個封包。若伺服器沒有待送資料,會把 ACK 與 FIN 合併成一個 FIN+ACK,看起來就變成「三向」。這不是錯誤。
TIME-WAIT 不是故障。主動關閉的一方要等 2MSL(多數系統 60 秒)才真正釋放通訊埠,用來吃掉網路上遲到的重複封包。伺服器出現大量 TIME-WAIT,通常代表它是主動關閉方。
實務上 RST 比 FIN 還常見。瀏覽器關分頁、連線逾時、掃到關閉的埠,都直接送 RST。用 tcp.flags.reset == 1 與 tcp.flags.fin == 1 的比例對照,很能看出網路的健康程度。
Cisco IOS 的 permit tcp any any established 只檢查封包的 ACK 或 RST 位元是否為 1,不查連線表。攻擊者只要偽造一個帶 ACK 的封包,就能通過這條規則進入內網 —— 這正是把它稱為「偽狀態過濾」的原因。
Nmap 的 -sA 用的就是這個原理:它不判斷埠是開是關,而是判斷有沒有被過濾。收到 RST = 該埠未被過濾(防火牆沒擋),毫無回應 = 被過濾。攻擊者藉此畫出防火牆的規則地圖。
防禦是改用真正的有狀態檢測:Cisco 的 CBAC 或 Zone-Based Firewall、reflexive ACL,或任何現代有狀態防火牆 —— 它們會查連線表,找不到對應連線的 ACK 一律丟棄。監控上則用 tcp.flags == 0x010 && tcp.analysis.ack_lost_segment 找出「確認了從未出現過的封包」的孤兒 ACK。