快速结论:该问题通常出现在 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.py、routers/ollama.py、utils/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.py 的 get_headers_and_cookies()、routers/ollama.py 的 send_request() 以及 utils/tools.py 的 build_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)。
解决步骤
- 定位到
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 - 定位到
routers/ollama.py,在send_request()的自定义 headers 代码块之后,插入相同的判断逻辑,注意外层包一层if request:判断。 - 定位到
utils/tools.py,在build_tool_server_headers()的 message_id 头处理代码块之后,插入相同的判断逻辑,同样需要if request:保护。 - 保存文件,重启 Open WebUI 服务(如为 Docker 部署需要重新构建镜像或在容器内直接修改后重启进程)。
- 如果上游使用 LiteLLM,确认 LiteLLM 转发逻辑在注入之后才执行,避免被 LiteLLM 的前缀过滤规则丢弃。
- 如不方便修改源码,可等待官方将本修改合并到正式版本后升级 Open WebUI。
验证方法
在反向代理日志中确认传入请求携带了 X-Forwarded-For: <真实客户端IP>,然后发起一次聊天请求,在 llama-swap 或上游 LLM 服务的访问日志中查看该请求的来源 IP。如果日志中显示的 IP 与真实客户端 IP 一致,而不是 Open WebUI Pod IP,说明转发已生效。也可以临时在上游服务中打印收到的所有 headers 来确认。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


