AWS ALBをSSLの終端にしたときに Strict Transport Security ヘッダーが付与されない
現在クラウドリフトの作業をしていて、ECS(またはEC2)の前段にALBを配置し、ALBをSSLの終端としている。
これはAWSでパブリックなアプリケーションを作成する際によく取られる構成だが、HTTP Strict Transport Security(HSTS)は仕様上HTTPSの経路でのみレスポンスに付与される。
この仕様により、ALBをSSLの終端に設定するとレスポンスにHSTSが付与されない。
この問題を解決するためにはECSに乗せているアプリケーション上で、ALBに到達した際のプロトコルを見るように修正する必要があり、その元のプロトコルがX-Forwarded-Proto (XFP) に入ってくる。
この対応を行う上で調べた内容をメモしておく。
HTTP Strict Transport Security とは
ウェブサイトとブラウザ間の通信をHTTPS(安全な接続)のみに制限するレスポンスヘッダーです。
Strict-Transport-Security: max-age=<expire-time>
通常のHTTPからHTTPSへのリダイレクトと異なり、HSTSはブラウザが最初から安全な接続を使用するよう強制します。
解りずらいですが、HTTP接続を通じてStrict-Transport-Securityヘッダーを送信したとしても、ブラウザはそれを無視するという仕様があります。
それに則り一部のフレームワークで、HSTSを付与しようとしても、HTTP通信の場合、それが無視されます。
これを回避するために、アプリケーション側に
「これはALBを経由してるからHTTPでリクエストされてるけど、エンドユーザーからのリクエストはHTTPSで行われているよ」
と教えてあげる必要があります。
ALBはバックエンドに対して以下のリクエストヘッダーを付与します。
- X-Forwarded-For(LBが受け取ったIP)
- X-Forwarded-Proto(LBとの接続に使われたプロトコル)
- X-Forwarded-Port(LBとの接続に使われたポート)
元の通信がHTTPSかは「X-Forwarded-Proto」を見ればわかるので、これの値が正しいプロトコルであるとフレームワークに伝えます。
.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();
// 省略..
}
}
}