プロキシ サーバーとロード バランサーを使用するために ASP.NET Core を構成する
Note
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
作成者: Chris Ross
ASP.NET Core の推奨される構成では、アプリは IIS の ASP.NET Core モジュール (ANCM)、Nginx、または Apache を使ってホストされます。 プロキシ サーバー、ロード バランサー、および他のネットワーク アプライアンスにより、要求に関する情報が、アプリに到達する前にわからなくなることがよくあります。
- HTTPS 要求が HTTP によってプロキシされると、元のスキーム (HTTPS) は失われ、ヘッダーで転送される必要があります。
- アプリは、インターネット上または社内ネットワーク上の本来の送信元ではなく、プロキシから要求を受信するため、送信元クライアントの IP アドレスもヘッダーで転送される必要があります。
この情報は、リダイレクト、認証、リンクの生成、ポリシーの評価、クライアントの位置情報など、要求の処理で重要になる可能性があります。
Web ファームでの実行を意図したアプリは、「Web ファームでの ASP.NET Core のホスト」を参考にしてください。
転送されるヘッダー
慣例によりは、プロキシは HTTP ヘッダーで情報を転送します。
Header | 説明 |
---|---|
X-Forwarded-For (XFF) |
要求を開始したクライアントと、プロキシ チェーン内の後続のプロキシに関する情報を保持します。 このパラメーターには、IP アドレス (および、必要に応じてポート番号) を含めることができます。 プロキシ サーバーのチェーンにおいては、最初のパラメーターが、要求を最初に行ったクライアントを示します。 その後に、後続のプロキシの識別子が指定されています。 チェーン内の最後のプロキシは、パラメーターのリストには含まれません。 最後のプロキシの IP アドレスとオプションのポート番号は、トランスポート層のリモート IP アドレスとして入手できます。 |
X-Forwarded-Proto (XFP) |
開始スキーム (HTTP または HTTPS) の値です。 要求が複数のプロキシを通過している場合、値はスキームのリストである場合もあります。 |
X-Forwarded-Host (XFH) |
ホスト ヘッダー フィールドの元の値です。 通常、プロキシはホスト ヘッダーを変更しません。 プロキシにおいてホスト ヘッダーが既知の適切な値であることが検証されない、または既知の適切な値に制限されないシステムに影響を与える、特権の昇格脆弱性については、マイクロソフト セキュリティ アドバイザリ CVE-2018-0787 をご覧ください。 |
X-Forwarded-Prefix |
クライアントによって要求された元のベース パス。 このヘッダーは、アプリケーションが URL、リダイレクト、またはクライアントへのリンクバックを正しく生成するのに役立ちます。 |
Forwarded Headers Middleware (ForwardedHeadersMiddleware) によって、これらのヘッダーが読み取られ、HttpContext 上の関連するフィールドに入力されます。
ミドルウェアの更新:
HttpContext.Connection.RemoteIpAddress
:X-Forwarded-For
ヘッダー値を使用して設定します。 追加の設定は、ミドルウェアがRemoteIpAddress
を設定する方法に影響を与えます。 詳しくは、「Forwarded Headers Middleware のオプション」をご覧ください。 使われた値はX-Forwarded-For
から削除され、HttpContext.Connection.RemoteIpAddress
の古い値はX-Original-For
に保持されています。 注: このプロセスは、X-Forwarded-For/Proto/Host/Prefix
に複数の値がある場合に複数回繰り返され、元のRemoteIpAddress/Host/Scheme/PathBase
を含む複数の値がX-Original-*
に移動される場合があります。HttpContext.Request.Scheme
:X-Forwarded-Proto
ヘッダー値を使用して設定します。 使われた値はX-Forwarded-Proto
から削除され、HttpContext.Request.Scheme
の古い値はX-Original-Proto
に保持されています。HttpContext.Request.Host
:X-Forwarded-Host
ヘッダー値を使用して設定します。 使われた値はX-Forwarded-Host
から削除され、HttpContext.Request.Host
の古い値はX-Original-Host
に保持されています。HttpContext.Request.PathBase
:X-Forwarded-Prefix
ヘッダー値を使用して設定します。 使われた値はX-Forwarded-Prefix
から削除され、HttpContext.Request.PathBase
の古い値はX-Original-Prefix
に保持されています。
上記に関する詳細については、こちらの GitHub イシューを参照してください。
Forwarded Headers Middleware の既定の設定は構成できます。 既定の設定の場合:
- アプリと要求のソースの間には、"1 つのプロキシ" だけが存在します。
- 既知のプロキシと既知のネットワークに対しては、ループバック アドレスのみが構成されています。
- 転送されるヘッダーには
X-Forwarded-For
、X-Forwarded-Proto
、X-Forwarded-Host
、X-Forwarded-Prefix
の名前が付けられます。 ForwardedHeaders
の値はForwardedHeaders.None
です。ミドルウェアを有効にするには、目的のフォワーダーをここで設定する必要があります。
すべてのネットワーク アプライアンスが追加構成なしで X-Forwarded-For
および X-Forwarded-Proto
ヘッダーを追加するわけではありません。 プロキシされた要求がアプリに届いたときにこれらのヘッダーが含まれていない場合は、アプライアンスの製造元のガイダンスを参照してください。 アプライアンスが X-Forwarded-For
と X-Forwarded-Proto
以外の名前を使用している場合は、アプライアンスで使用されるヘッダー名と一致するように ForwardedForHeaderName と ForwardedProtoHeaderName のオプションを設定してください。 詳細については、「Forwarded Headers Middleware のオプション」と「別のヘッダー名を使用するプロキシの構成」を参照してください。
IIS/IIS Express と ASP.NET Core モジュール
アプリが IIS と IIS の ASP.NET Core モジュール (ANCM) の背後でアウト プロセスでホストされている場合、IIS Integration Middleware によって Forwarded Headers Middleware が既定で有効にされます。 Forwarded Headers Middleware は、アクティブ化されると、ASP.NET Core モジュールに固有の制限された構成を使って、ミドルウェア パイプライン内で最初に実行されます。 制限された構成は、転送されるヘッダーの信頼に関する問題 (たとえば、IP スプーフィング) に起因します。 ミドルウェアは、X-Forwarded-For
および X-Forwarded-Proto
ヘッダーを転送するように構成され、単一の localhost プロキシに制限されます。 追加の構成が必要な場合は、「Forwarded Headers Middleware のオプション」をご覧ください。
プロキシ サーバーとロード バランサーの他のシナリオ
アウト プロセスでホストされている場合に IIS 統合が使われていない場合は、Forwarded Headers Middleware は既定で有効になりません。 UseForwardedHeaders を含む転送されたヘッダーをアプリで処理するためには、Forwarded Headers Middleware を有効にする必要があります。 ミドルウェアを有効にした後、ミドルウェアに対して ForwardedHeadersOptions が指定されていない場合の既定の ForwardedHeadersOptions は ForwardedHeaders.None です。
ForwardedHeadersOptions でミドルウェアを構成して、X-Forwarded-For
および X-Forwarded-Proto
ヘッダーを転送します。
Forwarded Headers Middleware の順序
Forwarded Headers Middleware は、他のミドルウェアの前に実行する必要があります。 この順序により、転送されるヘッダー情報に依存するミドルウェアが処理にヘッダー値を使用できます。 Forwarded Headers Middleware は、診断とエラー処理の後に実行できますが、UseHsts を呼び出す前に実行する必要があります。
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseForwardedHeaders();
app.UseHsts();
}
else
{
app.UseDeveloperExceptionPage();
app.UseForwardedHeaders();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
または、診断の前に UseForwardedHeaders
を呼び出します。
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Note
ForwardedHeadersOptions が指定されていない場合、または UseForwardedHeaders を使って拡張メソッドに直接適用されていない場合、転送される既定のヘッダーは ForwardedHeadersOptions です。 転送するヘッダーで ForwardedHeaders プロパティが構成されている必要があります。
Nginx の構成
X-Forwarded-For
および X-Forwarded-Proto
ヘッダーを転送する方法については、「X-Forwarded-For
」を参照してください。 詳細については、「NGINX:Using the Forwarded header」 (NGINX: 転送されるヘッダーの使用) を参照してください。
Apache の構成
X-Forwarded-For
は、自動的に追加されます。 詳細については、Apache モジュール mod_proxy のリバース プロキシ要求ヘッダーに関するページを参照してください。
Forwarded Headers Middleware のオプション
ForwardedHeadersOptions は、ForwardedHeadersOptions の動作を制御します。 既定の値の変更例を次に示します。
- 転送されるヘッダー内のエントリの数を
2
に制限します。 127.0.10.1
の既知のプロキシ アドレスを追加します。- 転送されるヘッダーの名前を既定の
X-Forwarded-For
からX-Forwarded-For-My-Custom-Header-Name
に変更します。
using System.Net;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardLimit = 2;
options.KnownProxies.Add(IPAddress.Parse("127.0.10.1"));
options.ForwardedForHeaderName = "X-Forwarded-For-My-Custom-Header-Name";
});
var app = builder.Build();
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
オプション | 説明 |
---|---|
AllowedHosts | X-Forwarded-Host ヘッダーによるホストを指定した値に制限します。
IList<string> です。 |
ForwardedForHeaderName | ForwardedHeadersDefaults.XForwardedForHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使います。 このオプションは、プロキシ/フォワーダーが X-Forwarded-For ヘッダーを使用していないが、情報の転送のためにその他のヘッダーを使用している場合に使用されます。既定値は、 X-Forwarded-For です。 |
ForwardedHeaders | 処理する必要があるフォワーダーを識別します。 適用されるフィールドの一覧については、「ForwardedHeaders Enum」(ForwardedHeaders 列挙型) をご覧ください。 このプロパティに割り当てられる標準値は、ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto です。既定値は ForwardedHeaders.None です。 |
ForwardedHostHeaderName | ForwardedHeadersDefaults.XForwardedHostHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使います。 このオプションは、プロキシ/フォワーダーが X-Forwarded-Host ヘッダーを使用していないが、情報の転送のためにその他のヘッダーを使用している場合に使用されます。既定値は、 X-Forwarded-Host です。 |
ForwardedProtoHeaderName | ForwardedHeadersDefaults.XForwardedProtoHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使います。 このオプションは、プロキシ/フォワーダーが X-Forwarded-Proto ヘッダーを使用していないが、情報の転送のためにその他のヘッダーを使用している場合に使用されます。既定値は、 X-Forwarded-Proto です。 |
ForwardLimit | 処理されるヘッダー内のエントリの数を制限します。 制限を無効にするには null に設定しますが、これは KnownProxies または KnownNetworks が構成されている場合にのみ行う必要があります。 null 以外の値を設定することは、正しく構成されていないプロキシや、ネットワーク上のサイドチャネルから届く悪意のある要求から保護するための予防策となります (ただし保証はできません)。Forwarded Headers Middleware では、ヘッダーが右から左の逆の順序で処理されます。 規定値 ( 1 ) を使う場合は、ForwardLimit の値を増やさない限りヘッダーの右端にある値のみが処理されます。既定値は、 1 です。 |
KnownNetworks | 受け付けるヘッダーの転送元である既知のネットワークのアドレス範囲です。 クラスレス ドメイン間ルーティング (CIDR) の表記を使って、IP の範囲を指定します。 サーバーがデュアル モードのソケットを使用している場合、IPv4 アドレスは IPv6 形式で提供されます (たとえば、IPv4 での 10.0.0.1 は IPv6 で ::ffff:10.0.0.1 と表現されます)。 「IPAddress.MapToIPv6」をご覧ください。 この形式が必要かどうかを判断するには、「HttpContext.Connection.RemoteIpAddress」をご覧ください。既定値は、 new IPNetwork(IPAddress.Loopback, 8) に対する単一のエントリを含む IList <IPNetwork> です。 |
KnownProxies | 受け付けるヘッダーの転送元である既知のプロキシのアドレスです。 IP アドレスの正確な一致を指定するには、KnownProxies を使います。サーバーがデュアル モードのソケットを使用している場合、IPv4 アドレスは IPv6 形式で提供されます (たとえば、IPv4 での 10.0.0.1 は IPv6 で ::ffff:10.0.0.1 と表現されます)。 「IPAddress.MapToIPv6」をご覧ください。 この形式が必要かどうかを判断するには、「HttpContext.Connection.RemoteIpAddress」をご覧ください。既定値は、 IPAddress.IPv6Loopback に対する単一のエントリを含む IList <IPAddress> です。 |
OriginalForHeaderName | ForwardedHeadersDefaults.XOriginalForHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使います。 既定値は、 X-Original-For です。 |
OriginalHostHeaderName | ForwardedHeadersDefaults.XOriginalHostHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使います。 既定値は、 X-Original-Host です。 |
OriginalProtoHeaderName | ForwardedHeadersDefaults.XOriginalProtoHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使います。 既定値は、 X-Original-Proto です。 |
RequireHeaderSymmetry | 処理対象の ForwardedHeadersOptions.ForwardedHeaders の間でヘッダー値の数が同期していることを要求します。 ASP.NET Core 1.x での既定値は true です。 ASP.NET Core 2.0 以降での既定値は false です。 |
シナリオとユース ケース
転送されるヘッダーを追加することができず、すべての要求が安全な場合
アプリにプロキシされる要求に、転送されるヘッダーを追加できない場合があります。 すべてのパブリック外部要求が HTTPS を使うことをプロキシが強制している場合、任意の種類のミドルウェアを使う前に、スキームを手動で設定できます。
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next(context);
});
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
このコードは、開発環境またはステージング環境の環境変数または他の構成設定によって無効にすることができます。
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
if (!app.Environment.IsProduction())
{
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next(context);
});
}
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
要求のパスを変更するパス ベースとプロキシを操作する
一部のプロキシでは、パスはそのまま渡されますが、ルーティングが正しく機能するためには削除する必要のあるアプリ ベース パスが含まれます。 UsePathBaseExtensions.UsePathBase ミドルウェアは、パスを HttpRequest.Path と HttpRequest.PathBase へのアプリ ベース パスに分割します。
/foo
が /foo/api/1
として渡されるプロキシ パスのアプリ ベース パスである場合、ミドルウェアは次のコマンドで Request.PathBase
を /foo
に、Request.Path
を /api/1
に設定します。
app.UsePathBase("/foo");
// ...
app.UseRouting();
Note
WebApplication を使用する場合 (ASP.NET Core 5.0 から 6.0 への移行に関する記事を参照) は、UsePathBase
の後に app.UseRouting
を呼び出して、ルーティング ミドルウェアがルートを照合する前に変更されたパスを確認できるようにする必要があります。 そうしない場合、ミドルウェアの順序とルーティングに関する記事で説明されているように、ルートはパスが書き直される前に UsePathBase
によって照合されます。
ミドルウェアが逆方向にもう一度呼び出されると、元のパスとパス ベースが再度適用されます。 ミドルウェアの順序の処理の詳細については、「ASP.NET Core のミドルウェア」を参照してください。
プロキシがパスをトリミングする場合は (たとえば、/foo/api/1
を /api/1
に転送)、要求の /foo/api/1
プロパティを設定することによって、リダイレクトとリンクを修正します。
app.Use((context, next) =>
{
context.Request.PathBase = new PathString("/foo");
return next(context);
});
プロキシがパス データを追加している場合は、StartsWithSegments を使用して Path プロパティに割り当てることで、パスの一部を破棄してリダイレクトとリンクを修正します。
app.Use((context, next) =>
{
if (context.Request.Path.StartsWithSegments("/foo", out var remainder))
{
context.Request.Path = remainder;
}
return next(context);
});
別のヘッダー名を使用するプロキシの構成
プロキシがプロキシ アドレス/ポートおよび開始スキーム情報の転送に名前が X-Forwarded-For
と X-Forwarded-Proto
のヘッダーを使用しない場合、プロキシで使用されるヘッダー名と一致するように、ForwardedForHeaderName と ForwardedProtoHeaderName のオプションを設定してください。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedForHeaderName = "HeaderNamUsedByProxy_X-Forwarded-For_Header";
options.ForwardedProtoHeaderName = "HeaderNamUsedByProxy_X-Forwarded-Proto_Header";
});
var app = builder.Build();
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Linux および非 IIS のリバース プロキシのスキームを転送する
UseHttpsRedirection および UseHsts を呼び出すアプリが、Azure Linux App Service、Azure Linux 仮想マシン (VM)、または IIS 以外の他のリバース プロキシの背後に展開されている場合、サイトは無限ループに陥ります。 TLS はリバース プロキシによって終了され、Kestrel では正しい要求スキームが認識されません。 OAuth と OIDC もこの構成では正しくないリダイレクトを生成するため、失敗します。 UseIISIntegration は IIS の背後で実行される場合、Forwarded Headers Middleware を追加して構成しますが、Linux 用の対応する自動設定 (Apache または Nginx 統合) はありません。
非 IIS シナリオでプロキシからスキームを転送するには、ASPNETCORE_FORWARDEDHEADERS_ENABLED
を true
に設定して、Forwarded Headers Middleware を有効にします。 警告: このフラグでは、クラウド環境向けに設計された設定が使用され、フォワーダーが受け入れられる IP を制限する KnownProxies option
などの機能は有効になりません。
証明書の転送
Azure
証明書の転送用に Azure App Service を構成するには、「Azure App Service に対する TLS 相互認証の構成」を参照してください。 次のガイダンスは、ASP.NET Core アプリの構成に関するものです。
- Azure で使用されるヘッダー名を指定するように、証明書転送ミドルウェアを構成します。 次のコードを追加して、ミドルウェアが証明書を作成する元となるヘッダーを構成します。
- UseAuthentication の呼び出しの前に UseCertificateForwarding を呼び出します。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddCertificateForwarding(options =>
options.CertificateHeader = "X-ARR-ClientCert");
var app = builder.Build();
app.UseCertificateForwarding();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.UseAuthentication();
app.MapRazorPages();
app.Run();
他の Web プロキシ
使用されているプロキシが、IIS でも、Azure App Service のアプリケーション要求ルーティング処理 (ARR) でもない場合は、HTTP ヘッダーで受け取った証明書を転送するように、プロキシを構成します。
- ヘッダー名を指定するように、証明書転送ミドルウェアを構成します。 次のコードを追加して、ミドルウェアが証明書を作成する元となるヘッダーを構成します。
- UseAuthentication の呼び出しの前に UseCertificateForwarding を呼び出します。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddCertificateForwarding(options =>
options.CertificateHeader = "YOUR_CERTIFICATE_HEADER_NAME");
var app = builder.Build();
app.UseCertificateForwarding();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.UseAuthentication();
app.MapRazorPages();
app.Run();
プロキシで証明書が base64 でエンコードされていない場合は (Nginx の場合のように)、HeaderConverter
オプションを設定します。 次の例を確認してください。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "YOUR_CUSTOM_HEADER_NAME";
options.HeaderConverter = (headerValue) =>
{
// Conversion logic to create an X509Certificate2.
var clientCertificate = ConversionLogic.CreateAnX509Certificate2();
return clientCertificate;
};
});
var app = builder.Build();
app.UseCertificateForwarding();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.UseAuthentication();
app.MapRazorPages();
app.Run();
トラブルシューティング
ヘッダーが意図したとおりに転送されない場合は、debug
レベルのdebug
と HTTP 要求のログを有効にします。 UseHttpLogging は、UseForwardedHeaders の後に呼び出す必要があります。
using Microsoft.AspNetCore.HttpLogging;
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddHttpLogging(options =>
{
options.LoggingFields = HttpLoggingFields.RequestPropertiesAndHeaders;
});
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var app = builder.Build();
app.UseForwardedHeaders();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
// Connection: RemoteIp
app.Logger.LogInformation("Request RemoteIp: {RemoteIpAddress}",
context.Connection.RemoteIpAddress);
await next(context);
});
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
指定されたヘッダーに複数の値がある場合、Forwarded Headers Middleware では右から左の逆の順序でヘッダーが処理されます。 既定の ForwardLimit
は 1
です。そのため、ForwardLimit
の値を増やさない限り、ヘッダーの右端にある値のみが処理されます。
Forwarded Headers が処理される前に、要求の元のリモート IP アドレスが KnownProxies リストまたは KnownNetworks リストのエントリと一致する必要があります。 これにより、信頼されないプロキシからの転送を受け付けないことで、ヘッダーのスプーフィングを制限します。 不明なプロキシが検出されると、ログにプロキシのアドレスが示されます。
September 20th 2018, 15:49:44.168 Unknown proxy: 10.0.0.100:54321
前の例では、10.0.0.100 がプロキシ サーバーです。 サーバーが信頼されているプロキシであれば、KnownProxies
にサーバーの IP アドレスを追加するか、信頼されているネットワークを KnownNetworks
に追加します。 詳細については、「Forwarded Headers Middleware のオプション」セクションをご覧ください。
using Microsoft.AspNetCore.HttpOverrides;
using System.Net;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseForwardedHeaders();
app.UseHsts();
}
else
{
app.UseDeveloperExceptionPage();
app.UseForwardedHeaders();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
ログを表示するには、"Microsoft.AspNetCore.HttpLogging": "Information"
を appsettings.Development.json
ファイルに追加します。
{
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.HttpLogging": "Information"
}
}
}
重要
信頼されているプロキシとネットワークにのみ、ヘッダーの転送を許可します。 それ以外に許可すると、IP なりすまし攻撃が可能になります。
その他の技術情報
ASP.NET Core の推奨される構成では、アプリは IIS/ASP.NET Core モジュール、Nginx、または Apache を使ってホストされます。 プロキシ サーバー、ロード バランサー、および他のネットワーク アプライアンスにより、要求に関する情報が、アプリに到達する前にわからなくなることがよくあります。
- HTTPS 要求が HTTP によってプロキシされると、元のスキーム (HTTPS) は失われ、ヘッダーで転送される必要があります。
- アプリは、インターネット上または社内ネットワーク上の本来の送信元ではなく、プロキシから要求を受信するため、送信元クライアントの IP アドレスもヘッダーで転送される必要があります。
この情報は、リダイレクト、認証、リンクの生成、ポリシーの評価、クライアントの位置情報など、要求の処理で重要になる可能性があります。
転送されるヘッダー
慣例によりは、プロキシは HTTP ヘッダーで情報を転送します。
Header | 説明 |
---|---|
X-Forwarded-For | 要求を開始したクライアントと、プロキシ チェーン内の後続のプロキシに関する情報を保持します。 このパラメーターは、IP アドレス (および、必要に応じてポート番号) を含むことがあります。 プロキシ サーバーのチェーンにおいては、最初のパラメーターが、要求を最初に行ったクライアントを示します。 その後に、後続のプロキシの識別子が指定されています。 チェーン内の最後のプロキシは、パラメーターのリストには含まれません。 最後のプロキシの IP アドレスとオプションのポート番号は、トランスポート層のリモート IP アドレスとして入手できます。 |
X-Forwarded-Proto | 開始スキーム (HTTP/HTTPS) の値です。 要求が複数のプロキシを通過している場合、値はスキームのリストである場合もあります。 |
X-Forwarded-Host | ホスト ヘッダー フィールドの元の値です。 通常、プロキシはホスト ヘッダーを変更しません。 プロキシにおいてホスト ヘッダーが既知の適切な値であることが検証されない、または既知の適切な値に制限されないシステムに影響を与える、特権の昇格脆弱性については、マイクロソフト セキュリティ アドバイザリ CVE-2018-0787 をご覧ください。 |
Forwarded Headers Middleware (ForwardedHeadersMiddleware) によって、これらのヘッダーが読み取られ、HttpContext 上の関連するフィールドに入力されます。
ミドルウェアの更新:
- HttpContext.Connection.RemoteIpAddress:
X-Forwarded-For
ヘッダーの値を使って設定します。 追加の設定は、ミドルウェアがRemoteIpAddress
を設定する方法に影響を与えます。 詳しくは、「Forwarded Headers Middleware のオプション」をご覧ください。 使われた値はX-Forwarded-For
から削除され、古い値はX-Original-For
に保持されています。Host
やProto
などの他のヘッダーにも同じパターンが適用されます。 - HttpContext.Request.Scheme:
X-Forwarded-Proto
ヘッダーの値を使って設定します。 - HttpContext.Request.Host:
X-Forwarded-Host
ヘッダーの値を使って設定します。
上記に関する詳細については、こちらの GitHub イシューを参照してください。
Forwarded Headers Middleware の既定の設定は構成できます。 既定の設定の場合:
- アプリと要求のソースの間には、"1 つのプロキシ" だけが存在します。
- 既知のプロキシと既知のネットワークに対しては、ループバック アドレスのみが構成されています。
- 転送されるヘッダーには
X-Forwarded-For
とX-Forwarded-Proto
の名前が付けられます。 ForwardedHeaders
の値はForwardedHeaders.None
です。ミドルウェアを有効にするには、目的のフォワーダーをここで設定する必要があります。
すべてのネットワーク アプライアンスが追加構成なしで X-Forwarded-For
および X-Forwarded-Proto
ヘッダーを追加するわけではありません。 プロキシされた要求がアプリに届いたときにこれらのヘッダーが含まれていない場合は、アプライアンスの製造元のガイダンスを参照してください。 アプライアンスが X-Forwarded-For
と X-Forwarded-Proto
以外の名前を使用している場合は、アプライアンスで使用されるヘッダー名と一致するように ForwardedForHeaderName と ForwardedProtoHeaderName のオプションを設定してください。 詳細については、「Forwarded Headers Middleware のオプション」と「別のヘッダー名を使用するプロキシの構成」を参照してください。
IIS/IIS Express と ASP.NET Core モジュール
アプリが IIS と ASP.NET Core モジュールの背後でアウト プロセスでホストされている場合、IIS Integration Middleware によって Forwarded Headers Middleware が既定で有効にされます。 転送されるヘッダーの信頼に関する問題のため (たとえば、IP スプーフィング)、Forwarded Headers Middleware はアクティブ化されると最初に、ASP.NET Core モジュールに固有の制限された構成を使って、ミドルウェア パイプライン内で実行します。 ミドルウェアは、X-Forwarded-For
および X-Forwarded-Proto
ヘッダーを転送するように構成され、単一の localhost プロキシに制限されます。 追加の構成が必要な場合は、「Forwarded Headers Middleware のオプション」をご覧ください。
プロキシ サーバーとロード バランサーの他のシナリオ
アウト プロセスでホストされている場合に IIS Integration が使われていない場合は、Forwarded Headers Middleware は既定で有効になりません。 UseForwardedHeaders を含む転送されたヘッダーをアプリで処理するためには、Forwarded Headers Middleware を有効にする必要があります。 ミドルウェアを有効にした後、ミドルウェアに対して ForwardedHeadersOptions が指定されていない場合の既定の ForwardedHeadersOptions は ForwardedHeaders.None です。
ForwardedHeadersOptions でミドルウェアを構成して、Startup.ConfigureServices
で X-Forwarded-For
および X-Forwarded-Proto
ヘッダーを転送します。
Forwarded Headers Middleware の順序
Forwarded Headers Middleware は、他のミドルウェアの前に実行する必要があります。 この順序により、転送されるヘッダー情報に依存するミドルウェアが処理にヘッダー値を使用できます。 Forwarded Headers Middleware は、診断とエラー処理の後に実行できますが、UseHsts
を呼び出す前に実行する必要があります。
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseForwardedHeaders();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseForwardedHeaders();
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
または、診断の前に UseForwardedHeaders
を呼び出します。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseForwardedHeaders();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Note
ForwardedHeadersOptions が Startup.ConfigureServices
において指定されていない場合、または UseForwardedHeaders を使って拡張メソッドに直接渡されない場合、転送される既定のヘッダーは ForwardedHeadersOptions です。 転送するヘッダーで ForwardedHeaders プロパティが構成されている必要があります。
Nginx の構成
X-Forwarded-For
および X-Forwarded-Proto
ヘッダーを転送する方法については、「X-Forwarded-For
」を参照してください。 詳細については、「NGINX:Using the Forwarded header」 (NGINX: 転送されるヘッダーの使用) を参照してください。
Apache の構成
X-Forwarded-For
は自動的に追加されます (「X-Forwarded-For
」 (Apache モジュール mod_proxy: リバース プロキシがヘッダーを要求する) を参照)。
Forwarded Headers Middleware のオプション
ForwardedHeadersOptions は、Forwarded Headers Middleware の動作を制御します。 既定の値の変更例を次に示します。
- 転送されるヘッダーのエントリ数を
2
に制限します。 127.0.10.1
の既知のプロキシ アドレスを追加します。- 転送されるヘッダーの名前を既定の
X-Forwarded-For
からX-Forwarded-For-My-Custom-Header-Name
に変更します。
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardLimit = 2;
options.KnownProxies.Add(IPAddress.Parse("127.0.10.1"));
options.ForwardedForHeaderName = "X-Forwarded-For-My-Custom-Header-Name";
});
オプション | 説明 |
---|---|
AllowedHosts | X-Forwarded-Host ヘッダーによるホストを指定した値に制限します。
IList<string> です。 |
ForwardedHeaders | 処理する必要があるフォワーダーを識別します。 適用されるフィールドの一覧については、「ForwardedHeaders Enum」(ForwardedHeaders 列挙型) をご覧ください。 このプロパティに割り当てられる標準値は、ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto です。既定値は ForwardedHeaders.None です。 |
ForwardedForHeaderName | ForwardedHeadersDefaults.XForwardedForHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使います。 このオプションは、プロキシ/フォワーダーが X-Forwarded-For ヘッダーを使用していないが、情報の転送のためにその他のヘッダーを使用している場合に使用されます。既定値は、 X-Forwarded-For です。 |
ForwardedHostHeaderName | ForwardedHeadersDefaults.XForwardedHostHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使います。 このオプションは、プロキシ/フォワーダーが X-Forwarded-Host ヘッダーを使用していないが、情報の転送のためにその他のヘッダーを使用している場合に使用されます。既定値は、 X-Forwarded-Host です。 |
ForwardedProtoHeaderName | ForwardedHeadersDefaults.XForwardedProtoHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使います。 このオプションは、プロキシ/フォワーダーが X-Forwarded-Proto ヘッダーを使用していないが、情報の転送のためにその他のヘッダーを使用している場合に使用されます。既定値は、 X-Forwarded-Proto です。 |
ForwardedPrefixHeaderName | ForwardedHeadersDefaults.XForwardedPrefixHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使用します。 このオプションは、プロキシ/フォワーダーが X-Forwarded-Prefix ヘッダーを使用していないが、情報の転送のためにその他のヘッダーを使用している場合に使用されます。既定値は、 X-Forwarded-Prefix です。 |
ForwardLimit | 処理されるヘッダー内のエントリの数を制限します。 制限を無効にするには null に設定しますが、これは KnownProxies または KnownNetworks が構成されている場合にのみ行う必要があります。 null 以外の値を設定することは、正しく構成されていないプロキシや、ネットワーク上のサイドチャネルから届く悪意のある要求から保護するための予防策となります (ただし保証はできません)。Forwarded Headers Middleware では、ヘッダーが右から左の逆の順序で処理されます。 規定値 ( 1 ) を使う場合は、ForwardLimit の値を増やさない限りヘッダーの右端にある値のみが処理されます。既定値は、 1 です。 |
KnownNetworks | 受け付けるヘッダーの転送元である既知のネットワークのアドレス範囲です。 クラスレス ドメイン間ルーティング (CIDR) の表記を使って、IP の範囲を指定します。 サーバーがデュアル モードのソケットを使用している場合、IPv4 アドレスは IPv6 形式で提供されます (たとえば、IPv4 での 10.0.0.1 は IPv6 で ::ffff:10.0.0.1 と表現されます)。 「IPAddress.MapToIPv6」をご覧ください。 この形式が必要かどうかを判断するには、「HttpContext.Connection.RemoteIpAddress」をご覧ください。既定値は、 new IPNetwork(IPAddress.Loopback, 8) に対する単一のエントリを含む IList <IPNetwork> です。 |
KnownProxies | 受け付けるヘッダーの転送元である既知のプロキシのアドレスです。 IP アドレスの正確な一致を指定するには、KnownProxies を使います。サーバーがデュアル モードのソケットを使用している場合、IPv4 アドレスは IPv6 形式で提供されます (たとえば、IPv4 での 10.0.0.1 は IPv6 で ::ffff:10.0.0.1 と表現されます)。 「IPAddress.MapToIPv6」をご覧ください。 この形式が必要かどうかを判断するには、「HttpContext.Connection.RemoteIpAddress」をご覧ください。既定値は、 IPAddress.IPv6Loopback に対する単一のエントリを含む IList <IPAddress> です。 |
OriginalForHeaderName | ForwardedHeadersDefaults.XOriginalForHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使います。 既定値は、 X-Original-For です。 |
OriginalHostHeaderName | ForwardedHeadersDefaults.XOriginalHostHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使います。 既定値は、 X-Original-Host です。 |
OriginalProtoHeaderName | ForwardedHeadersDefaults.XOriginalProtoHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使います。 既定値は、 X-Original-Proto です。 |
OriginalPrefixHeaderName | ForwardedHeadersDefaults.XOriginalPrefixHeaderName によって指定されているヘッダーではなく、このプロパティによって指定されているヘッダーを使用します。 既定値は、 X-Original-Prefix です。 |
RequireHeaderSymmetry | 処理対象の ForwardedHeadersOptions.ForwardedHeaders の間でヘッダー値の数が同期していることを要求します。 ASP.NET Core 1.x での既定値は true です。 ASP.NET Core 2.0 以降での既定値は false です。 |
シナリオとユース ケース
転送されるヘッダーを追加することができず、すべての要求が安全な場合
アプリにプロキシされる要求に、転送されるヘッダーを追加できない場合があります。 すべてのパブリック外部要求が HTTPS を使うことをプロキシが強制している場合、すべての種類のミドルウェアを使う前に、Startup.Configure
でスキームを手動で設定できます。
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next();
});
このコードは、開発環境またはステージング環境の環境変数または他の構成設定によって、無効にすることができます。
要求のパスを変更するパス ベースとプロキシを処理する
一部のプロキシでは、パスはそのまま渡されますが、ルーティングが正しく機能するためには削除する必要のあるアプリ ベース パスが含まれます。 UsePathBaseExtensions.UsePathBase ミドルウェアは、パスを HttpRequest.Path と HttpRequest.PathBase へのアプリ ベース パスに分割します。
/foo
が /foo/api/1
として渡されるプロキシ パスのアプリ ベース パスである場合、ミドルウェアは次のコマンドで Request.PathBase
を /foo
に、Request.Path
を /api/1
に設定します。
app.UsePathBase("/foo");
ミドルウェアが逆方向にもう一度呼び出されると、元のパスとパス ベースが再度適用されます。 ミドルウェアの順序の処理の詳細については、「ASP.NET Core のミドルウェア」を参照してください。
プロキシがパスをトリミングする場合は (たとえば、/foo/api/1
を /api/1
に転送)、要求の /foo/api/1
プロパティを設定することによって、リダイレクトとリンクを修正します。
app.Use((context, next) =>
{
context.Request.PathBase = new PathString("/foo");
return next();
});
プロキシがパス データを追加している場合は、StartsWithSegments を使用して Path プロパティに割り当てることで、パスの一部を破棄してリダイレクトとリンクを修正します。
app.Use((context, next) =>
{
if (context.Request.Path.StartsWithSegments("/foo", out var remainder))
{
context.Request.Path = remainder;
}
return next();
});
別のヘッダー名を使用するプロキシの構成
プロキシがプロキシ アドレス/ポートおよび開始スキーム情報の転送に名前が X-Forwarded-For
と X-Forwarded-Proto
のヘッダーを使用しない場合、プロキシで使用されるヘッダー名と一致するように、ForwardedForHeaderName と ForwardedProtoHeaderName のオプションを設定してください。
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedForHeaderName = "Header_Name_Used_By_Proxy_For_X-Forwarded-For_Header";
options.ForwardedProtoHeaderName = "Header_Name_Used_By_Proxy_For_X-Forwarded-Proto_Header";
});
Linux および非 IIS のリバース プロキシのスキームを転送する
UseHttpsRedirection および UseHsts を呼び出すアプリが、Azure Linux App Service、Azure Linux 仮想マシン (VM)、または IIS 以外の他のリバース プロキシの背後に展開されている場合、サイトは無限ループに陥ります。 TLS はリバース プロキシによって終了され、Kestrel では正しい要求スキームが認識されません。 OAuth と OIDC もこの構成では正しくないリダイレクトを生成するため、失敗します。 UseIISIntegration は IIS の背後で実行される場合、Forwarded Headers Middleware を追加して構成しますが、Linux 用の対応する自動設定 (Apache または Nginx 統合) はありません。
非 IIS シナリオでプロキシからスキームを転送するには、Forwarded Headers Middleware を追加して構成します。 Startup.ConfigureServices
で、次のコードを使用します。
// using Microsoft.AspNetCore.HttpOverrides;
if (string.Equals(
Environment.GetEnvironmentVariable("ASPNETCORE_FORWARDEDHEADERS_ENABLED"),
"true", StringComparison.OrdinalIgnoreCase))
{
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto;
// Only loopback proxies are allowed by default.
// Clear that restriction because forwarders are enabled by explicit
// configuration.
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
}
証明書の転送
Azure
証明書の転送用に Azure App Service を構成するには、「Azure App Service に対する TLS 相互認証の構成」を参照してください。 次のガイダンスは、ASP.NET Core アプリの構成に関するものです。
Startup.Configure
で、app.UseAuthentication();
の呼び出しの前に次のコードを追加します。
app.UseCertificateForwarding();
Azure で使用されるヘッダー名を指定するように、証明書転送ミドルウェアを構成します。 Startup.ConfigureServices
に次のコードを追加し、ミドルウェアによる証明書作成の基になるヘッダーを構成します。
services.AddCertificateForwarding(options =>
options.CertificateHeader = "X-ARR-ClientCert");
他の Web プロキシ
使用されているプロキシが、IIS でも、Azure App Service のアプリケーション要求ルーティング処理 (ARR) でもない場合は、HTTP ヘッダーで受け取った証明書を転送するように、プロキシを構成します。 Startup.Configure
で、app.UseAuthentication();
の呼び出しの前に次のコードを追加します。
app.UseCertificateForwarding();
ヘッダー名を指定するように証明書の転送ミドルウェアを構成します。 Startup.ConfigureServices
に次のコードを追加し、ミドルウェアによる証明書作成の基になるヘッダーを構成します。
services.AddCertificateForwarding(options =>
options.CertificateHeader = "YOUR_CERTIFICATE_HEADER_NAME");
プロキシで証明書が base64 エンコードではない場合は (Nginx の場合と同様)、HeaderConverter
オプションを設定します。 Startup.ConfigureServices
での次の例を検討してください。
services.AddCertificateForwarding(options =>
{
options.CertificateHeader = "YOUR_CUSTOM_HEADER_NAME";
options.HeaderConverter = (headerValue) =>
{
var clientCertificate =
/* some conversion logic to create an X509Certificate2 */
return clientCertificate;
}
});
トラブルシューティング
ヘッダーが意図したとおりに転送されない場合は、ログ を有効にします。 ログで問題のトラブルシューティングに十分な情報が提供されない場合は、サーバーが受信した要求ヘッダーを列挙します。 インライン ミドルウェアを使用し、アプリ応答に要求ヘッダーを書き込んだり、ヘッダーをログに記録したりします。
アプリの応答にヘッダーを書き込むには、Startup.Configure
内の UseForwardedHeaders の呼び出しの直後に、次の端末のインライン ミドルウェアを配置します。
app.Run(async (context) =>
{
context.Response.ContentType = "text/plain";
// Request method, scheme, and path
await context.Response.WriteAsync(
$"Request Method: {context.Request.Method}{Environment.NewLine}");
await context.Response.WriteAsync(
$"Request Scheme: {context.Request.Scheme}{Environment.NewLine}");
await context.Response.WriteAsync(
$"Request Path: {context.Request.Path}{Environment.NewLine}");
// Headers
await context.Response.WriteAsync($"Request Headers:{Environment.NewLine}");
foreach (var header in context.Request.Headers)
{
await context.Response.WriteAsync($"{header.Key}: " +
$"{header.Value}{Environment.NewLine}");
}
await context.Response.WriteAsync(Environment.NewLine);
// Connection: RemoteIp
await context.Response.WriteAsync(
$"Request RemoteIp: {context.Connection.RemoteIpAddress}");
});
応答本文ではなく、ログに書き込むことができます。 ログに書き込むことで、デバッグしている間、サイトは正常に機能できます。
応答本文ではなく、ログに書き込むには:
- 「
ILogger<Startup>
」に説明されているように、ILogger<Startup>
をStartup
クラスに挿入します。 Startup.Configure
内で UseForwardedHeaders を呼び出した直後に次のインライン ミドルウェアを配置します。
app.Use(async (context, next) =>
{
// Request method, scheme, path, and base path
_logger.LogDebug("Request Method: {Method}", context.Request.Method);
_logger.LogDebug("Request Scheme: {Scheme}", context.Request.Scheme);
_logger.LogDebug("Request Path: {Path}", context.Request.Path);
_logger.LogDebug("Request Path Base: {PathBase}", context.Request.PathBase);
// Headers
foreach (var header in context.Request.Headers)
{
_logger.LogDebug("Header: {Key}: {Value}", header.Key, header.Value);
}
// Connection: RemoteIp
_logger.LogDebug("Request RemoteIp: {RemoteIpAddress}",
context.Connection.RemoteIpAddress);
await next();
});
処理時、X-Forwarded-{For|Proto|Host|Prefix}
値は X-Original-{For|Proto|Host|Prefix}
に移動されます。 指定されたヘッダーに複数の値がある場合、Forwarded Headers Middleware では右から左の逆の順序でヘッダーが処理されます。 既定の ForwardLimit
は 1
です。そのため、ForwardLimit
の値を増やさない限り、ヘッダーの右端にある値のみが処理されます。
Forwarded Headers が処理される前に、要求の元のリモート IP アドレスが KnownProxies
リストまたは KnownNetworks
リストのエントリと一致する必要があります。 これにより、信頼されないプロキシからの転送を受け付けないことで、ヘッダーのスプーフィングを制限します。 不明なプロキシが検出されると、ログにプロキシのアドレスが示されます。
September 20th 2018, 15:49:44.168 Unknown proxy: 10.0.0.100:54321
前の例では、10.0.0.100 がプロキシ サーバーです。 サーバーが信頼されているプロキシであれば、Startup.ConfigureServices
で KnownProxies
にサーバーの IP アドレスを追加します (あるいは、信頼されているネットワークを KnownNetworks
に追加します)。 詳細については、「Forwarded Headers Middleware のオプション」セクションをご覧ください。
services.Configure<ForwardedHeadersOptions>(options =>
{
options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});
重要
信頼されているプロキシとネットワークにのみ、ヘッダーの転送を許可します。 それ以外に許可すると、IP なりすまし攻撃が可能になります。
その他の技術情報
ASP.NET Core