December 3, 2024

Properly configure forwarded headers in ASP.NET Core

Whenever we are using a proxy server like nginx or IIS, we will run into problems when we need to find the exact IP that is calling into our service. Basically, what happens under a proxy is that our app doesn’t directly receive requests from outside, but from the proxy server itself.

We will notice that if we try to get the remote IP address like in the below example:

HttpContext.Connection.RemoteIpAddress

We’ll end up with the same IP every time (eg. 10.0.0.144). So the solution is to use forwarded headers feature which is implemented in ASP.NET Core.

What is a forwarded header?

Like shown above, a forwarded header will help the application to determine which is the original IP that sent the request. It’s up to the proxy server to set up the headers correctly. We have a couple of headers:

  1. X-Forwarded-Host – the original host name
  2. X-Forwarded-Proto – the original scheme (http or https)
  3. X-Forwarded-For – the original IP

In the majority of situations, we will need the X-Forwarded-For, which is the most important.

Configure forwarded headers in ASP.NET Core

Configuring the forwarded headers in ASP.NET Core is pretty straightforward. Thanks why we can call them straight-forwarded headers
😂

Cool so to configure a straight-forwarded header we don’t need to add a new NuGet package, just add the right configuration and middleware to our Startup.cs file like so:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<ForwardedHeadersOptions>(options =>
    {
         options.ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.All;
    }
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseForwardedHeaders();
}

However, there is a small trick here that took me 2 days to solve. It’s not enough just to enable them, but you also have to supply a known proxy IP or known network for it to work as it should. Doing so will prevent IP spoofing attacks. The elegant solution is to add a configuration section in appsettings.json with the known proxy IPs:

{
  "KnownProxies": [
    "10.0.0.144"
  ]
}

And then use it in ConfigureServices method:

services.Configure<ForwardedHeadersOptions>(options =>
{
      options.ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.All;

      foreach (var proxy in Configuration.GetSection("KnownProxies").AsEnumerable().Where(c => c.Value != null))
      {
           options.KnownProxies.Add(IPAddress.Parse(proxy.Value));
      }
});

And that’s quite about it. It’s now up to you to determine which is the local proxy IP address to configure correctly.

Hope this article helps to understand more about straight-forwarded headers and how they work.

Thanks for reading, I hope you found this article useful and interesting. If you have any suggestions don’t hesitate to contact me. If you found my content useful please consider a small donation. Any support is greatly appreciated! Cheers  😉

afivan

Enthusiast adventurer, software developer with a high sense of creativity, discipline and achievement. I like to travel, I like music and outdoor sports. Because I have a broken ligament, I prefer safer activities like running or biking. In a couple of years, my ambition is to become a good technical lead with entrepreneurial mindset. From a personal point of view, I’d like to establish my own family, so I’ll have lots of things to do, there’s never time to get bored 😂

View all posts by afivan →