From b6ca033e53e5f35abf3e804252045b94240af229 Mon Sep 17 00:00:00 2001 From: Rick Anderson <3605364+Rick-Anderson@users.noreply.github.com> Date: Thu, 18 Jun 2020 14:11:11 -1000 Subject: [PATCH] ForwardedHeaders must be called before UseHsts (#18821) * ForwardedHeaders must be called before UseHsts * ForwardedHeaders must be called before UseHsts * ForwardedHeaders must be called before UseHsts * ForwardedHeaders must be called before UseHsts * ForwardedHeaders must be called before UseHsts * react to feedback * react to feedback * react to feedback * react to feedback * react to feedback * react to feedback * Update aspnetcore/host-and-deploy/linux-nginx.md Co-authored-by: Chris Ross Co-authored-by: Chris Ross --- aspnetcore/fundamentals/middleware/index.md | 4 ++ aspnetcore/host-and-deploy/linux-apache.md | 4 +- aspnetcore/host-and-deploy/linux-nginx.md | 3 +- .../host-and-deploy/proxy-load-balancer.md | 36 +++-------- .../proxy-load-balancer/3.1samples/Startup.cs | 58 +++++++++++++++++ .../3.1samples/Startup2.cs | 64 +++++++++++++++++++ aspnetcore/includes/ForwardedHeaders.md | 1 + 7 files changed, 140 insertions(+), 30 deletions(-) create mode 100644 aspnetcore/host-and-deploy/proxy-load-balancer/3.1samples/Startup.cs create mode 100644 aspnetcore/host-and-deploy/proxy-load-balancer/3.1samples/Startup2.cs create mode 100644 aspnetcore/includes/ForwardedHeaders.md diff --git a/aspnetcore/fundamentals/middleware/index.md b/aspnetcore/fundamentals/middleware/index.md index e1d599e9d7..9e0eab9934 100644 --- a/aspnetcore/fundamentals/middleware/index.md +++ b/aspnetcore/fundamentals/middleware/index.md @@ -173,6 +173,10 @@ For Single Page Applications (SPAs), the SPA middleware extensions are used as a convention for branching the pipeline. `Map` branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed. diff --git a/aspnetcore/host-and-deploy/linux-apache.md b/aspnetcore/host-and-deploy/linux-apache.md index ac6a91c9f9..994246afcf 100644 --- a/aspnetcore/host-and-deploy/linux-apache.md +++ b/aspnetcore/host-and-deploy/linux-apache.md @@ -57,7 +57,9 @@ A proxy server is one which forwards client requests to another server instead o Because requests are forwarded by reverse proxy, use the [Forwarded Headers Middleware](xref:host-and-deploy/proxy-load-balancer) from the [Microsoft.AspNetCore.HttpOverrides](https://www.nuget.org/packages/Microsoft.AspNetCore.HttpOverrides/) package. The middleware updates the `Request.Scheme`, using the `X-Forwarded-Proto` header, so that redirect URIs and other security policies work correctly. -Any component that depends on the scheme, such as authentication, link generation, redirects, and geolocation, must be placed after invoking the Forwarded Headers Middleware. As a general rule, Forwarded Headers Middleware should run before other middleware except diagnostics and error handling middleware. This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing. +Any component that depends on the scheme, such as authentication, link generation, redirects, and geolocation, must be placed after invoking the Forwarded Headers Middleware. + +[!INCLUDE[](~/includes/ForwardedHeaders.md)] Invoke the method at the top of `Startup.Configure` before calling other middleware. Configure the middleware to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers: diff --git a/aspnetcore/host-and-deploy/linux-nginx.md b/aspnetcore/host-and-deploy/linux-nginx.md index fae8fffeb1..69880978f1 100644 --- a/aspnetcore/host-and-deploy/linux-nginx.md +++ b/aspnetcore/host-and-deploy/linux-nginx.md @@ -78,7 +78,8 @@ For the purposes of this guide, a single instance of Nginx is used. It runs on t Because requests are forwarded by reverse proxy, use the [Forwarded Headers Middleware](xref:host-and-deploy/proxy-load-balancer) from the [Microsoft.AspNetCore.HttpOverrides](https://www.nuget.org/packages/Microsoft.AspNetCore.HttpOverrides/) package. The middleware updates the `Request.Scheme`, using the `X-Forwarded-Proto` header, so that redirect URIs and other security policies work correctly. -Any component that depends on the scheme, such as authentication, link generation, redirects, and geolocation, must be placed after invoking the Forwarded Headers Middleware. As a general rule, Forwarded Headers Middleware should run before other middleware except diagnostics and error handling middleware. This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing. + +[!INCLUDE[](~/includes/ForwardedHeaders.md)] Invoke the method at the top of `Startup.Configure` before calling other middleware. Configure the middleware to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers: diff --git a/aspnetcore/host-and-deploy/proxy-load-balancer.md b/aspnetcore/host-and-deploy/proxy-load-balancer.md index 701a90119e..93101866ef 100644 --- a/aspnetcore/host-and-deploy/proxy-load-balancer.md +++ b/aspnetcore/host-and-deploy/proxy-load-balancer.md @@ -56,39 +56,19 @@ Forwarded Headers Middleware is enabled by default by [IIS Integration Middlewar Outside of using [IIS Integration](xref:host-and-deploy/iis/index#enable-the-iisintegration-components) when hosting [out-of-process](xref:host-and-deploy/iis/index#out-of-process-hosting-model), Forwarded Headers Middleware isn't enabled by default. Forwarded Headers Middleware must be enabled for an app to process forwarded headers with . After enabling the middleware if no are specified to the middleware, the default [ForwardedHeadersOptions.ForwardedHeaders](xref:Microsoft.AspNetCore.Builder.ForwardedHeadersOptions.ForwardedHeaders) are [ForwardedHeaders.None](xref:Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders). -Configure the middleware with to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers in `Startup.ConfigureServices`. Invoke the method in `Startup.Configure` before calling other middleware: +Configure the middleware with to forward the `X-Forwarded-For` and `X-Forwarded-Proto` headers in `Startup.ConfigureServices`. -```csharp -public void ConfigureServices(IServiceCollection services) -{ - services.AddMvc(); + - services.Configure(options => - { - options.ForwardedHeaders = - ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; - }); -} +### Forwarded Headers Middleware order -public void Configure(IApplicationBuilder app, IHostingEnvironment env) -{ - app.UseForwardedHeaders(); +Forwarded Headers Middleware should run before other middleware. This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing. Forwarded Headers Middleware can run after diagnostics and error handling, but it must be be run before calling `UseHsts`: - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Home/Error"); - } +[!code-csharp[](~/host-and-deploy/proxy-load-balancer/3.1samples/Startup.cs?name=snippet&highlight=13-17,25,30)] - app.UseStaticFiles(); - // In ASP.NET Core 1.x, replace the following line with: app.UseIdentity(); - app.UseAuthentication(); - app.UseMvc(); -} -``` +Alternatively, call `UseForwardedHeaders` before diagnostics: + +[!code-csharp[](~/host-and-deploy/proxy-load-balancer/3.1samples/Startup2.cs?name=snippet)] > [!NOTE] > If no are specified in `Startup.ConfigureServices` or directly to the extension method with , the default headers to forward are [ForwardedHeaders.None](xref:Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders). The property must be configured with the headers to forward. diff --git a/aspnetcore/host-and-deploy/proxy-load-balancer/3.1samples/Startup.cs b/aspnetcore/host-and-deploy/proxy-load-balancer/3.1samples/Startup.cs new file mode 100644 index 0000000000..f3256edb06 --- /dev/null +++ b/aspnetcore/host-and-deploy/proxy-load-balancer/3.1samples/Startup.cs @@ -0,0 +1,58 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + + +#region snippet +public class Startup +{ + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + public void ConfigureServices(IServiceCollection services) + { + services.AddControllersWithViews(); + services.Configure(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?}"); + }); + } +} +#endregion diff --git a/aspnetcore/host-and-deploy/proxy-load-balancer/3.1samples/Startup2.cs b/aspnetcore/host-and-deploy/proxy-load-balancer/3.1samples/Startup2.cs new file mode 100644 index 0000000000..1caa089fba --- /dev/null +++ b/aspnetcore/host-and-deploy/proxy-load-balancer/3.1samples/Startup2.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.AspNetCore.HttpsPolicy; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + + +public class Startup2 +{ + public Startup2(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + public void ConfigureServices(IServiceCollection services) + { + services.AddControllersWithViews(); + services.Configure(options => + { + options.ForwardedHeaders = + ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; + }); + } + + #region snippet + 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?}"); + }); + } + #endregion + +} diff --git a/aspnetcore/includes/ForwardedHeaders.md b/aspnetcore/includes/ForwardedHeaders.md new file mode 100644 index 0000000000..b95a02685f --- /dev/null +++ b/aspnetcore/includes/ForwardedHeaders.md @@ -0,0 +1 @@ +Forwarded Headers Middleware should run before other middleware. This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing. To run Forwarded Headers Middleware after diagnostics and error handling middleware, see [Forwarded Headers Middleware order](xref:host-and-deploy/proxy-load-balancer#fhmo). \ No newline at end of file