很抱歉,编辑历史记录,但是这个问题对我来说真的很不清楚,很难找到确切的问题。
我有一个 .Net-Core Web应用程序,该应用程序在 Nginx 之后运行,并且 X-Forwarded-Proto 始终通过{{1 }},而不是http
。
Startup.cs
https
Nginx conf
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.conf
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;
}
}
access.log记录
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;
您可以看到我登录的 $ scheme 总是 HTTP 。
解决此问题的一种方法是将Scheme强制为 HTTPS ,如下所示:
"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"
但是使用这种解决方案,我不会传递标头,并且会丢失一些信息。
那么有人对此案有解决方案吗?
答案 0 :(得分:1)
您的Startup.cs文件很好,但是您没有为Kesterl配置ssl。
您需要为.net核心应用程序配置X.509 ssl证书
仅反向代理服务器需要X.509证书,并且该证书 服务器可以与内部网络上的应用服务器通信 使用纯HTTP
因此,您需要执行7个主要步骤:
1)从CloudFlare ORIGIN CA获取SSL证书
2)在您的服务器中安装ssl证书
3)创建一个PFX文件,以便您的Kesterl Server可以读取它。
4)配置Kesterl https端点。
5)修改您的Nginx服务器以监听端口443,然后重定向到Kestrel监听端口
6)根据您的配置修改服务文件
7)将Cloudflare更改为运行严格模式
步骤1-从cloudflare获取ssl证书:
转到Cloudflare的信息中心,然后选择SSL / TLS->原始服务器->创建证书。
按照说明进行操作,然后在过程结束时将有2个文件:
example.com.key
example.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": "**********"
}
}
}
}
第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;
}
}
第6步-像这样配置服务文件:
[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
答案 1 :(得分:0)
通常,HTTP标头不接受非ASCII字符。生成的Urls必须正确编码,Redirect方法无法为您完成。
快速修复可能是使用WebUtility.UrlEncode
using System.Net;
// ...
var encodedLocationName = WebUtility.UrlEncode(locationName);
return Redirect("~/locations/" + encodedLocationName);
答案 2 :(得分:0)
这似乎与NGinx文件和Cloudflare的设置方式有关。在配置中,您设置为
HTTPS-> Cloudflare-> HTTP->您的服务器
这就是为什么Scheme在您的nginx日志中始终为“ http”的原因。当Cloudflare通过HTTP将请求传递到您的服务器时。您应该在Cloudflare和您之间设置TLS,这将在nginx配置上启用端口443,这会将方案设置为HTTPS。强迫dotnet相信它是通过HTTPS处理的,这是无效的,因为Cloudflare正在通过公共Internet发送未加密的客户数据。
Cloudflare的文档列出了如何使用NGinx进行设置。
答案 3 :(得分:0)
您仅在端口80上运行nginx而没有ssl,因此$scheme
变量将始终为http
。参见http://nginx.org/r/$scheme。
如果您关心https,那么通过HTTPS保护Cloudflare和您的后端之间的连接也是一个好主意;这样,您的$scheme
变量将被正确填充。否则,您也可以用硬编码https
代替$scheme
,但是这样就无法达到进行条件测试和在真正的最终Net后端进行重定向的目的。
答案 4 :(得分:-1)
请在您的nginx文件中设置适当的字符集。
这里是文档 http://nginx.org/en/docs/http/ngx_http_charset_module.html#charset_types