Closed4

AWS ALBをSSLの終端にしたときに Strict Transport Security ヘッダーが付与されない

ishiyamaishiyama

現在クラウドリフトの作業をしていて、ECS(またはEC2)の前段にALBを配置し、ALBをSSLの終端としている。

これはAWSでパブリックなアプリケーションを作成する際によく取られる構成だが、HTTP Strict Transport Security(HSTS)は仕様上HTTPSの経路でのみレスポンスに付与される。
この仕様により、ALBをSSLの終端に設定するとレスポンスにHSTSが付与されない。
この問題を解決するためにはECSに乗せているアプリケーション上で、ALBに到達した際のプロトコルを見るように修正する必要があり、その元のプロトコルがX-Forwarded-Proto (XFP) に入ってくる。
この対応を行う上で調べた内容をメモしておく。

ishiyamaishiyama

HTTP Strict Transport Security とは

ウェブサイトとブラウザ間の通信をHTTPS(安全な接続)のみに制限するレスポンスヘッダーです。

Strict-Transport-Security: max-age=<expire-time>

通常のHTTPからHTTPSへのリダイレクトと異なり、HSTSはブラウザが最初から安全な接続を使用するよう強制します。

解りずらいですが、HTTP接続を通じてStrict-Transport-Securityヘッダーを送信したとしても、ブラウザはそれを無視するという仕様があります。

それに則り一部のフレームワークで、HSTSを付与しようとしても、HTTP通信の場合、それが無視されます。

ishiyamaishiyama

これを回避するために、アプリケーション側に

「これはALBを経由してるからHTTPでリクエストされてるけど、エンドユーザーからのリクエストはHTTPSで行われているよ」

と教えてあげる必要があります。

ALBはバックエンドに対して以下のリクエストヘッダーを付与します。

  • X-Forwarded-For(LBが受け取ったIP)
  • X-Forwarded-Proto(LBとの接続に使われたプロトコル)
  • X-Forwarded-Port(LBとの接続に使われたポート)

元の通信がHTTPSかは「X-Forwarded-Proto」を見ればわかるので、これの値が正しいプロトコルであるとフレームワークに伝えます。

ishiyamaishiyama

.NET(C#)の場合はこうします。

namespace SampleWebApp
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            // 省略..
            
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders
                    = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost;
                    
                // デフォルトではループバックプロキシのみが許可されているので、すべてのリバースプロキシを許可
                options.KnownNetworks.Clear();
                options.KnownProxies.Clear();
            });

            // 省略..
        }

        public void Configure(IApplicationBuilder app)
        {
            // 省略..
            
            app.UseForwardedHeaders(); // UseHstsの前に呼び出す必要がある
            app.UseHsts();
            
            // 省略..
        }
    }
}
このスクラップは2023/06/14にクローズされました