简体   繁体   中英

`X-Forwareded-For` is not used by ASP.Net Core behind reverse proxy

I am trying to get the remote IP address of a request (ie, the IP of the client who sent the request) in my ASP.Net Core 2.1 MVC Controller (runs in .Net Docker container). Taking into consideration that My ASP.Net Core application is located behind NGINX reverse proxy (runs in NGINX Docker container).

As known, when the reverse proxy redirects the request to my .Net Core application, it will change the source IP of my request (TCP/IP layer), therefore, I configured NGINX to add X-Forwareded-For with the original IP to the request. The request that is redirected from NGINX container to .Net container has X-Forwareded-For in the header:

在此处输入图片说明

And of course, I configured .Net Core to know about that:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
    // Rewrite the header when being redirected (this is required because we are behind reverse proxy)
    var forwardedHeadersOptions = new ForwardedHeadersOptions
    {
        ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
        KnownProxies = { IPAddress.Parse("172.20.10.2"), IPAddress.Parse("172.20.10.3"), IPAddress.Parse("172.20.10.4") },
    };

    forwardedHeadersOptions.KnownNetworks.Add(
        new IPNetwork(IPAddress.Parse("172.0.0.0"), 8));
    forwardedHeadersOptions.KnownNetworks.Add(
        new IPNetwork(IPAddress.Parse("127.0.0.1"), 8));

    app.UseForwardedHeaders(forwardedHeadersOptions);
    ...

However, HTTPContext.Connection.RemoteIPAddress still returning 172.20.10.3 (NGINX container IP, not the real remote IP):

logger.LogDebug("Remote IP Address: " + Request.HttpContext.Connection.RemoteIpAddress.ToString());

Remote IP Address: 172.20.10.3

I checked my header in .Net Core, it has X-Forwareded-For with the correct original remote IP address:

logger.LogDebug("X-Forwareded-For Header Feature: " + HttpContext.Request.Headers["X-Forwarded-For"]);

X-Forwareded-For Header Feature: 85.XX.4.121

Does someone have any idea what I am missing? Why RemoteIPAddress still returning the IP of the NGINX docker container instead of the real remote IP address?

Update

My Program.cs

public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseUrls("http://*:5000")
            .UseStartup<Startup>()
            .Build();
}

I tried Also to configure the the ForwarededHeadersOptions by configuring its service like this:

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    //options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("172.0.0.0"), 8));
    options.RequireHeaderSymmetry = false;
    options.ForwardLimit = null;
    options.KnownProxies.Add(IPAddress.Parse("172.20.10.3"));
    //options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("127.0.0.1"), 8));
});

With no success...

UPDATE 2

OK I guess I am on the right way, the IP address returned by RemoteIPAddress was ::ffff:172.20.10.20, not 172.20.10.20! I did not know that they are different. The official documentation helped me to discover that.

The IP I got from RemoteIPAddress was IPv4 represented as IPv6 (was ::ffff:172.20.10.20, not 172.20.10.20!). I was using only IPv4 part of the IP, therefore the KnownProxies in my case were wrong. I should have entered the full IPv4 address also with the v6 representation part.

The official documentation showed that:

https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1

UPDATE as requested by a comment:

So in my case, the code should look like this:

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    options.RequireHeaderSymmetry = false;
    options.ForwardLimit = null;
    options.KnownProxies.Add(IPAddress.Parse("::ffff:172.20.10.20")); // <<-- Notice the full format of the IP address.
});

As per the official documentation, if you are using Apache or Nginx integration , following code should be added to the Startup.ConfigureServices method.

// using Microsoft.AspNetCore.HttpOverrides;

    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();
    });

and then on top of everything, in Configure method use

app.UseForwardedHeaders();

Further suppose in nginx conf file, inside a location, use

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-Host $server_name;

Now the first entry in the X-Forwarded-For will be the real client IP.

IMPORTANT: If you want to secure the app and not allow an attacker inject X-Forwarded-For, Please following this Nginx Dealing with invalid headers

Please see Forward the scheme for Linux and non-IIS reverse proxies and Configure Nginx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM