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 が返り、接続拒否として扱われます。
Webアクセスではこの後に何が起きるのか
TCP接続の確立は、Web通信の土台を作った段階にすぎません。HTTPの場合は、この後にリクエストとレスポンスを交換します。HTTPSでは、TCPハンドシェイクの後にTLSハンドシェイクを行い、暗号方式や証明書を確認してからHTTPデータを送ります。
- DNSDNSでIPアドレスを取得
- TCPTCP 3ウェイハンドシェイク
- HTTPSTLSハンドシェイク後にHTTPリクエストとレスポンス
- 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増える理由も理解しやすくなります。