Handling Forwarded Headers in ASP.NET Core with Nginx

Ejan ShresthaEjan Shrestha
2 min read

When hosting an ASP.NET Core application behind a reverse proxy like Nginx, you must configure your app to handle forwarded headers properly. This ensures that properties like Request.Scheme, Request.Host, and HttpContext.Connection.RemoteIpAddress reflect the original client values, not the proxy.

Why Forwarded Headers Matter

When a client makes a request to your app through a proxy (like Nginx), the original request metadata is hidden from the app unless forwarded explicitly. To preserve these details:

  • Nginx forwards the headers (e.g., X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Host).

  • ASP.NET Core must be told to trust and read those headers.

If you don’t configure this correctly:

  • Request.Scheme might return http even when the client used HTTPS.

  • Request.Host may show localhost or proxy IP instead of the original host.

  • HttpContext.Connection.RemoteIpAddress will reflect the proxy's IP.

Nginx Configuration for Forwarded Headers

Here is the correct Nginx server block configuration to forward the necessary headers:

server {
    listen 443 ssl;
    server_name your-domain.com;

    location / {
        proxy_pass http://localhost:5000;  # Your .NET app port
        proxy_http_version 1.1;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_cache_bypass $http_upgrade;
    }

    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

Remember to replace your-domain.com and app port appropriately.

ASP.NET Core Configuration

In your Program.cs or Startup.cs, you must enable forwarded headers middleware early in the pipeline:

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                       ForwardedHeaders.XForwardedProto |
                       ForwardedHeaders.XForwardedHost,
    KnownProxies = { IPAddress.Parse("127.0.0.1") } // or the IP of your reverse proxy
});

Middleware Placement

Ensure UseForwardedHeaders() is placed before any middleware that relies on HttpContext (like UseRouting, UseAuthentication, etc.).

Security Consideration: Header Spoofing

ASP.NET Core does not trust forwarded headers by default for security reasons. Without validation, a malicious client could send spoofed X-Forwarded-For or X-Forwarded-Proto headers directly and trick your app.

How to Secure It

  • Use KnownProxies if your proxy has a fixed IP:

      options.KnownProxies.Add(IPAddress.Parse("127.0.0.1"));
    
  • Use KnownNetworks if you're behind a load balancer or container network:

      options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8));
    

This ensures ASP.NET Core will only process forwarded headers from trusted sources.

Summary

  • Configure Nginx to forward all necessary headers.

  • Configure ASP.NET Core to read and trust those headers using UseForwardedHeaders().

  • Protect your app from header spoofing by explicitly listing KnownProxies or KnownNetworks.

  • Always test your setup with:

      sudo nginx -t && sudo systemctl reload nginx
    

With this setup, your ASP.NET Core app will correctly reflect the original request information, even when running behind a reverse proxy like Nginx.

0
Subscribe to my newsletter

Read articles from Ejan Shrestha directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ejan Shrestha
Ejan Shrestha