3ウェイハンドシェイク中、SYN または SYN+ACK パケットがドロップしたときは気づけるけど、ACK パケットがドロップしても気づけ無い・・・?
ふと気になったので調べてみました。
結論から言うと、後続のデータ送信用のパケットに付与されているacknowledgment numbers(確認応答番号)により、ACKパケットだけが途中でドロップしたことを確認できます。
ACKパケットのドロップを確認した宛先側は暗黙的なACKパケットを受け取った状態になり、SYN_RECEIVED状態からESTABLISHED状態に遷移、コネクションを確立します。
解説します。
#3ウェイハンドシェイクとは
名前の通り以下の3つの要求と許可の確認をし、通信できる状態を作り出している。
1.送信元が通信路を確保するため、相手にデータ転送の許可要求を出す。(SYN)
2.宛先側が許可を送信元に知らせると同時に受信側も許可要求を出す。(ACK + SYN)
3.最初にSYNを送った送信元も宛先側に許可を出す。(ACK)
以上の手順で送信元と宛先側の双方が許可依頼、許可受領を済ますとコンピュータ上ではESTABLISHEDという状態になる。この状態をコネクションの確立と呼ぶ。
引用元 : 【TCP】コネクションの確立までの道のり - Qiita
上記の3つの手順でパケットがドロップした場合どのような動作になるのか、トレースします。
#1. SYNパケットがドロップしたら
もしもSYNパケットが宛先側に届かなかったらどうなるでしょうか。
送信元はSYNパケットを送信しているので、SYN+ACKパケットを待機している状態です(SYN_SENT)。
宛先側は何のパケットも受け取っていないのでLISTEN状態のままです。
タイムアウトまでにSYN+ACKパケットが帰ってこなければ送信元はSYNパケットを再送信します。
#2. SYN+ACKパケットがドロップしたら
宛先側がSYNパケットを受信し、SYN+ACKパケットを返送した後SYN_RECEIVED状態に遷移します。
送信元からしてみれば、往路と復路のどちらでパケットがドロップしたとしても「SYN+ACKパケットが帰ってこない」という状態に変わりは無いので、タイムアウトを迎え次第パケットを再送信します。
#3. ACKパケットがドロップしたら
ここからがいよいよ本題です。
送信元はESTABLISHED状態に遷移し、ACKパケットを送信します。
ここでACKパケットがドロップした場合どうなるでしょうか。
送信元はESTABLISHED状態。つまりコネクションが確立した状態になり、対する宛先側はコネクションが確立されていない待機状態です。
送信元ではコネクションが確立されたと思っているので、手順1, 2のようにタイムアウトを迎えることはありません。
では宛先側でタイムアウトが有るのかというとそうではありません。
送信元はコネクションが確立された状態に遷移したため、宛先側の状態にかかわらずデータ送受信用のパケットを宛先側に送信します。
ここで正常にパケットが受信された場合、パケットに付与されたacknowledgment numbers(確認応答番号)という情報を元に、途中のパケットが消失していないかの計算が行われます。
確認応答番号はとある一定の規則に従い増加していくため、この数値が飛んでいたらパケットの消失に気づける仕組みになっています。
確認応答番号を計算することで、ACK パケットだけが途中でドロップしたことを確認できます。
ACKパケットのドロップを確認した宛先側は暗黙的な ACK パケットを受け取った状態になり、SYN_RECEIVED 状態から ESTABLISHED 状態に遷移、コネクションを確立、データの送受信を開始します。
#まとめ
ACK パケットが正常に伝送できなくても後続のパケットが正常に伝送できれば問題ない。
ちなみに、
後続のパケットもドロップし、その後のパケットが正常に伝送され場合は確認応答番号が急激に増えるため、異常を検知し、コネクションは強制的にリセットされます。
#参考
確認応答番号について詳しく知りたい方はこのサイトをおすすめします。
https://www.infraexpert.com/study/tcpip9.html
TCPのRFC
https://tools.ietf.org/html/rfc793
#蛇足
高度にブラックボックス化されているおかげで普段気にしなくて良いような知識をどれだけ知っているか。
そこに価値を見出していきたい。