ハンドシェイクの仕組みと実務ガイド: TCP三者ハンドシェイクからTLS1.3・WebSocket・SSHまで セキュリティと性能を最適化
ハンドシェイクとは
ハンドシェイク(handshake)は、通信を開始する前に通信当事者同士が「誰と話すか」「どの方式で話すか」を合意するための手続き(プロトコル上のやりとり)を指します。ネットワーク層からアプリケーション層まで多くのプロトコルにおいて存在し、接続確立、暗号化のネゴシエーション、認証、セッション情報の交換などを目的とします。正しく実装されたハンドシェイクは安全で信頼できる通信の土台になりますが、不適切だと盗聴・改ざん・DoS等のリスクを招きます。
代表的なハンドシェイクの仕組み(概要と手順)
以下に代表的なハンドシェイクを挙げ、それぞれの手順とポイントを解説します。
TCP の三者ハンドシェイク(Three-way Handshake)
クライアントとサーバ間で接続を確立するために3回のパケット交換を行います。
- 1) クライアント → サーバ:SYN (seq = x)
- 2) サーバ → クライアント:SYN+ACK (seq = y, ack = x+1)
- 3) クライアント → サーバ:ACK (ack = y+1)
SYN フラグはシーケンス番号を消費するため +1 の扱いになる点や、SYN flood(同時に大量の未完了接続)に対する対策(SYN cookie など)が実装上重要です。RFC 793 を基礎知識として押さえておきましょう。
TLS(SSL)ハンドシェイク
通信チャネルの暗号化と認証を行うプロセスです。バージョンによって手順が異なります。
- TLS 1.2(従来型):ClientHello → ServerHello → Certificate → ServerKeyExchange? → ServerHelloDone → ClientKeyExchange → ChangeCipherSpec → Finished。RSA 暗号での鍵交換や(より安全な)(EC)DHE による鍵共有が用いられます。
- TLS 1.3(簡素化・高速化):ClientHello(key_share, supported_versions, PSK など)→ ServerHello → EncryptedExtensions → Certificate / CertificateVerify → Finished。TLS 1.3 は静的 RSA 暗号での鍵交換を廃止し、エフェメラル鍵交換(ECDHE)が中心で、フォワードシークレシーを標準で提供します。またハンドシェイク往復数(RTT)が削減され、0-RTT(過去のPSKを使用した早期データ送信)は再生攻撃リスクに注意が必要です。
TLS では「証明書チェーン」「署名」「ランダム値(nonce)」「鍵導出」が重要な要素です。TLS 1.3 は RFC 8446 に規定されています。
WebSocket ハンドシェイク
HTTP ベースの Upgrade 機構を用いて行われます。クライアントが HTTP GET を送信し、ヘッダに Upgrade: websocket と Sec-WebSocket-Key を含めます。サーバは Sec-WebSocket-Key に定められたマジック文字列を結合して SHA-1 → Base64 を行った値を Sec-WebSocket-Accept に入れて応答します(RFC 6455)。
SSH ハンドシェイク(トランスポート層)
SSH はまずプロトコルバージョン交換、その後 KEX(鍵交換)と暗号アルゴリズムネゴシエーションを行います。一般的に以下の流れです:バージョン交換 → KEXINIT(アルゴリズムリスト)→ 鍵交換(例:curve25519-sha256)→ サーバホスト鍵の提示と検証→ セッションキー確立。ホスト鍵の検証(known_hosts)によって MITM を防ぎます(RFC 4253 等)。
ハンドシェイクに関わるセキュリティ上の課題と攻撃例
中間者攻撃(MITM):証明書やホスト鍵の検証を省略すると暗号化されても通信を盗聴・改ざんされる可能性があります。信頼できる CA と正しい検証を行うことが必須です。
ダウングレード攻撃:クライアントとサーバが古い脆弱なプロトコルや弱い暗号にフォールバックされる手法。TLS では強制的に最新安全なバージョンを選ぶ設定や、TLS_FALLBACK_SCSV の導入が対策です。
SYN Flood(TCP):大量の不正 SYN を送りサーバのリソースを枯渇させる攻撃。SYN cookie、接続キューの拡張、レート制限で緩和します。
再生攻撃(TLS 0-RTT など):0-RTT は性能向上をもたらす反面、同一メッセージの再送(再生)に対する脆弱性があります。アプリケーション側で冪等性を担保するなどの対策が必要です。
パフォーマンスと最適化の観点
ハンドシェイクは往復遅延(RTT)を伴うため、接続確立に時間がかかります。特に TCP+TLS の組合せだと複数 RTT が重なることがあります。対策としては:
- TLS 1.3 の採用(RTT 削減、0-RTT の活用は注意を払う)
- セッション再開(session tickets / session IDs)によるハンドシェイク短縮
- TCP Fast Open の利用(対応環境で有効)
- 接続の再利用(HTTP/2, HTTP/3 のコネクション多重化)
- 地理的に近いエッジや CDN を使って RTT を減らす
運用・実装で押さえるべきベストプラクティス
- TLS は TLS 1.3 を優先し、TLS 1.2 は ECDHE を中心に安全な暗号スイートのみ有効化する(RC4、DES、3DES、NULL 暗号は無効化)。
- 証明書のライフサイクル管理を自動化する(Let's Encrypt + 自動更新など)。有効期限切れを防ぐことが最も基本的な可用性対策の一つ。
- OCSP ステープリングや CRL/OCSP を適切に用い、証明書失効情報をタイムリーに反映する。
- フォワードシークレシーを必須にする(ECDHE/DHE)ことで長期的な秘密流出に対する耐性を持たせる。
- サーバ設定は定期的にスキャン(testssl.sh、Qualys SSL Labs)して脆弱な設定を検出・修正する。
- エラーメッセージやログは攻撃者に情報を与えないよう注意しつつ、原因追跡に十分な情報を残す。
トラブルシューティングとデバッグツール
ハンドシェイクの問題を解析する際に有用なツールとチェックポイント:
- Wireshark / tcpdump:パケットレベルで SYN/TCP フラグ、TLS ハンドシェイクメッセージを解析。
- openssl s_client -connect host:port:TLS のネゴシエーション詳細、証明書チェーン、サポートするプロトコル/スイートの確認。
- curl -v/--trace:HTTP/HTTPS のやりとりとヘッダ確認。
- nmap --script ssl-enum-ciphers:サーバの暗号スイート列挙。
- sslyze、testssl.sh:脆弱性や設定ミスの自動診断。
まとめ(実践的な勧め)
ハンドシェイクは単なる「接続開始の儀式」ではなく、セキュリティと性能に直結する重要部分です。設計・運用では最新の安全なプロトコル(TLS 1.3 等)を採用し、古いプロトコルや弱い暗号の無効化、証明書管理の自動化、ログと監視の整備を行うことが基本です。また、パフォーマンスと安全性のトレードオフ(例:0-RTT の再生リスク)を理解して適切に取り扱うことが求められます。
参考文献
- RFC 793 - Transmission Control Protocol
- RFC 5246 - TLS 1.2
- RFC 8446 - TLS 1.3
- RFC 6455 - The WebSocket Protocol
- RFC 4253 - SSH Transport Layer Protocol
- OWASP(セキュリティ一般)
- MDN WebSocket ドキュメント
- Cloudflare - TLS 1.3 の解説(概要と利点)
- Qualys SSL Labs - Best Practices
- Let's Encrypt(証明書自動化)


