feat: Forward X-Forwarded-For header from incoming requests to upstream LLM APIs

该问题通常出现在 Open WebUI 部署在反向代理(如 NGINX、OpenShift Route)之后,且上游 LLM 服务(如 LiteLLM、llama-swap)需要基于客户端真实 IP 做统计或限流时。优先排查 Open WebUI 向 LLM 后端发起请求时,是否在构造 header

快速结论:该问题通常出现在 Open WebUI 部署在反向代理(如 NGINX、OpenShift Route)之后,且上游 LLM 服务(如 LiteLLM、llama-swap)需要基于客户端真实 IP 做统计或限流时。优先排查 Open WebUI 向 LLM 后端发起请求时,是否在构造 headers 后丢弃了带有真实客户端 IP 的 X-Forwarded-For 头;目前 Issue 中提供的是代码修改补丁,尚未合并到正式版本。

适用环境:Open WebUI(源码运行方式);反向代理/网关(NGINX、OpenShift Route 等);LLM 后端(LiteLLM、Ollama、llama-swap);相关文件:routers/openai.pyrouters/ollama.pyutils/tools.py。Issue 未提及操作系统、Python、CUDA、显卡等具体版本。

最快修复方案:暂无确认的一步修复方案。Issue 仅提供代码修改建议,需手动修改三个 Python 文件后在源码模式下运行,或等待官方合并到后续版本。

注意事项:修改代码后需要重启 Open WebUI 服务方可生效;补丁方案对三个文件的位置做了明确要求,如果版本不同,行号或上下文可能不一致,需要按注释标记的“自定义 headers 代码块之后”自行定位。另外上游 LiteLLM 只会转发 x-* 前缀的 headers,因此必须在 LiteLLM 转发逻辑之前注入该头。

问题场景

用户通过反向代理(NGINX、OpenShift Route 等)访问 Open WebUI,网关在请求头中添加 X-Forwarded-For: <真实客户端IP>。Open WebUI 收到请求后,在内部向 LLM 后端(LiteLLM、Ollama、llama-swap 等)发起 HTTP 调用时,却丢弃了该请求头,导致上游服务只能看到 Open WebUI 的 Pod IP 而非真实客户端 IP,从而无法完成基于来源 IP 的活动追踪。

报错原文

feat: Forward X-Forwarded-For header from incoming requests to upstream LLM APIs

- Gateway adds X-Forwarded-For: <real-client-ip> to the incoming request
- OpenWebUI receives the request with the header but discards it when making its own HTTP call to the LLM backend
- LiteLLM never sees the X-Forwarded-For header, so it cannot forward it to llama-swap
- llama-swap sees the OpenWebUI pod IP instead of the real client IP

原因分析

Open WebUI 在 routers/openai.pyget_headers_and_cookies()routers/ollama.pysend_request() 以及 utils/tools.pybuild_tool_server_headers() 中构造转发给上游 LLM 服务的 headers 时,只加入了自定义 headers 和用户信息等,并没有把传入请求中的 X-Forwarded-For 头复制到出站请求中。因此无论客户端或网关传入什么代理头,Open WebUI 作为中间层都会将其剥离。可能原因还包括:Open WebUI 侧没有统一处理标准代理头转发的逻辑,且 LiteLLM 的 _get_forwardable_headers() 只转发 x-* 前缀 headers,所以即使 LiteLLM 收到该头也会因为前缀问题被拦下。

环境排查

  • 确认 Open WebUI 是否通过源码运行(修改 Python 文件需要源码模式,Docker 官方镜像可能无法直接改文件)。
  • 确认 Open WebUI 版本与 Issue 中提出的三个文件路径是否一致。
  • 确认反向代理(NGINX、OpenShift Route)是否在传入请求中正确添加了 X-Forwarded-For 头,且未被 Open WebUI 外层再次覆盖。
  • 确认上游 LLM 后端是否确实在读取 X-Forwarded-For(如 llama-swap 的日志中显示 Pod IP 而非真实客户端 IP)。
  • 确认是否使用了 LiteLLM,并核对 LiteLLM 的转发逻辑是否会过滤掉 X-Forwarded-For(LiteLLM 只转发 x-* 前缀的 headers)。

解决步骤

  1. 定位到 routers/openai.py,在 get_headers_and_cookies() 的自定义 headers 代码块之后,插入以下逻辑:
    x_forwarded_for = request.headers.get("x-forwarded-for")
    if x_forwarded_for and "X-Forwarded-For" not in headers:
        headers["X-Forwarded-For"] = x_forwarded_for
  2. 定位到 routers/ollama.py,在 send_request() 的自定义 headers 代码块之后,插入相同的判断逻辑,注意外层包一层 if request: 判断。
  3. 定位到 utils/tools.py,在 build_tool_server_headers() 的 message_id 头处理代码块之后,插入相同的判断逻辑,同样需要 if request: 保护。
  4. 保存文件,重启 Open WebUI 服务(如为 Docker 部署需要重新构建镜像或在容器内直接修改后重启进程)。
  5. 如果上游使用 LiteLLM,确认 LiteLLM 转发逻辑在注入之后才执行,避免被 LiteLLM 的前缀过滤规则丢弃。
  6. 如不方便修改源码,可等待官方将本修改合并到正式版本后升级 Open WebUI。

验证方法

在反向代理日志中确认传入请求携带了 X-Forwarded-For: <真实客户端IP>,然后发起一次聊天请求,在 llama-swap 或上游 LLM 服务的访问日志中查看该请求的来源 IP。如果日志中显示的 IP 与真实客户端 IP 一致,而不是 Open WebUI Pod IP,说明转发已生效。也可以临时在上游服务中打印收到的所有 headers 来确认。

参考来源

open-webui/open-webui #28959

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 19930

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注