AI に TCP の切断手順を説明させていたところ、 「FIN 単独は仕様上禁止されていません」と言われて驚きました。
え、FIN+ACK が仕様なのでは。 FIN 単独なんて無視されるのでは。
さらに調べていくと、 教科書で「4ウェイハンドシェイク」と説明されている TCP の切断について、 RFC には「4ウェイハンドシェイク」という言葉が一切出てこない という事実にも驚きました。
この記事では、この 驚き2連発 をまとめてみます。
1. FIN 単独は仕様上「禁止されていない」という衝撃
まず最初の驚きです。
AI に何度も「それはないだろう?」と確認したのですが、 調べてみると FIN 単独は仕様上「禁止されていない」 という衝撃の事実がありました。
RFC 793 は FIN 単独を禁止していません
TCP の仕様(RFC 793)では、FIN と ACK は 独立したフラグ として定義されています。
そのため、仕様上は次のどれも許容されています。
- FIN 単独
- ACK 単独
- FIN+ACK
「FIN 単独は仕様違反」というイメージを持っていたので、 これはかなり意外でした。
しかし実装では FIN 単独は“無視される”
仕様上は許容されているのに、 実際の OS(Linux/Windows/BSD)は FIN 単独を無視します。
理由は RFC 793 の動作モデルにあります。
ACK=0 のセグメントは無視される
RFC 793 の「SEGMENT ARRIVES」には、 ACK ビットが OFF のセグメントは無視する と明記されています。
つまり、FIN 単独は 実質的に“不正なセグメント”扱い になります。
そのため、実装では必ず FIN+ACK が送られます。
2. 仕様上は「4ウェイ」とは書いていないという事実
2つ目の驚きです。
当たり前のようにあちこちで見かける「4ウェイハンドシェイク」。 ところが、RFC を確認してみると 「4ウェイハンドシェイク」という言葉が一切出てこない という事実に驚きました。
教科書は「4ウェイハンドシェイク」と説明します
教科書では次のように説明されます。
- FIN+ACK
- ACK
- FIN+ACK
- ACK
この4回のやり取りから「4ウェイハンドシェイク」と呼ばれています。
しかし、実際のパケットはこの通りには見えません。
4. 実際のパケットは“3回”に見える
実装では、FIN を送るときに 必ず ACK もセット になります。
そのため、実際のパケットは次のようになります。
- FIN+ACK
- FIN+ACK
- ACK
最初の FIN+ACK が 1 パケットにまとまるため、 Wireshark などで観察すると 3回の交換に見える ことがあります。
RFC 793 は「4ウェイハンドシェイク」という言葉を一切使っていない
RFC 793 の仕様書には、
- FIN を送る
- 相手は ACK を返す
- 相手も FIN を送る
- こちらが ACK を返す
という 動作モデル が書かれているだけで、 「4ウェイ」という表現は存在しません。
つまり、
- 4ウェイハンドシェイクは“教科書が説明のために作った言葉”
- 仕様はもっと抽象的で、FIN と ACK の動作だけを定義している
ということになります。
まとめ
今回の驚き2連発をまとめると次の通りです。
驚き1:FIN 単独は仕様上禁止されていない
→ しかし実装では無視されるため、実質 FIN+ACK が必須です。
驚き2:4ウェイと教科書に書いてあるのに、仕様には書いていない
→ 実際のパケットは FIN+ACK がまとまるため、3回に見えることがあります。
TCP は「仕様(RFC)」と「実装(OS)」の間に 独特のギャップがあるプロトコルで、 その違いを知ることで理解が深まりました。


人気ブログランキング ブログパーツ