この記事の結論3ウェイハンドシェイクは、クライアントとサーバーがそれぞれ初期シーケンス番号を知らせ、相手の番号を受け取ったと確認する手続きです。SYN、SYN + ACK、ACK の3段階を終えるとTCP接続が確立し、その上でTLSやHTTPの通信が始まります。

TCPハンドシェイクは何を準備するのか

TCPは、送ったデータが欠けたり順序が入れ替わったりしても、受信側で正しいバイト列へ戻せるように設計されています。そのため、接続の両側はデータを識別するためのシーケンス番号を持ちます。ハンドシェイクでは、相手が応答できることを確かめると同時に、お互いの初期シーケンス番号(ISN)を交換します。

SYN と ACK は別々のパケット名ではなく、TCPヘッダー内のフラグです。ひとつのパケットで両方を有効にできるため、2番目の応答は一般に「SYN/ACK」と呼ばれます。

3ウェイハンドシェイクを図で見る

例として、クライアントの初期シーケンス番号を1000、サーバーの番号を5000とします。

sequenceDiagram
  autonumber
  participant Client as クライアント
  participant Server as サーバー

  Client->>Server: SYN / Seq=1000
  Note right of Client: 接続したい。こちらの開始番号は1000
  Server-->>Client: SYN + ACK / Seq=5000 / Ack=1001
  Note left of Server: 1000を確認。こちらの開始番号は5000
  Client->>Server: ACK / Seq=1001 / Ack=5001
  Note over Client,Server: TCP接続が確立(ESTABLISHED)
段階送信内容と意味
1. SYNクライアントが接続を要求し、自分の初期シーケンス番号を知らせる
2. SYN + ACKサーバーが要求の受信を確認しながら、自分の初期シーケンス番号も知らせる
3. ACKクライアントがサーバーのSYNを受信したと確認し、接続を成立させる

SYNとACKは何を表しているのか

SYN は synchronize の略で、シーケンス番号を同期して接続を開始するためのフラグです。ACK は acknowledgment の略で、確認応答番号が有効であることを示します。

ACK番号は「最後に受け取った番号」ではなく、基本的に次に受け取りたいシーケンス番号です。最初のSYNが Seq=1000 なら、サーバーは Ack=1001 を返します。SYNはアプリケーションデータを含まなくても、シーケンス番号を1つ消費するためです。サーバーのSYNも同様に5000を1つ消費し、最後の応答は Ack=5001 になります。

確認応答番号 = 受信したシーケンス番号 + 受信データ長
SYNまたはFINがある場合は、さらに + 1

なぜ2回ではなく3回必要なのか

最初のSYNで、サーバーは「クライアントから自分へ届く」ことを確認できます。次のSYN/ACKで、クライアントは「サーバーから自分へも届く」ことを確認できます。しかし、この時点ではサーバー側に、自分のSYN/ACKがクライアントへ届いたという確証がありません。

3回目のACKがサーバーへ届くことで、サーバーも双方向の到達性と、自分の初期シーケンス番号が受け取られたことを確認できます。これで双方が必要な情報を共有した状態になります。

パケットが届かなかったらどうなるのか

SYNやSYN/ACKが失われた場合、送信側は一定時間待った後に再送します。何度試しても応答が得られなければ、接続はタイムアウトします。サーバーがそのポートで待ち受けていない場合は、通常、SYN/ACKの代わりに RST が返り、接続拒否として扱われます。

SYN floodとの関係サーバーはSYNを受け取ると、最後のACKを待つ間、接続情報を一時的に保持します。大量のSYNを送り、ACKを返さずにこの領域を消費させる攻撃がSYN floodです。SYN cookieなどは、この負荷を軽減するための対策です。

Webアクセスではこの後に何が起きるのか

TCP接続の確立は、Web通信の土台を作った段階にすぎません。HTTPの場合は、この後にリクエストとレスポンスを交換します。HTTPSでは、TCPハンドシェイクの後にTLSハンドシェイクを行い、暗号方式や証明書を確認してからHTTPデータを送ります。

  1. DNSDNSでIPアドレスを取得
  2. TCPTCP 3ウェイハンドシェイク
  3. HTTPSTLSハンドシェイク後にHTTPリクエストとレスポンス
  4. HTTP暗号化なしの場合はTCP接続後にHTTP通信

したがって、TCPハンドシェイク自体には通信内容の暗号化やサーバーの本人確認はありません。それらはTLSが担当します。またHTTP/3はTCPではなくQUICを利用するため、この順序とは異なります。

開発時の切り分けに使う

ブラウザやAPIからサーバーへ接続できないときは、どの段階で止まっているかを分けて考えると原因を絞れます。SYNに応答がなければ、IPアドレス、ルーティング、ファイアウォールなどを確認します。RSTが返るなら、対象ポートでプロセスが待ち受けているかを確認します。TCP接続後に失敗するなら、TLS証明書やHTTPの設定が次の候補です。

観測結果主な確認箇所
SYNを再送し続ける経路、ファイアウォール、宛先IP、サーバーの稼働状態
RSTが返るポート番号、待ち受けプロセス、ポート公開設定
TCP確立後に切断TLS、証明書、アプリケーションプロトコル、サーバーログ

まとめ

3ウェイハンドシェイクの本質は、単なる「接続します・了解・確認」の挨拶ではありません。双方が初期シーケンス番号を交換し、その受信をACKで確認することで、信頼性のあるバイトストリームを始める準備をしています。ACK番号を「次に欲しい番号」と捉えると、1000 → 1001 のように1増える理由も理解しやすくなります。