こんにちは、AWSを使ったインフラ構築・運用を担当している大久保です。

今回は、HSTSについて調査・検証した内容と、ALBとEC2を使ったWebサイト環境での設定方法について話していきます。

HSTSとは?


HSTSとはHTTP Strict Transport Securityの略で、クライアントとサーバー間の通信をHTTPSに強制する仕組みです。
サーバーがStrict-Transport-Securityヘッダーを送信し、受け取ったクライアント(ブラウザなど)側は以降の通信を必ずHTTPSで行うようになります。

上図のように、サーバー側からStrict-Transport-Securityヘッダーを1度受け取ったクライアントは、ユーザー側でhttp://を指定されてもhttps://に変換して通信を行ってくれます。
この時HTTPステータスコードは307 Internal Redirectとなり、サーバー側でのリダイレクトでなくクライアント側でリダイレクトしているような動きになります。

またRFCに「HTTP経由で送信されるStrict-Transport-Securityヘッダーは無効となる」というような記載があります。
実際に試してみたところ、HTTP通信時に渡されたStrict-Transport-Securityヘッダーは利用されず、それ以降の通信がHTTPSに強制されることはありませんでした。

An HSTS Host MUST NOT include the STS header field in HTTP responses conveyed over non-secure transport.

7.2. HTTP Request Type(2024/10/28時点)

If an HTTP response is received over insecure transport, the UA MUST ignore any present STS header field(s).

8.1. Strict-Transport-Security Response Header Field Processing(2024/10/28時点)

HSTSプリロードとは?


サーバー側でStrict-Transport-Securityヘッダーを付与するだけだと、初回アクセス時はクライアント側でStrict-Transport-Securityヘッダーを持っていないので、HSTSが効かないという問題が発生します。

これを解決できるのがHSTSプリロードです。
HSTSプリロードとは、HSTSプリロードリスト(HSTSが有効になっているドメインリスト)をクライアント側で事前に読み込んでおき、初回アクセスからHSTS利用してHTTPS通信を強制することができる仕組みです。

HSTSプリロードリストにドメインを登録するには以下の条件を満たしている状態で、https://hstspreload.org/から申請を行う必要があります。

  1. 有効な証明書を利用している。
  2. ポート 80 でリッスンしている場合、 HTTP から HTTPS にリダイレクトさせている。
  3. すべてのサブドメインでHTTPS接続できる状態にしている。
  4. Strict-Transport-Securityヘッダーを設定している。
    • max-age31536000秒(1年)以上に設定している。
    • includeSubDomainsを設定している。
    • preloadを設定している。
    • HTTPS サイトから追加のリダイレクトを提供する場合、そのリダイレクトには HSTS ヘッダー (リダイレクト先のページではなく) が含まれている。

気になる方は、Submission RequirementsDeployment Recommendationsの内容を確認してみてください。

※HSTSプリロードリストはブラウザのソースコードにハードコードされて利用されるものらしく、申請してから実際に反映されるまでに時間がかかるみたいです。

ALB+EC2(apache)環境での設定方法


では、ALBとEC2を利用している環境でどうやって設定すればいいか?
そんなに難しくなく、以下のことをすれば設定できます。

  1. ALBで80ポートのリスナーを作成し、強制的にHTTPS:443にリダイレクトさせる。
  2. EC2のapacheの設定ファイルで、Strict-Transport-Securityヘッダーを付与する設定を追加する。

※ 今回はHSTSプリロードリストへの登録までは行なわないので、apacheの設定は最低限にしています。

ALBのリスナーの設定

まずALBのリスナーの設定です。

以下の設定で、HTTP:80のリスナーを作成します。

  • リスナーの設定
    • プロトコル
      • HTTP
    • ポート
      • 80
  • デフォルトアクション
    • アクションのルーティング
      • URLにリダイレクト
    • URLにリダイレクト
      • URL部分
    • プロトコル
      • HTTPS
    • ポート
      • 443
    • ステータスコード
      • 301 - 完全に移動されました

Apacheの設定

次にApacheの設定です。

今回はubuntuを利用しているので、/etc/apache2/apache2.confに以下の設定を追記します。

Header always set Strict-Transport-Security "max-age=31536000"
設定説明
Header always set常に指定したヘッダーをHTTPレスポンスに追加する。
Strict-Transport-Security追加するヘッダー名。
ヘッダー名をStrict-Transport-Securityに設定。
"max-age=31536000"追加するヘッダーのパラメーター。
HSTSの有効期間を365日に設定。

※apacheのメインファイルに設定を追加していますが、vhostごとに設定したい場合はそれぞれのvhostの<VirtualHost>ディレクティブ内に設定を追記してください。

ヘッダーを付与するためにApacheのheadersモジュールを有効化し、Apacheを再起動します。

sudo a2enmod headers
sudo systemctl restart apache2

HSTSの確認

ブラウザの開発者ツールを起動した状態でHSTSの設定を行ったサイトにアクセスし、レスポンスヘッダーにStrict-Transport-Securityヘッダーが付与されているか確認します。

次に、chrome://net-internals/#hstsにアクセスし、Query HSTS/PKP domainの検索欄にアクセスしたドメインを入力してQueryをクリックします。
結果がFoundになっていればOKです。

最後に、HSTSによって本当にHTTP通信がHTTPS通信に変わるか確認します。

ブラウザの開発者ツールを起動した状態でHSTSの設定を行ったサイトにhttp://でアクセスします。
レスポンスで、HTTPステータスコードが307 Internal Redirect、ヘッダーにnon-authoritative-reason: HSTSがあればHSTSによるリダイレクトが成功してます。

ALBとEC2間がHTTP通信だけどいいの?


ALBとEC2を使った構成の場合、Route53でドメインを取得・ACMで証明書を取得し、ALBをSSL終端にすることが多いと思います。
この場合、クライアントとALB間はHTTPS:443で通信しますが、ALBとEC2間はHTTP:80で通信することになります。

ALBとEC2間の通信がHTTP:80通信のため、冒頭で記載した「HTTP経由で送信されるStrict-Transport-Securityヘッダーは無効」という仕様に抵触し、Strict-Transport-Securityヘッダーがクライアントで利用されないのでは?と思いましたが、そうはなりませんでした。

結果からの予想ですが、「HTTP通信時は無視される」というのは「クライアントへのレスポンスがHTTP:80通信だった場合、クライアントはStrict-Transport-Securityヘッダーを無視する」ということだと思います。

まとめ


今回の調査で、HSTSの設定方法について記載しました。
個人的にはALBの80ポートリスナーで、HTTPS:443への強制リダイレクト入れていればHSTSの設定まで入れなくもいいのかな?とも思いました。
とはいえ、セキュリティは強化しておくに越したことはないので、設定しておくのが無難です。

この情報が誰か助けになれば幸いです。

参考にしたもの


By okubo

主にAWS上でのインフラ構築を担当してます。 ・AWS Certified Solutions Architect - Professional ・AWS Certified DevOps Engineer - Professional ・AWS Certified Database - Specialty ・AWS Certified Security - Specialty