反向代理后面的 ASP.Net Core 不使用 `X-Forwareded-For`

Moh*_*din 5 c# .net-core asp.net-core

我试图在我的ASP.Net Core 2.1 MVC 控制器(在 .Net Docker 容器中运行)中获取请求的远程 IP 地址(即发送请求的客户端的 IP )。考虑到我的 ASP.Net Core 应用程序位于 NGINX 反向代理之后(在 NGINX Docker 容器中运行)。

众所周知,当反向代理将请求重定向到我的 .Net Core 应用程序时,它会更改我请求的源 IP(TCP/IP 层),因此,我将 NGINX 配置为将X-Forwareded-For原始 IP添加到请求中。从 NGINX 容器重定向到 .Net 容器的请求X-Forwareded-For在标头中有:

在此处输入图片说明

当然,我配置了 .Net Core 以了解这一点:

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);
    ...
Run Code Online (Sandbox Code Playgroud)

但是,HTTPContext.Connection.RemoteIPAddress仍然返回172.20.10.3(NGINX容器IP,不是真正的远程IP):

logger.LogDebug("Remote IP Address: " + Request.HttpContext.Connection.RemoteIpAddress.ToString());
Run Code Online (Sandbox Code Playgroud)

远程 IP 地址:172.20.10.3

我在 .Net Core 中检查了我的标头,它具有X-Forwareded-For正确的原始远程 IP 地址:

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

X-Forwarded-For 标题功能:85.XX.4.121

有人知道我缺少什么吗?为什么 RemoteIPAddress 仍然返回 NGINX docker 容器的 IP 而不是真正的远程 IP 地址?

更新

我的 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();
}
Run Code Online (Sandbox Code Playgroud)

我还尝试ForwarededHeadersOptions通过像这样配置它的服务来配置它:

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));
});
Run Code Online (Sandbox Code Playgroud)

没有成功...

更新 2

好的,我想我走对了,返回的 IP 地址RemoteIPAddress是 ::ffff:172.20.10.20,而不是 172.20.10.20!我不知道他们是不同的。在官方文档帮助我发现。

Moh*_*din 12

我获得的 IPRemoteIPAddress是 IPv4,表示为 IPv6(是 ::ffff:172.20.10.20,而不是 172.20.10.20!)。我只使用了 IP 的 IPv4 部分,因此KnownProxies就我而言是错误的。我应该输入完整的 IPv4 地址以及 v6 表示部分。

官方文档显示:

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

根据评论的要求更新:

所以就我而言,代码应该如下所示:

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.
});
Run Code Online (Sandbox Code Playgroud)


Say*_*ood 11

根据官方文档,如果您使用Apache 或 Nginx 集成,则应将以下代码添加到Startup.ConfigureServices方法中。

// 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();
    });
Run Code Online (Sandbox Code Playgroud)

然后最重要的是,在Configure方法使用中

app.UseForwardedHeaders();
Run Code Online (Sandbox Code Playgroud)

进一步假设在 nginx conf 文件中的某个位置内,使用

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;
Run Code Online (Sandbox Code Playgroud)

现在,第一个条目X-Forwarded-For将是真实的客户端 IP。

重要提示:如果您想保护应用程序并且不允许攻击者注入 X-Forwarded-For,请阅读此答案

请参阅Linux 和非 IIS 反向代理的转发方案配置 Nginx处理无效标头