はじめに
通信の暗号化のためにHTTPSは今や当たり前のように使われていますが、インフラエンジニアであってもその仕組みを深く理解していないケースは少なくありません。特に最近ではTLS1.3が普及し、従来のバージョンからハンドシェイクや暗号スイートの仕組みが大きく変わっています。
本記事ではWiresharkを用いたパケットキャプチャ を通じて、TLS1.3における通信の流れを具体的に確認します。これにより、HTTPS 通信の仕組みを従来よりも深く理解できるはずです。ぜひ読み進めてみてください。
TLSによるHTTPS通信の概要
HTTPS(Hyper Text Transfer Protocol Secure)は、HTTP通信をTLS(Transport Layer Security)によって保護する仕組みです。かつてはSSLが用いられていましたが、脆弱性が発見されたため、現在はTLSが標準となっています。
TLSを利用したHTTPS通信により、次の3つのセキュリティ機能が実現されます。
- 暗号化(Confidentiality)
通信データを暗号化することで、第三者が盗み見ても内容を理解できません。たとえば、ユーザが入力したパスワードやクレジットカード情報を安全に送信できます。 - 改ざん防止(Integrity)
通信データが途中で書き換えられていないかを検証します。TLSではMAC(メッセージ認証コード)やAEAD暗号(AES-GCMなど)によって、1ビットでも改ざんがあれば検出して破棄します。 - 認証(Authentication)
サーバ証明書を利用して「接続先が正しいWebサイトか」を確認できます。これによりフィッシング対策になります。また、クライアント証明書を導入すれば、特定の利用者だけにアクセスを許可することも可能です。
参考サイト:What is HTTPS? Understanding Network Protocols by WireX
※OSI参照モデルにおいてHTTPSはアプリケーション層、TLSはセッション層やプレゼンテーション層の役割を担うプロトコルと位置づけられることが多いです。
TLS1.3におけるHTTPS通信フロー
TLS1.3におけるHTTPS通信のフローを見ていきましょう。下図のように、TCPスリーウェイハンドシェイクとTLSハンドシェイクで接続を確立した後、暗号化された通信が行われます。詳細を順を追ってみていきましょう。

TCPスリーウェイハンドシェイク
TLSによるHTTPS通信において、まずはTCPスリーウェイハンドシェイクによって接続を確立します。
クライアントとサーバはSYN、SYN/ACK、ACKをやり取りして通信路を確立します。

パケットキャプチャを使って具体的な通信を確認してみましょう。tcp.stream でフィルタをかけると、SYN、SYN/ACK、ACK の順にパケットがやり取りされており、TCP のスリーウェイハンドシェイクが正常に確立されていることが確認できます。

TLSハンドシェイク
TLSハンドシェイクにて、暗号化の鍵交換、暗号方式の決定、サーバ認証などの処理が行われます。詳細にご説明します。

Client Hello
TLSハンドシェイクにおいて、クライアントからサーバに最初に送信されるハンドシェイクメッセージです。ここでは、クライアントが対応可能な暗号スイート、署名アルゴリズム、TLSバージョンなどをサーバに通知します。これにより、サーバはクライアントの提示した候補の中から適切な方式を選択することが可能です。また、鍵共有のための公開鍵も送付します。

クライアントからサーバに送付されるClient Helloに含まれる主な情報を記載します。
Cipher Suites
利用可能な暗号スイート一覧を送付します。サーバ側はこの一覧から暗号スイートを選択します。

signature_algorithms
サーバ証明書の署名検証やハンドシェイクで使える署名アルゴリズムを列挙した情報を送付します。

supported_versions
クライアントがサポートしているTLSバージョンの一覧をサーバに伝えます。本例ではTLS1.3とTLS1.2をサポートしていることがわかります。

key_share
鍵共有のためにクライアントが送信する公開鍵を送信します。

Server Hello
サーバが受け取った ClientHello の内容をもとに、サーバ側で選択した暗号スイート、TLSのバージョンをクライアント側に通知するメッセージです。

サーバからクライアントに送付されるServer Helloに含まれる主な情報を記載します。
Cipher Suites
サーバが選択した暗号スイートの情報をを送付します。本例ではTLS_AES_256_GCM_SHA384が選択されていることがわかります。

supported_versions
サーバが選択したTLSバージョン情報をサーバに伝えます。本例ではTLS1.3が選択されています。

key_share
鍵共有のためにサーバ側の公開鍵情報を送信します。

Certificate, Certificate Verify, Finished
サーバからクライアントに対して、証明書チェーン(サーバ証明書、中間CA証明書(必要に応じて))、証明書に対する署名し、TLSハンドシェイクの完了を通知します。
Certificate
Webサイトを構築しているサーバの信頼性を証明するために証明書を送付します。本例では、サーバ証明書と中間CA証明書の2つが送付されています。それぞれ見てみましょう。

サーバ証明書
まず、ひとつめのサーバ証明書に記載されている主要な情報を説明します。

・バージョン(version)
X.509(公開鍵証明書の標準規格)のバージョンが記載されています。現在はv3が使われることがほとんどです。
・シリアル番号(serialNumber)
証明書を一意に識別する番号となります。CAによって管理されています。
・署名アルゴリズム(signature)
CAの秘密鍵で証明書が署名される際に指定された署名アルゴリズムとなります。本例では「ecdsa-with-SHA384」が選択されてます。
・発行者(issuer)
証明書の発行者の情報が記載されています。本例では、id-at-organizationNameにあるとおり「Let’s Encrypt」によって発行されていることが確認できます。
・有効期間(validity)
証明書の有効期限が記載されています。notAfterが有効期限切れの期日であるため、この期日までに証明書の更新が必要です。本例では期限が「2025-09-30 07:34:12 (UTC)」となっています。
・サブジェクト(subject)
証明書の所有者に関する情報が記載されています。本例ではドメイン名であるCN=quiz.eeengineer.comが指定されています。
・公開鍵情報(subjectPublicKeyInfo)
証明書内に含まれる公開鍵の情報が記載されています。本鍵を用いることで暗号化通信におけるサーバ認証や鍵交換が実現されます。
中間CA証明書
続いて、ふたつめの中間CA証明書に記載されている主要な情報を説明します。

・バージョン(version)
サーバ証明書と同様、X.509のv3が使われることがわかります。
・シリアル番号(serialNumber)
証明書を一意に識別する番号が記載されています。
・署名アルゴリズム(signature)
署名アルゴリズムが記載されています。本例ではサーバ証明書のアルゴリズムとは異なり、「sha256WithRSAEncryption」が選択されていることがわかります。
・発行者(issuer)
証明書の発行者の情報が記載されています。本例では、id-at-organizationNameよりInternet Security Research Groupが発行組織であることがわかります。こちらはLet’s Encryptを運営している非営利団体となります。また、id-at-commonNameに記載されているISRG Root X1は、Let’s Encryptが発行しているルート認証局のひとつとなります。
・有効期間(validity)
証明書の有効期限が記載されています。
・サブジェクト(subject)
証明書の所有者に関する情報が記載されています。本例では、id-at-commonName=E6となっておりまして、こちらは中間CA証明書の名称を表しています。
・公開鍵情報(subjectPublicKeyInfo)
サーバ証明書と同様、証明書内に含まれる公開鍵の情報が記載されています。
※中間CA証明書が何なのか正確に理解できていない方は、下記を参考にしてください。
初心者でもできる!OpenSSLでプライベートCAと中間CAを構築しサーバ証明書を発行する方法 –
※TLS1.3では、この通信データも暗号化されています。そのままでは Wireshark 上でパケット内容を確認できないため、セッションキーを取得して Wireshark に設定してください。詳しい手順は、下記記事をご参照ください。
【初心者向け】Wireshark(パケットキャプチャ)で暗号化されたTLS/HTTPS通信を復号化する方法 | TLS1.3対応 –
Certificate Verify
自身が提示した証明書に対応する秘密鍵を確かに保持していることサーバが示すために、これまでのハンドシェイクメッセージに基づくデータへ署名し、送信します。クライアント側は証明書の公開鍵を使ってこの署名を検証することで、提示された証明書が正当なものであり、秘密鍵を保持していることを確認できます。

・Signature
署名の字一体となります。これまでのハンドシェイクメッセージ(ClientHello、ServerHello、Certificateなど)をまとめてハッシュ化したデータに対する署名となります。
Finished
いままでのハンドシェイクの内容全体が改ざんされていないことを検証する最後のやりとりです。

・Verify Data
これまでのハンドシェイク全体のやり取りを入力データとし、Finished keyという鍵を使って HMAC(秘密鍵つきのハッシュ)を計算した結果が格納されています。クライアントとサーバはこの値を照合することで、通信内容が改ざんされていないこと、そして双方が同じ鍵を共有できていることを確認します。
Finished
Finishedを受け取ったクライアントからもFinishedを応答します。

クライアント側でもVefify Dataの値を同じように算出し、サーバから送付されてくる値と一致すれば、TLSハンドシェイクが完了です。以降はアプリケーション通信のデータがやり取りされることになります。

・Verify Data
サーバから送付されてくるデータと同じ値が入ります。
さいごに
以上が、HTTPS通信の仕組みとTLS1.3における通信の流れの解説です。実際にパケットキャプチャを確認しながら手を動かすことで、TLSのハンドシェイクや暗号化の仕組みがより具体的に理解できるようになります。ぜひWiresharkなどのツールを使い、ご自身の環境でHTTPS通信を解析してみてください。実際のデータを目で追うことが、理解を深める一番の近道です。
TLS1.3の挙動はRFC 8446にて記載されていますので、興味がわいた方は下記を参考にさらに調べてみて下さい。
RFC 8446 – The Transport Layer Security (TLS) Protocol Version 1.3


コメント