ASP.NET Core无法识别Forwarded Headers问题求助
问题描述
ASP.NET Core 应用部署链路为:浏览器 > Cloudflare > NGINX > Docker > 应用。已配置Forwarded Headers但未生效,具体表现:
RemoteIpAddress显示Docker网关IP(::ffff:172.18.0.1)而非真实用户IPRequest.Scheme显示http而非转发的https- 已确认Cloudflare的IP段(如
162.158.0.0/15)已加入信任列表,且X-Forwarded-For中的代理IP属于该信任段
相关配置与日志
Program.cs 关键配置
// Fetch Cloudflare IP ranges if not in dev env IList<string> cloudflareRanges = []; if (!builder.Environment.IsDevelopment()) { using SocketsHttpHandler handler = new() { PooledConnectionLifetime = TimeSpan.FromMinutes(2) }; using HttpClient httpClient = new(handler, disposeHandler: false); string list = await httpClient.GetStringAsync("https://www.cloudflare.com/ips-v4/"); string[] ranges = list.Split("\n"); foreach (string range in ranges) cloudflareRanges.Add(range); } builder.Services.Configure<ForwardedHeadersOptions>(async options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; if (!builder.Environment.IsDevelopment()) { options.ForwardLimit = 1; // Trust Cloudflare's IP ranges foreach (string range in cloudflareRanges) { string[] parts = range.Split('/'); options.KnownIPNetworks.Add(new System.Net.IPNetwork( IPAddress.Parse(parts[0]), int.Parse(parts[1]))); } } }); var app = builder.Build(); ILogger<Program> logger = app.Services.GetRequiredService<ILogger<Program>>(); logger.LogInformation("Running in {0} environment", app.Environment.EnvironmentName); IList<System.Net.IPNetwork> knownIPNetworks = app.Services.GetRequiredService<IOptions<ForwardedHeadersOptions>>().Value.KnownIPNetworks; logger.LogInformation( "The following {0} IP ranges will be trusted: {1}", knownIPNetworks.Count, string.Join(", ", knownIPNetworks.Select(n => $"{n.BaseAddress}/{n.PrefixLength}"))); app.UseForwardedHeaders(); app.Use(async (context, next) => { Console.WriteLine($"RemoteIpAddress: {context.Connection.RemoteIpAddress}"); Console.WriteLine($"X-Forwarded-For: {context.Request.Headers["X-Forwarded-For"]}"); Console.WriteLine($"X-Forwarded-Proto: {context.Request.Headers["X-Forwarded-Proto"]}"); Console.WriteLine($"Scheme: {context.Request.Scheme}"); await next(); }); // 其余中间件注册省略 app.Run();
(注:重复的UseRouting()调用为内部重写所需,用于获取端点元数据)
应用启动日志
info: Program[0] Running in Production environment info: Program[0] The following 16 IP ranges will be trusted: 127.0.0.0/8, 173.245.48.0/20, 103.21.244.0/22, 103.22.200.0/22, 103.31.4.0/22, 141.101.64.0/18, 108.162.192.0/18, 190.93.240.0/20, 188.114.96.0/20, 197.234.240.0/22, 198.41.128.0/17, 162.158.0.0/15, 104.16.0.0/13, 104.24.0.0/14, 172.64.0.0/13, 131.0.72.0/22
NGINX 配置
server { listen 80; server_name example.com; # Redirect all HTTP traffic to HTTPS return 301 https://$host$request_uri; } server { listen 443 ssl; server_name example.com; # SSL Configuration ssl_certificate /etc/ssl/certs/app-cloudflare.pem; ssl_certificate_key /etc/ssl/private/app-cloudflare.key; access_log /var/log/nginx/app_headers.log debug_proxy_headers; location / { proxy_pass http://localhost:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; 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; } } # Map block to handle WebSocket connection upgrades dynamically map $http_upgrade $connection_upgrade { default upgrade; '' close; }
NGINX 访问日志(app_headers.log)
"GET / HTTP/1.1" 200 316 Host: "example.com" X-Forwarded-For: "MY_IP_ADDRESS, 162.158.116.84" X-Forwarded-Proto: "https" Scheme: "https"
应用输出日志
2026-05-17T13:17:32.592944997Z RemoteIpAddress: ::ffff:172.18.0.1 2026-05-17T13:17:32.592972238Z X-Forwarded-For: MY_IP_ADDRESS, 162.158.116.145 2026-05-17T13:17:32.592975118Z X-Forwarded-Proto: https 2026-05-17T13:17:32.592988278Z Scheme: http
解决方案
1. 修复ForwardedHeadersOptions的异步配置问题
Configure<ForwardedHeadersOptions>不支持异步委托,会导致Cloudflare IP段未正确加载到信任列表中。修改为同步获取IP段:
// 替换原异步获取IP段逻辑 if (!builder.Environment.IsDevelopment()) { using var handler = new SocketsHttpHandler { PooledConnectionLifetime = TimeSpan.FromMinutes(2) }; using var httpClient = new HttpClient(handler, disposeHandler: false); // 同步获取Cloudflare IP段 string list = httpClient.GetStringAsync("https://www.cloudflare.com/ips-v4/").GetAwaiter().GetResult(); // 移除空行和换行符 string[] ranges = list.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); foreach (string range in ranges) if (!string.IsNullOrWhiteSpace(range)) cloudflareRanges.Add(range); } // 配置ForwardedHeadersOptions使用同步委托 builder.Services.Configure<ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; if (!builder.Environment.IsDevelopment()) { options.ForwardLimit = 1; options.KnownProxies.Clear(); // 清空默认信任的代理 // 添加Cloudflare IP段到信任列表 foreach (string range in cloudflareRanges) { string[] parts = range.Split('/'); options.KnownIPNetworks.Add(new System.Net.IPNetwork( IPAddress.Parse(parts[0]), int.Parse(parts[1]))); } // 额外信任直接转发请求的Docker网关IP options.KnownProxies.Add(IPAddress.Parse("172.18.0.1")); } });
2. 调整中间件顺序
确保UseForwardedHeaders是第一个被调用的中间件,在所有请求处理中间件之前:
var app = builder.Build(); // 日志输出部分保留 // 必须放在最前面 app.UseForwardedHeaders(); // 之后再注册其他中间件 app.Use(async (context, next) => { Console.WriteLine($"RemoteIpAddress: {context.Connection.RemoteIpAddress}"); Console.WriteLine($"X-Forwarded-For: {context.Request.Headers["X-Forwarded-For"]}"); Console.WriteLine($"X-Forwarded-Proto: {context.Request.Headers["X-Forwarded-Proto"]}"); Console.WriteLine($"Scheme: {context.Request.Scheme}"); await next(); }); app.UseHttpsRedirection(); app.UseRequestLocalization(); // 其余中间件注册保留
3. 优化NGINX转发配置
修改X-Forwarded-For配置,避免NGINX添加自身IP到转发头中,符合ForwardLimit=1的信任逻辑:
# 替换原X-Forwarded-For配置 proxy_set_header X-Forwarded-For $http_x_forwarded_for;
4. 启用调试日志排查
添加日志过滤,查看ForwardedHeaders中间件的处理细节:
builder.Logging.AddFilter("Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware", LogLevel.Debug);
启动后检查日志,确认是否有“Trusted proxy detected”相关调试信息,验证信任IP是否被正确识别。
内容的提问来源于stack exchange,提问作者iKingNinja
相关产品推荐
相关产品推荐

