.Net核心X-Forwarded-Proto头无法正确传递到Nginx

byqmnocz  于 7个月前  发布在  Nginx
关注(0)|答案(6)|浏览(102)

对不起的编辑历史,但这个问题是真的不清楚我,很难找到确切的问题。
我有一个**.Net-CoreWeb应用程序,它在Nginx**后面运行,X-Forwarded-Proto总是传递http而不是https

Startup.cs

public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
            });

            services.AddMvc();

        }

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            //first middlewear
            app.UseForwardedHeaders();
             //and the rest
         }

字符串

Nginx配置文件

server {
    listen        80;
    server_name   example.com;
    location / {
        proxy_pass         http://localhost:5001/;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

Nginx.conf

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    #cloudflare real ip
    #https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs-Logging-visitor-IP-addresses-with-mod-cloudflare-#12345681
    set_real_ip_from 173.245.48.0/20;
    real_ip_header    X-Forwarded-For;
    real_ip_recursive on;

    log_format  main  '"$scheme" $remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

access.log记录

"http" 185.108.83.156 - - [03/Oct/2019:19:59:33 +0300] "GET /auth/signin/Facebook?returnUrl=%2F HTTP/1.1" 302 0 "https://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36" "156"


正如你所看到的,我记录的**$scheme总是HTTP**。
解决这个问题的一个解决方案是强制Scheme成为HTTPS,如下所示:

app.Use((context, next) =>
        {
            context.Request.Scheme = "https";
            return next();
        });


从https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.2#forwarded-headers-middleware-options下载
但是使用这个解决方案,我不传递头,并丢失了一些信息。
有没有人对这个案子有什么解决办法?

mwecs4sa

mwecs4sa1#

您的Startup.cs文件正常,但您没有为Kesterl配置ssl。
您需要为.net core应用程序配置X.509 ssl证书
来自https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-2.2#when-to-use-kestrel-with-a-reverse-proxy-1
只有反向代理服务器需要X.509证书,并且该服务器可以使用普通HTTP与内部网络上的应用程序服务器通信
所以,在你的情况下,你有7个主要步骤要做:

**1)从CloudFlare ORIGIN CA获取SSL证书 *2)在您的服务器上安装SSL证书 *3)创建PFX文件,以便您的Kesterl服务器可以读取它。*4)配置Kesterl https端点。5)修改Nginx服务器以侦听端口443,然后重定向到Kestrel侦听端口 6)根据您的配置修改服务文件 * 7)将Cloudflare更改为运行严格模式
步骤1 -从cloudflare获取ssl证书:

转到Cloudflare的 Jmeter 板并选择SSL/TLS --> Origin Server -->Create Certificate。按照说明操作,您将在过程结束时获得2个文件:example.com.keyexample.com.pem

第2步-将文件放在您的服务器上的etc/ssl文件夹
第3步-创建PFX文件,以便Kesterl可以使用证书:

在你的服务器上运行这个:

openssl pkcs12 -export -out example.pfx -inkey example.com.key -in example.com.pem

字符串
这将生成example.pfx,将其放在同一个文件夹中。

步骤4 -配置Kesterl https端点。

从第3步开始,您应该已经获得了在此步骤中需要使用的密码。
在您的appsetting.json中放置以下行:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "Kestrel": {
    "Endpoints": {
      "HTTPS": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "/etc/ssl/example.pfx",
          "Password": "**********"
        }
      }
    }
  }

Step 5 -配置Nginx监听443端口,如下所示:

server {
    #listen        80;
    listen                 *:443 ssl;
    ssl_certificate        /etc/ssl/example.pem;
    ssl_certificate_key    /etc/ssl/example.key;
    server_name            example.com
    location / {
        proxy_pass         https://localhost:5001/;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

第六步-配置服务文件:

[Unit]
    Description=example

    [Service]
    WorkingDirectory=/var/www/example
    ExecStart=/usr/bin/dotnet /var/www/example/exampleSite.dll
    Restart=always
    # Restart service after 10 seconds if the dotnet service crashes:
    RestartSec=10
    KillSignal=SIGINT
    SyslogIdentifier=example
    User=www-data
    Environment=ASPNETCORE_ENVIRONMENT=Staging
    Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
    Environment=ASPNETCORE_HTTPS_PORT=5001
    Environment=ASPNETCORE_URLS=https://localhost:5001

    [Install]
    WantedBy=multi-user.target

第7步-在SSL/TLS上更改Cloudflare以使用严格模式

重新启动你的应用程序+ Nginx,你的服务器现在应该像这样工作:
请求--> Cloudflare(HTTPS)--> Nginx(HTTPS)--> Example.com

11dmarpk

11dmarpk2#

你只在80端口上运行nginx,没有ssl,所以,$scheme变量将永远是http。参见http://nginx.org/r/$scheme
如果您关心HTTPS,那么也使用HTTPS保护Cloudflare和后端之间的连接可能是一个好主意;这样,您的$scheme变量将被正确填充。否则,您也可以硬编码https来代替$scheme,但这样就无法在真实的和最终的.Net后端上进行条件测试和重定向。

wfsdck30

wfsdck303#

一般来说,HTTP的Header不接受非ASCII字符。URL在生成时必须正确编码,Redirect方法不会为您做这件事。
一个快速修复可能是使用WebUtility.UrlEncode

using System.Net;
// ...
var encodedLocationName = WebUtility.UrlEncode(locationName);
return Redirect("~/locations/" + encodedLocationName);

字符串

j5fpnvbx

j5fpnvbx4#

请在nginx文件中设置适当的字符集。
以下是文档http://nginx.org/en/docs/http/ngx_http_charset_module.html#charset_types

pdtvr36n

pdtvr36n5#

这看起来是你的NGinx文件和Cloudflare设置方式的问题。从配置中,你的设置是
HTTPS->Cloudflare->HTTP->您的服务器
这就是为什么Scheme在你的nginx日志中总是“http”。由于Cloudflare通过HTTP将请求传递到你的服务器。你应该在Cloudflare和你之间设置TLS,这将在你的nginx配置上启用端口443,这将把scheme设置为HTTPS。强迫dotnet相信它是通过HTTPS处理的是无效的,因为Cloudflare正在通过公共互联网发送未加密的客户端数据。
https://support.cloudflare.com/hc/en-us/articles/115000479507-Managing-Cloudflare-Origin-CA-certificates
Cloudflare的文档列出了如何使用NGinx进行设置。

lo8azlld

lo8azlld6#

我也遇到过类似的问题。默认情况下,ForwardedHeadersOptions.KnownProxies只允许代理IP为127.0.0.1- Source。如果启用Microsoft: Debug日志,您将看到类似以下内容:
[12:25:25 DBG] Unknown proxy: [::ffff:x.x.x.x]:xxxxx的值。该值为
要解决此问题,您需要允许任何代理IP或将您的代理IP添加到KnownProxies和KnownNetworks

services.Configure<ForwardedHeadersOptions>(opts =>
{
    opts.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    opts.KnownNetworks.Clear();
    opts.KnownProxies.Clear();
    opts.KnownProxies.Add(IPAddress.Any);
    opts.KnownNetworks.Add(new IPNetwork(IPAddress.Any, 0));
});

字符串

相关问题