0%

解决因为Chrome实施PNA(Private Network Access)策略,导致访问内网服务被拦截

问题复盘

场景

  • 服务端: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
brew install nginx
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),由本机代理去连接内网服务。