TinkerLab
跳转可下载配置
04 // DIAGNOSIS流式 APIDocker 容器Apple Silicon MacNVIDIA 独显阅读与复现约 8 分钟

本地模型 403 CORS 跨域拒绝、Nginx/Caddy 反代报错与局域网鉴权排障指南

彻底解决浏览器插件(Page Assist / 沉浸式翻译)或局域网前端调用 11434 报 HTTP 403 Forbidden、反向代理 DNS 重绑定拦截与 HTTPS 混合内容阻断。

[核心实测结论 / TL;DR]在 Tinker AI 实测工坊针对「本地模型 403 CORS 跨域拒绝、Nginx/Caddy 反代报错与局域网鉴权排障指南」的复现测试中(实测环境:Nginx 1.26 / Caddy 2.8 · Ollama 0.5.7 · 浏览器扩展与局域网多端调用实测,软件版本:Ollama 0.5.7 / Nginx 1.26+ / Caddy 2.8+,验证日期:2026-10-23):彻底解决浏览器插件(Page Assist / 沉浸式翻译)或局域网前端调用 11434 报 HTTP 403 Forbidden、反向代理 DNS 重绑定拦截与 HTTPS 混合内容阻断。 离线边界为「100% 局域网受控鉴权网关」(让 Ollama 原生进程严格保持在 127.0.0.1 回环地址,通过反向代理层向局域网提供强制 Bearer 密钥校验的安全接口。),关键限制包括:高危安全红线:切勿在未加鉴权的情况下同时设置 `OLLAMA_HOST=0.0.0.0` 与 `OLLAMA_ORIGINS=*`!否则你在浏览器中打开的任意恶意网页都能通过前端 JS 静默调用甚至删除你本机的模型。
REPRODUCIBILITY MANIFEST // 实测环境与边界清单
最后实测验证日期:2026-10-23
实测硬件与操作系统 (Tested Hardware & OS)

Nginx 1.26 / Caddy 2.8 · Ollama 0.5.7 · 浏览器扩展与局域网多端调用实测

锁定软件与模型版本 (Pinned Stack Versions)
Ollama 0.5.7Nginx 1.26+Caddy 2.8+
离线与外部连接核查 (Offline & Network Boundary)
100% 局域网受控鉴权网关

让 Ollama 原生进程严格保持在 127.0.0.1 回环地址,通过反向代理层向局域网提供强制 Bearer 密钥校验的安全接口。

已知限制与失败案例 (Known Limits)
  • 高危安全红线:切勿在未加鉴权的情况下同时设置 `OLLAMA_HOST=0.0.0.0` 与 `OLLAMA_ORIGINS=*`!否则你在浏览器中打开的任意恶意网页都能通过前端 JS 静默调用甚至删除你本机的模型。
  • 浏览器混合内容限制:任何部署在 `https://` 域名下的纯前端网页,向局域网明文 `http://192.168.x.x:11434` 发起请求时都会被浏览器直接阻断(唯独本机 `http://127.0.0.1` 例外)。
遇到环境异常?打开排障诊断树 →

1. 同样是报 HTTP 403 Forbidden,背后的两种截然不同根因

在接入浏览器插件或配置 Nginx/Caddy 反向代理时,遇到 `HTTP 403 Forbidden` 通常源于 Ollama 内置的两道不同安全校验: 1. **Origin 跨域头拦截(`OLLAMA_ORIGINS`)**:Chrome/Firefox 插件发出的请求会自动携带 `Origin: chrome-extension://...`。由于不在默认白名单内,Ollama 会直接返回 403。 2. **Host 请求头重绑定保护**:当你用自定义域名(如 `ai.homelab.local`)通过 Nginx 反代至本机 `127.0.0.1:11434` 时,若 Nginx 原样透传了外部 `Host` 头,Ollama 会判定为 DNS 重绑定攻击并拒绝服务。只需在反代中加上 `proxy_set_header Host localhost:11434;` 即可解决。
表 1:浏览器插件与局域网反向代理调用本地模型的常见报错对照表
调用端场景实际报错特征底层拦截原因安全修复方案
本机浏览器插件 (Page Assist 等)OPTIONS 预检或 POST 报 403未放行 chrome-extension://* Origin精确配置扩展协议白名单(勿用 *)
通过 Nginx 自定义域名反代连终端 curl 走反代域名也报 403Ollama 拒绝非 localhost 的 Host 头反代层重写 Host 为 localhost:11434
HTTPS 网页直连 HTTP 局域网 IP浏览器控制台报 Mixed Content 拦截浏览器禁止 HTTPS 页面请求明文私有 IP改为服务端后端转发或配置 Caddy HTTPS
Reproduce & Verify CORS + Host Header Behavior via cURL
# 1. Test browser extension Origin check (Expect 204/200 after setting OLLAMA_ORIGINS)
curl -i -X OPTIONS http://127.0.0.1:11434/api/tags \
  -H "Origin: chrome-extension://abcdefghijklmnop" \
  -H "Access-Control-Request-Method: POST"

# 2. Test reverse-proxy Host header check
curl -i http://127.0.0.1:11434/api/version -H "Host: localhost:11434"

2. 局域网安全共享最佳实践:Ollama 锁死 127.0.0.1 + Nginx Bearer 鉴权反代

由于 Ollama 原生不包含 API Key 鉴权机制,直接开启 `OLLAMA_HOST=0.0.0.0` 意味着同一 Wi-Fi 下的任何设备都能随意调用甚至执行 `/api/delete` 删除你的模型。更稳妥的生产级做法是:让 Ollama 保持默认的 `127.0.0.1:11434` 本机监听,在前面套一层轻量 Nginx 反向代理(见下方可下载配置附件),强制校验 `Authorization: Bearer <密钥>` 并关闭流式缓冲。

3. 在反向代理层熔断高危管理接口(禁止局域网调用 `/api/delete`)

即便在局域网反代层配置了共享 Bearer Token,普通客户端也只需要调用 `/api/chat`、`/api/generate`、`/api/embeddings` 与 `/v1/*` 推理接口。建议在 Nginx 中增加一条显式拦截规则(`location ~ ^/api/(delete|pull|push|create) { return 403; }`),确保只有登录宿主机终端的管理员才能增删模型。
FIELD Q&A // 常见实测疑问与边界解答

复现常见疑问与深层原理解答

Q: 为什么公网 HTTPS 网页(比如在线版前端)可以直连本机的 `http://127.0.0.1:11434`,却无法直连局域网另一台机器的 `http://192.168.1.50:11434`?

根据 W3C 安全上下文规范,浏览器将本机回环地址(`127.0.0.1`)特批为“可信上下文”,因此只要 CORS 允许即可直连;但局域网私有 IP(`192.168.x.x`)不属于豁免范围,HTTPS 页面请求明文 HTTP 局域网 IP 会触发浏览器的 Mixed Content 硬性阻断。

Q: 为什么我在 macOS 终端里执行了 `export OLLAMA_ORIGINS=...`,但桌面状态栏里的 Ollama 依然报 403?

macOS 桌面图标启动的 GUI 进程不会读取终端 `~/.zshrc` 里的变量。必须执行 `launchctl setenv OLLAMA_ORIGINS "chrome-extension://*,moz-extension://*"`,然后完全退出并重新打开状态栏的 Ollama 图标才会生效。

REPRODUCIBLE ARTIFACT // 配套可参数化附件

本地模型局域网安全反向代理配置(Bearer 鉴权 + CORS 放行 + 零缓冲流式转发)

让 Ollama 只监听本机 127.0.0.1,通过 Nginx 对局域网提供带 Bearer 密钥鉴权、CORS 跨域头与零缓冲 SSE 流式转发的安全接口。

nginx-ollama-lan-auth.conf ↗
修改上方参数将实时更新下方配置内容
# Tinker AI — Secure Nginx Reverse Proxy for Local Ollama (Keep Ollama on 127.0.0.1:11434)
map $http_authorization $auth_ok {
    default 0;
    "Bearer sk-tinker-homelab-secret-2026" 1;
}

server {
    listen 0.0.0.0:11435;
    server_name _;

    location / {
        # Handle browser / Chrome extension CORS preflight
        if ($request_method = OPTIONS) {
            add_header Access-Control-Allow-Origin "*" always;
            add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
            add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;
            return 204;
        }

        if ($auth_ok = 0) {
            return 401 '{"error":"Unauthorized: valid Bearer token required"}';
        }

        proxy_pass http://127.0.0.1:11434;
        proxy_set_header Host localhost:11434;
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 300s;
        chunked_transfer_encoding on;
    }
}

更多可复现工程指南

查看全部 42 篇指南 →