Exploring the Forwarded Headers Middleware in ASP.NET Core

Exploring the Forwarded Headers Middleware in ASP.NET Core

Proxies are vital for load balancing and security, but they obscure the actual client IP, scheme, and domain, causing broken links, inaccurate logging, and other headaches. In this post, we’ll look at how ASP.NET Core’s Forwarded Headers Middleware restores these details so your services behave as though they’re directly on the public internet.

What is the Forwarded Headers Middleware?

In ASP.NET Core, requests travel through a pipeline made of various middleware components. The Forwarded Headers Middleware is one such component that often comes pre-configured (or can be easily enabled) to handle forwarded headers from proxies. It’s typically placed among the first modules in the pipeline, as shown below:

Example of the ASP.NET Core request pipeline with the Forwarded Headers middleware

What problem does the Forwarded Headers Middleware solve?

In many scenarios, our services and applications are deployed behind a proxy server, which may serve various roles, such as:

  • Load balancer
  • Web Application Firewall (WAF)
  • Reverse proxy
  • Content cache
  • TLS Termination

The example below shows three service instances behind a proxy, acting as a load balancer.

three service instances behind a proxy, acting as a load balancer.

The general problem is that the details about the original request are lost as it passes through the proxy.

Shows how the internal service belives it is hosted as http://service1

In other scenarios, a single proxy might manage traffic for multiple domain names, and the services need to identify the original request to return the correct content to the caller.

How a proxy can have multiple public domains

Making ASP.NET Core Services Proxy-Aware

The goal is to make the internal services act as though they are directly accessible on the public internet, even though they are behind a proxy.

To solve this, we somehow need to:

  • Recognize the public URL that the user accessed instead of the internal network address.
  • Identify the original client IP address rather than the IP address of the proxy.
  • Determine the scheme of the original request (HTTP or HTTPS).

As shown below, we want the application in service1 to believe it received a request to https://tn-data.se rather than http://service1.

How we want the service to belive it is hosted on the public internet

Let’s get a bit more technical

Let’s dive a bit deeper into the technical details. Imagine a setup with a proxy sitting between the client and the service:

example setup of a proxy and a service

How can we make Service1 behave as if it received a request from IP 193.8.1.12 to https://tn-data.se instead of IP 10.0.0.1 to http://service1?

Introducing the X-Forwarded Headers

The first step is configuring the proxy to add a set of headers to the outgoing request describing the original request received by the proxy.

Hows how the proxy sets the x-forwarded-* headers

The X-Forwarded-* headers are special HTTP headers that help servers understand where a request came from when it passes through intermediaries like proxies or load balancers. They provide essential details such as the original client’s IP address, the protocol used, and the host requested.

Proxies can add these headers to the request, informing the service about the originating IP, scheme, and host.

Let’s explore how we handle this in ASP.NET Core next.

ASP.NET Core and the X-Forwarded Headers

The Forwarded Headers Middleware is responsible for rewriting the request when these headers are present in the incoming request.

Using the details from the above example, here’s what happens to the request as it passes through the middleware:

How the forwarded headers middleware rewrites the request

Steps taken:

  • The middleware adds X-Original-* headers to the request, containing details about the current request.
  • It then rewrites the request based on the information found in the X-Forwarded-* headers.

Forwarded Headers in Azure Container Apps

To observe these headers in action, we can deploy my open-source Cloud Debugger tool as an Azure Container App. This tool allows us to inspect the request before and after this middleware has processed it.

Example from the Cloud Debugger showing the raw and final reuest details

For example, in the image above:

  • The request scheme has been updated from HTTP to HTTPS.
  • The sender’s IP address has changed from ::ffff:100.100.0.60 (a local IPv6 Azure address) to 193.150.241.131 (my computer’s public IP address).
  • The ::ffff:x.x.x.x format is an IPv6 representation of an IPv4 address, mapping it into the IPv6 space.

This shows how the middleware reconstructs the original request context using the X-Forwarded-* headers.

In the cloud debugger for Azure, we also get this nice overview of the headers:

Example from the Cloud Debugger, comparing the headers before and after.

Here, two X-Forwarded-* headers are received, and two corresponding X-Original-* headers are created with the updated information.

What About Security?

The Forwarded Headers Middleware offers several ways to validate and control how X-Forwarded-* headers are processed. Because blindly trusting them can be risky. Attackers or misconfigured proxies might send bogus headers, leading to incorrect IP addresses, spoofed schemes, and other vulnerabilities. In a future post, we’ll explore best practices to secure and configure these headers properly, including limiting trusted networks and carefully validating header values.

Summary

In this blog post, I examined the purpose and functionality of the Forwarded Headers Middleware in ASP.NET Core. This middleware processes X-Forwarded-* headers to restore information about the original request, including the client’s IP address, the request scheme (HTTP or HTTPS), and the public URL. The middleware modifies the request with these details while preserving the original values in dedicated headers for reference.

In a future post, I’ll provide a hands-on guide to configuring and working with these headers in your applications.

About the Author

Hi, I’m Tore! I have been fascinated by computers since I unpacked my first Commodore VIC-20. Today, I enjoy providing freelance development and developer training services, focusing on ASP.NET Core, IdentityServer, OpenID Connect, Architecture, and Web Security. You can connect with me on LinkedIn and BlueSky, and you can find out more about me and my services here, as well as my courses for developers. Tore is also a Microsoft .NET MVP.

Resources

More Blog Posts by the Author

Share This Story

Related Posts

About Tore Nestenius - Freelance software development instructor and consultant.

About me

My name is Tore Nestenius and I’m a trainer and senior software developer focusing on Architecture, Security and Identity, .NET, C#, Backend, and Cloud, among other things.

Do You Want Tore To Be Your Mentor?

Categories