ネットワーク #4 - HTTP & HTTPS

Last Edited: 9/23/2024

このブログ記事ではHTTPとHTTPSについて紹介します。

DevOps

これまで、IPアドレスがどのように使われてお互いにメッセージを送信し、識別し、場所を特定し、ルーティングするか、 そしてTCPやUDPがアプリケーションに到達するために必要な情報をどのように添付し、通信に関するルールを確立するかを学びました。 今回の記事では、4層目のトランスポート層の上にあるレイヤーについて、データがどのように編成され、 TCPやUDPがどのように使用されるかを議論していきます。

HTTPのセマンティクス

ハイパーテキスト転送プロトコル(HTTP) は、クライアントとウェブサーバー間の通信を目的としたアプリケーション層プロトコルです。 データがどのように編成され、どのように通信が行われるべきかを指定します。

リクエストの形式
GET /index.html HTTP/1.0
Host: www.tkdev.blog
User-Agent: Mozilla/5.0
...

HTTPでは、リクエストが上記のような特定の形式に従う必要があると指定しています。GETはリクエスト内のメソッドの1つで、 クライアントがサーバーからリソースを取得したいことを示しています。他のメソッドとして、POSTPUTDELETEがあり、 それぞれクライアントがデータをサーバーに送信、サーバー上のデータを更新、または削除したいことを示します。

メソッドの隣にはリクエストのURLと、使用するHTTPのバージョンが指定されています。HostUser-AgentはHTTPヘッダーの一種で、 リクエストが送信されるホストとユーザーのデバイス情報を指定します。Content-TypeAuthorizationなどの他のヘッダーは、 GET以外のメソッドが使用される場合に関連します。また、GET以外のメソッドでは、リクエストボディにデータを含めることができ、 そのデータのタイプはContent-Typeによって(JSON、HTML、CSS、PNG、JPEGなど)指定されます。

レスポンスの形式
HTTP/1.0 200 OK
Access-Control-Allow-Origin: *
Content-Type: text/html; charset=utf-8
Date: Mon, 23 Sep 2024 00:00:00 GMT
...

HTTPでは、レスポンスが上記のような特定の形式に従う必要があるとも指定しています。レスポンスにはまず、 HTTPバージョン、ステータスコード、およびステータスメッセージが含まれます。ステータスコードには特定の意味が割り当てられており、 404は「見つかりません」、400は「不正なリクエスト」を示します。リクエストと同様に、 HTTPレスポンスにはContent-TypeAccess-Control-Allow-Originのようなヘッダーが含まれており、 ボディ内のデータのコンテンツタイプ(ボディが存在する場合)や、サーバーにアクセスすることが許可されているオリジンまたはドメインを伝えます。 (CORSまたはクロスオリジンリソースシェアリングのエラーは、ユーザーがリクエストを行っているオリジンまたはドメインが許可されていない場合に発生します。)

HTTP 1.0と1.1

HTTPバージョンに応じて、データの送信方法が異なります。最初の公開バージョンであるHTTP 1.0はTCP上に構築されていました。 各リクエストとレスポンスのペアごとに、HTTP 1.0はTCP接続を開いて閉じていました。これは、クライアントがウェブサーバーからHTML、 CSS、および画像を取得してウェブページを読み込むとき、各リソースのためにクライアントとサーバーが接続を確立し、 それを閉じる必要があることを意味します。

各リソースのためにTCP接続を閉じるのは非効率的であるため、HTTP 1.0は長く続きませんでした。代わりに、HTTP 1.1が登場し、 この非効率性を解決しました。HTTP 1.1はConnection: Keep-Aliveヘッダーを導入し、TCP接続を維持できるようにしました。 また、データをストリームとして送信できるようにし、すべてのリソースが送信されるのを待つ必要がなくなりました。

HTTP 2.0と3.0

さらなる改良が加えられたのがHTTP 2.0です。これにはデータ圧縮とマルチプレキシングが導入されました。 マルチプレキシングにより、複数のリクエストを1つにまとめて送信できるようになります。 また、HTTP 2.0ではProtocol Buffersのようなコンテンツタイプがサポートされており、こ れらはより軽量で高速です(今後の回で詳しく取り上げるかもしれません)。

HTTP 2.0までのすべてのバージョンはTCP上に構築されていましたが、TCPは前回の記事で説明したように信頼性がありますが、 UDPよりも遅くなる傾向があります。そのため、HTTP 3.0ではQUICという、UDP上に構築されたマルチプレキシングプロトコルを使用して、 より高速かつ信頼性のある通信を実現しています。現在、HTTP 1.1、2.0、および3.0はほとんどのウェブでサポートされています。

HTTPS

リクエストとレスポンスのフォーマット、およびさまざまなHTTPバージョンにおける通信のセットアップ方法を理解したので、 次はその通信をどうやってセキュリティで保護するかを考えましょう。具体的には、機密性(データが第三者に見られないこと)、 完全性(データが改ざんされていないこと)、および認証性(通信が正しいサーバーと行われていること)を確保したいと考えます。

これらを実現するために、Hypertext Transfer Protocol Secure (HTTPS)Transport Layer Security (TLS) を使用します。 TLSは対称鍵と非対称鍵の暗号化を使用しますが、それらの暗号化の詳細な仕組みはこの記事の範囲外です。参考として、 対称鍵暗号化では同じ鍵を使ってメッセージを暗号化し、復号します。一方、非対称鍵暗号化では暗号化と復号に異なる鍵を使用します。 対称鍵暗号化の方が一般的に高速なので、TLSはクライアントと正当なサーバーの間で対称鍵を安全に交換することを目指します。

TLS

対称鍵を安全に共有するために、クライアントはサーバーの公開鍵を使用して、クライアントが生成したランダムな数値を暗号化し、 それをサーバーに送信します。サーバーは唯一の秘密鍵を持っているため、サーバーだけがそのランダム数値を復号できます。 クライアントとサーバーの両方がランダム数値を持つと、それを暗号化して(両者で合意した方法で)新しい対称鍵を生成し、 機密性が確保できます。

しかし、これだけではサーバーが本物であることは保証されません。攻撃者はサーバーを装って偽の公開鍵をクライアントに送信することができます。 また、データが攻撃者によって改ざんされる可能性もあり、これでは完全性が保てません。この問題を解決するために、公開鍵、ドメイン、 およびその他のサーバーに関連する情報が1つにまとめられ、信頼された認証局(CA)に送られます。CAはサーバーの身元を確認し、 その情報にデジタル署名を付けてTLS証明書を作成します。(サーバーがCAに対して署名付きデジタルメッセージの承認を要求することを証明書署名要求(CSR)と呼びます。)

デジタル署名

CAは、メッセージをハッシュ化して(任意の文字列からランダムな固定サイズの文字列を生成すること)、デジタル署名を作成します。 このハッシュ化の詳細についてはこの記事では取り扱いません。CAはその後、ハッシュを自分の秘密鍵で暗号化し、 その結果得られた文字列をメッセージに付けてデジタル署名とします。これを使用してクライアントがサーバーの身元を確認するためのTLS証明書が作成されます。

サーバーは事前にCAにCSRを提出して証明書を取得しているため、公開鍵単独ではなく証明書をクライアントに送信します。 クライアントは証明書を受け取り、CAの公開鍵を使用してデジタル署名を復号します。 (CAの情報と公開鍵はメッセージに含まれており、多くのブラウザやOSにはすでに信頼されたCAの公開鍵が保存されています。)クライアントは、 CAが使用したのと同じハッシュアルゴリズムを使用して元のメッセージをハッシュ化し、復号されたデジタル署名と比較します。 もし一致すれば、そのメッセージが改ざんされておらず(ハッシュは完全に一致した入力でなければ同じ値を生成しないため)、 さらにそのメッセージをCAが本当に認証した(秘密鍵は非公開なので)ことが確認され、完全性と認証性が確保できます。

TLSの続き

クライアントが認証性と完全性を確認すると、ランダム数値premature secretを生成し、サーバーの公開鍵で暗号化して送信します。 サーバーは唯一の秘密鍵を持っているため、他の誰もそのpremature secretを復号できません(機密性を確保)。その後、 クライアントとサーバーの両方はpremature secret、および合意した暗号化アルゴリズムを使用して対称鍵を生成し、 互いに対称鍵の生成が完了したことを伝えて、通信の準備が整ったことを確認します。この一連のプロセスを図で説明します。

TLS

CSRが事前に行われているため、リアルタイムで行われる通信は、暗号化アルゴリズム、ランダム数、およびpremature secretの交換だけです。 このプロセスはTLSハンドシェイクと呼ばれ、すべてのHTTPバージョン(HTTP 3.0はUDPを使用)で、 TCPハンドシェイクの直後に行われます。(多くの詳細は抽象化されており、TLSのバージョンによって実装が異なることも留意してください。)

プロトコルスタック

これまでの記事で、OSIモデルの下位から上位までのさまざまなプロトコルについて主にウェブに関連して議論してきました。 議論をまとめると、ウェブで使用されるプロトコルスタックを以下の図で示すことができます。

Protocols

抽象化や略語が多いので、理解するまで何度か読み返し、他のリソースも参考にすることをお勧めします。

リソース