コンテンツへスキップ

HTTPS について

HTTPS は単に「有効」かどうかの問題だと考えがちです。

しかし、実際はそれよりもはるかに複雑です。

ヒント

お急ぎの場合や興味がない場合は、次のセクションに進み、さまざまな技術でHTTPSを設定するための手順を順を追って確認してください。

消費者視点でのHTTPS の基礎を学ぶには、https://howhttps.works/ を確認してください。

次に、開発者視点から、HTTPS を考える際に留意すべき点がいくつかあります。

  • HTTPS の場合、サーバー第三者によって生成された「証明書」を持っている必要があります。
    • これらの証明書は、実際には「生成」されるのではなく、第三者から取得されます。
  • 証明書には有効期間があります。
    • これらは期限切れになります。
    • そして、これらは更新され、第三者から再度取得される必要があります。
  • 接続の暗号化はTCP レベルで行われます。
    • これはHTTP の下のレイヤーです。
    • したがって、証明書と暗号化の処理はHTTP の前に行われます。
  • TCP は「ドメイン」を知りません。IP アドレスのみを知っています。
    • 要求された特定のドメインに関する情報はHTTP データに含まれます。
  • HTTPS 証明書特定のドメインを「証明」しますが、プロトコルと暗号化は、どのドメインが扱われているかを知る前に TCP レベルで発生します。
  • デフォルトでは、これはIP アドレスごとに 1 つの HTTPS 証明書しか持てないことを意味します。
    • サーバーの規模や、そこにある各アプリケーションの規模に関係なく。
    • ただし、これには解決策があります。
  • TLS プロトコル(HTTP の前に TCP レベルで暗号化を処理するプロトコル)には、SNI と呼ばれる拡張機能があります。
    • この SNI 拡張機能により、1 台のサーバー(1 つの IP アドレス)で複数の HTTPS 証明書を持ち、複数の HTTPS ドメイン/アプリケーションをサービスできます。
    • これには、サーバー上で動作し、パブリック IP アドレスでリッスンしている単一のコンポーネント(プログラム)が、サーバー内のすべての HTTPS 証明書を持っている必要があります。
  • セキュアな接続を確立した後も、通信プロトコルは依然として HTTP です。
    • コンテンツは暗号化されていますが、HTTP プロトコルで送信されています。

一般的には、サーバー (マシン、ホストなど) 上で1 つのプログラム/HTTP サーバーが動作し、すべての HTTPS 部分を管理します。つまり、暗号化された HTTPS リクエストを受信し、同じサーバーで動作している実際の HTTP アプリケーション (この場合はFastAPIアプリケーション) に復号化された HTTP リクエストを送信し、アプリケーションからのHTTP レスポンスを受け取り、適切なHTTPS 証明書を使用して暗号化し、HTTPSを使用してクライアントに送り返します。このサーバーはしばしばTLS 終端プロキシと呼ばれます。

TLS 終端プロキシとして使用できるオプションには、次のようなものがあります。

  • Traefik (証明書の更新も処理できます)
  • Caddy (証明書の更新も処理できます)
  • Nginx
  • HAProxy

Let's Encrypt

Let's Encrypt の登場以前は、これらのHTTPS 証明書は信頼できる第三者によって販売されていました。

これらの証明書を取得するプロセスは面倒で、かなりの書類作業が必要で、証明書はかなり高価でした。

しかし、その後Let's Encryptが誕生しました。

これは Linux Foundation のプロジェクトです。HTTPS 証明書を無料で、自動化された方法で提供しています。これらの証明書は、すべての標準的な暗号化セキュリティを使用しており、有効期間が短い(約3ヶ月)ため、有効期間が短いことによってセキュリティは実際に向上します

ドメインは安全に検証され、証明書は自動的に生成されます。これにより、これらの証明書の更新も自動化できます。

その目的は、これらの証明書の取得と更新を自動化し、安全な HTTPS を無料で永続的に提供することです。

開発者向け HTTPS

開発者にとって重要なアイデアに主に焦点を当てて、HTTPS API がどのように機能するかをステップバイステップで説明します。

ドメイン名

おそらく、まずドメイン名取得することから始めるでしょう。次に、DNS サーバー (おそらく同じクラウドプロバイダー) で設定します。

おそらくクラウドサーバー (仮想マシン) またはそれに類するものを取得し、それは固定のパブリック IP アドレスを持つでしょう。

DNS サーバーで、あなたのドメインサーバーのパブリック IP アドレスにポイントするレコード (「A レコード」) を設定します。

これはおそらく、初回セットアップ時に一度だけ行うでしょう。

ヒント

このドメイン名の部分は HTTPS のずっと前のものですが、すべてがドメインと IP アドレスに依存しているため、ここで言及する価値があります。

DNS

次に、実際の HTTPS のすべての部分に焦点を当てましょう。

まず、ブラウザはDNS サーバーに問い合わせて、このケースではsomeapp.example.comドメインの IP アドレスを確認します。

DNS サーバーは、特定のIP アドレスを使用するようにブラウザに伝えます。それは、DNS サーバーで設定したサーバーが使用するパブリック IP アドレスです。

TLS ハンドシェイクの開始

その後、ブラウザはその IP アドレスのポート 443 (HTTPS ポート) に通信します。

通信の最初の部分は、クライアントとサーバー間の接続を確立し、使用する暗号化キーなどを決定するだけです。

TLS 接続を確立するためのクライアントとサーバー間のこのやり取りは、TLS ハンドシェイクと呼ばれます。

SNI 拡張機能による TLS

サーバー内の1 つのプロセスのみが、特定のIP アドレスの特定のポートでリッスンできます。同じ IP アドレスの他のポートでリッスンしている他のプロセスが存在する可能性はありますが、IP アドレスとポートの組み合わせごとに 1 つだけです。

TLS (HTTPS) はデフォルトで特定のポート443を使用します。したがって、必要なポートはそれです。

このポートでリッスンできるのは 1 つのプロセスだけなので、それを行うプロセスはTLS 終端プロキシになります。

TLS 終端プロキシは、1 つ以上のTLS 証明書(HTTPS 証明書)にアクセスできます。

前述のSNI 拡張機能を使用して、TLS 終端プロキシは、利用可能な TLS (HTTPS) 証明書のうち、この接続に使用すべきものを確認し、クライアントが期待するドメインに一致する証明書を使用します。

この場合、someapp.example.comの証明書を使用します。

クライアントは、その TLS 証明書を生成したエンティティ(この場合は Let's Encrypt ですが、これについては後で説明します)をすでに信頼しているため、証明書が有効であることを検証できます。

その後、証明書を使用して、クライアントと TLS 終端プロキシは、残りのTCP 通信を暗号化する方法を決定します。これでTLS ハンドシェイクのフェーズが完了します。

この後、クライアントとサーバーは暗号化された TCP 接続を持ちます。これが TLS が提供するものです。そして、その接続を使用して実際のHTTP 通信を開始できます。

そして、それがHTTPSです。単なる純粋な (暗号化されていない) TCP 接続ではなく、セキュアな TLS 接続内の通常のHTTPです。

ヒント

通信の暗号化は HTTP レベルではなく、TCP レベルで行われることに注意してください。

HTTPS リクエスト

クライアントとサーバー (特にブラウザと TLS 終端プロキシ) が暗号化された TCP 接続を確立したので、HTTP 通信を開始できます。

そのため、クライアントはHTTPS リクエストを送信します。これは、暗号化された TLS 接続を介した単なる HTTP リクエストです。

リクエストの復号化

TLS 終端プロキシは、合意された暗号化を使用してリクエストを復号化し、平文 (復号化された) HTTP リクエストをアプリケーションを実行しているプロセス (例えば、FastAPI アプリケーションを実行している Uvicorn プロセス) に送信します。

HTTP レスポンス

アプリケーションはリクエストを処理し、平文 (暗号化されていない) HTTP レスポンスを TLS 終端プロキシに送信します。

HTTPS レスポンス

TLS 終端プロキシは、以前に合意された暗号化(someapp.example.com の証明書から始まったもの)を使用して応答を暗号化し、ブラウザに送り返します。

次に、ブラウザは応答が有効で、正しい暗号化キーなどで暗号化されていることを確認します。その後、応答を復号化して処理します。

クライアント (ブラウザ) は、以前にHTTPS 証明書を使用して合意した暗号化を使用しているため、応答が正しいサーバーからのものであることを認識します。

複数のアプリケーション

同じサーバー (または複数のサーバー) には、たとえば他の API プログラムやデータベースなど、複数のアプリケーションが存在する可能性があります。

特定の IP とポートを処理できるプロセスは 1 つだけですが (この例では TLS 終端プロキシ)、他のアプリケーション/プロセスも、同じパブリック IP とポートの組み合わせを使用しようとしない限り、サーバーで実行できます。

これにより、TLS 終端プロキシは複数のドメインの HTTPS と証明書を処理し、複数のアプリケーションに対して、各ケースで適切なアプリケーションにリクエストを転送できます。

証明書の更新

将来のある時点で、各証明書は期限切れになります(取得後約 3 ヶ月)。

そして、別のプログラム (場合によっては別のプログラム、場合によっては同じ TLS 終端プロキシ) が Let's Encrypt と通信し、証明書を更新します。

TLS 証明書は、IP アドレスではなく、ドメイン名に関連付けられています

したがって、証明書を更新するには、更新プログラムが、実際にそのドメインを「所有」し、管理していることを認証局 (Let's Encrypt) に証明する必要があります。

これを行うには、さまざまなアプリケーションのニーズに対応するために、いくつかの方法があります。一般的な方法をいくつか紹介します。

  • DNS レコードをいくつか変更する.
    • このため、更新プログラムは DNS プロバイダーの API をサポートする必要があります。したがって、使用している DNS プロバイダーによっては、これがオプションになる場合とそうでない場合があります。
  • ドメインに関連付けられたパブリック IP アドレスでサーバーとして実行する(少なくとも証明書取得プロセス中に)。
    • 上記のように、特定の IP とポートでリッスンできるプロセスは 1 つだけです。
    • これは、同じ TLS 終端プロキシが証明書更新プロセスも担当する場合に非常に役立つ理由の 1 つです。
    • そうしないと、TLS 終端プロキシを一時的に停止し、更新プログラムを開始して証明書を取得し、それを TLS 終端プロキシで設定してから、TLS 終端プロキシを再起動する必要がある場合があります。これは理想的ではありません。TLS 終端プロキシがオフになっている間、アプリが利用できなくなるためです。

アプリをサービスしながらこの更新プロセス全体を行うことは、アプリケーションサーバーと直接 TLS 証明書を使用する(例:Uvicorn)代わりに、TLS 終端プロキシを使用してHTTPS を処理する別のシステムを持つことを望む主な理由の 1 つです。

まとめ

HTTPS を持つことは非常に重要であり、ほとんどの場合、非常に重要です。開発者として HTTPS 周りに費やすほとんどの努力は、単にこれらの概念を理解し、それらがどのように機能するかを理解することだけです。

しかし、開発者向け HTTPSの基本的な情報を知っていれば、さまざまなツールを簡単に組み合わせて設定し、すべてをシンプルな方法で管理できます。

次の章のいくつかでは、FastAPIアプリケーションのHTTPSをセットアップするためのいくつかの具体的な例を紹介します。🔒