问题复盘
场景
- 服务端:Win11(
192.168.2.246)运行 llama.cpp server,监听 0.0.0.0:8080
- 客户端:Mac(
192.168.2.209)用 Chrome 访问服务
为什么 Chrome 报错,Edge 正常?
Chrome 实施了 PNA(Private Network Access) 策略,Edge 尚未强制执行。
PNA 的核心逻辑是:当一个客户端试图访问比自己更”私有”的网络地址时,Chrome 会拦截请求。
1 2 3
| Mac (192.168.2.209) → Win11 (192.168.2.246) 私有网络 私有网络(更内层) └─── Chrome 判定为跨私有网络访问 → 拦截 ───┘
|
走过的弯路
| 尝试方案 |
结果 |
原因 |
修改 /etc/hosts 映射域名 |
❌ 无效 |
Chrome 解析回 IP 后仍判定为私有网络 |
| Win11 WSL2 装 Nginx |
❌ 复杂 |
WSL2 网络隔离,需要额外端口转发 |
| Win11 直接装 Nginx 加响应头 |
❌ 未生效 |
配置问题 + 治标不治本 |
修复响应头(Allow-Origin 不能用 *,需加 Credentials) |
⚠️ 头部正确了,但问题依然 |
导航请求的 PNA 限制比 fetch 更严格 |
最终解决方案
在 Mac 本机装 Nginx,做本地反代。
1 2 3
| Chrome → localhost:8080 → Mac Nginx → 192.168.2.246:8080 ↑ ↑ 本地访问 不触发PNA
|
1 2 3 4 5 6 7 8 9 10
| server { listen 8080; location / { proxy_pass http://192.168.2.246:8080; proxy_http_version 1.1; proxy_set_header Host $host; proxy_buffering off; proxy_cache off; } }
|
1
| brew services start nginx
|
Chrome 访问 http://localhost:8080 → 不触发 PNA,完美解决。
核心结论
PNA 的判断基于 IP 地址归属,而非域名。 绕过它最简单的方式不是加响应头,而是让 Chrome 认为自己在访问本机(localhost),由本机代理去连接内网服务。