如何防止修改请求X-Real-IP后AspNetCoreRateLimit限流规则重置的安全问题
AspNetCoreRateLimit X-Real-IP伪造限流失效修复方案
漏洞根源
当前配置下AspNetCoreRateLimit会优先读取X-Real-IP请求头的值作为客户端IP做限流计数,未校验该请求头的来源是否可信,攻击者可随意修改这个请求头绕过限流规则。
修复方案
- 方案1:配置可信反向代理规则(推荐,适用于服务前置Nginx/负载均衡的场景)
在注册AspNetCoreRateLimit中间件之前,先配置ASP.NET Core自带的转发头中间件,仅信任指定代理服务器传递的IP头:
// 需放在所有中间件注册逻辑的最顶部 builder.Services.Configure<ForwardedHeadersOptions>(options => { options.ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedFor | Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedProto; // 添加你实际使用的反向代理的内网IP,只有这些代理传递的头才会被认可 options.KnownProxies.Add(System.Net.IPAddress.Parse("192.168.1.100")); // 同网段代理可配置网段规则 // options.KnownNetworks.Add(new Microsoft.AspNetCore.HttpOverrides.IPNetwork(System.Net.IPAddress.Parse("192.168.1.0"), 24)); // 指定用X-Real-IP作为真实IP读取头,和你现有限流配置对应 options.ForwardedForHeaderName = "X-Real-IP"; }); // 注册转发头中间件,必须放在AspNetCoreRateLimit中间件之前 app.UseForwardedHeaders(); // 原有的限流中间件注册 // app.UseIpRateLimiting();
- 方案2:自定义IP解析逻辑(适用于需要灵活控制IP读取规则的场景)
自定义IP解析器,仅当请求来自可信代理时才读取X-Real-IP头,否则直接取TCP连接原始IP:
public class CustomIpAddressParser : IIpAddressParser { private readonly IIpAddressParser _defaultImpl; // 替换为你的可信代理IP列表 private readonly List<IPAddress> _trustedProxies = new List<IPAddress> { IPAddress.Parse("192.168.1.100") }; public CustomIpAddressParser(IIpAddressParser defaultImpl) { _defaultImpl = defaultImpl; } public IPAddress ParseIp(HttpContext httpContext) { var connectIp = httpContext.Connection.RemoteIpAddress; // 直连IP不是可信代理,直接用连接IP做限流,忽略请求头 if (!_trustedProxies.Contains(connectIp)) { return connectIp; } // 可信代理请求,走默认逻辑读取X-Real-IP return _defaultImpl.ParseIp(httpContext); } // 其余接口方法直接调用默认实现即可 public bool IsIpInList(string clientIp, List<string> ipList) => _defaultImpl.IsIpInList(clientIp, ipList); public bool ValidateIp(string ipAddress) => _defaultImpl.ValidateIp(ipAddress); }
注册自定义解析器替换默认实现:
builder.Services.AddSingleton<IIpAddressParser, CustomIpAddressParser>();
- 方案3:禁用请求头IP读取(适用于服务直接对外暴露,无反向代理的场景)
直接修改限流配置,把RealIpHeader设为空字符串即可,框架会直接读取TCP连接的原始IP作为客户端IP,不会解析任何请求头内容:
"IpRateLimiting": { "RealIpHeader": "", // 其余原有配置保持不变 ... }
注意:如果服务前置了反向代理不要直接使用方案3,否则会把代理IP识别为所有用户的IP,导致正常用户被误限流。
内容的提问来源于stack exchange,提问作者samin.hma
相关产品推荐
相关产品推荐

