You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Ocelot网关中保留客户端IP至指定HTTP请求头的方案咨询

解决Ocelot网关转发时将客户端IP放入Host/Referrer/Origin头的方案

问题原因

你之前的ASP.NET自定义中间件无效,是因为Ocelot在转发请求时会构建独立的DownstreamRequest对象,原始HttpContext的修改不会同步到这个转发请求中,必须在Ocelot自身的中间件管道内修改下游请求头。

可行方案

方案一:自定义Ocelot中间件修改下游请求头

Ocelot提供了扩展中间件的能力,可以在其请求处理流程中直接修改要转发给微服务的请求头。

  1. 创建Ocelot自定义中间件
using Ocelot.Middleware;
using Ocelot.Responses;

public class ClientIpHeaderMiddleware : Ocelot.Middleware.IMiddleware
{
    public async Task Invoke(DownstreamContext context, RequestDelegate next)
    {
        // 获取客户端真实IP:优先读取X-Forwarded-For(适配反向代理场景),否则取RemoteIpAddress
        var clientIp = context.HttpContext.Connection.RemoteIpAddress?.ToString();
        
        if (!string.IsNullOrEmpty(context.HttpContext.Request.Headers["X-Forwarded-For"]))
        {
            // X-Forwarded-For可能包含多个代理IP,取第一个即为客户端真实IP
            clientIp = context.HttpContext.Request.Headers["X-Forwarded-For"].ToString()
                .Split(',')[0].Trim();
        }

        if (!string.IsNullOrEmpty(clientIp))
        {
            // 选择目标头:以下以Origin为例,可替换为Host或Referrer
            context.DownstreamRequest.Headers.Remove("Origin");
            context.DownstreamRequest.Headers.Add("Origin", clientIp);

            // 若要设置Host头,可使用以下代码(注意:可能影响微服务路由逻辑,需确认微服务兼容性)
            // context.DownstreamRequest.Headers.Remove("Host");
            // context.DownstreamRequest.Headers.Add("Host", clientIp);
        }

        await next.Invoke(context);
    }
}
  1. 注册并插入中间件到Ocelot管道
    在Program.cs中配置Ocelot时,将自定义中间件插入到路由查找完成后的节点:
var builder = WebApplication.CreateBuilder(args);

// 添加Ocelot服务并注册自定义中间件
builder.Services.AddOcelot()
    .AddMiddleware<ClientIpHeaderMiddleware>();

var app = builder.Build();

// 若网关前有反向代理(如Nginx),需配置ForwardedHeaders以获取真实客户端IP
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
    KnownProxies = { IPAddress.Parse("127.0.0.1") } // 按需添加信任的代理IP,生产环境需调整
});

// 配置Ocelot管道,将自定义中间件插入到路由查找中间件之后
await app.UseOcelot(config =>
{
    config.PreMiddlewarePipeline.UseDownstreamRouteFinderMiddleware();
    config.PreMiddlewarePipeline.Use<ClientIpHeaderMiddleware>();
});

app.Run();

方案二:结合X-Forwarded-For配置与Ocelot中间件复制头

如果你已经通过AddHeadersToRequest配置让Ocelot自动添加X-Forwarded-For头,可简化中间件逻辑,直接将该头的值复制到目标头:

public class ClientIpHeaderMiddleware : Ocelot.Middleware.IMiddleware
{
    public async Task Invoke(DownstreamContext context, RequestDelegate next)
    {
        if (context.DownstreamRequest.Headers.TryGetValue("X-Forwarded-For", out var ipValues))
        {
            var clientIp = ipValues.FirstOrDefault()?.Split(',')[0].Trim();
            if (!string.IsNullOrEmpty(clientIp))
            {
                context.DownstreamRequest.Headers.Remove("Origin");
                context.DownstreamRequest.Headers.Add("Origin", clientIp);
            }
        }

        await next.Invoke(context);
    }
}

此方案需确保Ocelot配置中已开启AddHeadersToRequest:

"AddHeadersToRequest": {
  "X-Forwarded-For": "true"
}

注意事项

  • 修改Host头可能导致微服务路由异常,建议优先选择Origin或Referrer(若业务允许)。
  • 生产环境中配置ForwardedHeaders时,需严格限制KnownProxies或KnownNetworks,避免IP伪造。

内容的提问来源于stack exchange,提问作者maryam mohammadbagheri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 00:37:44