文章目录
- [Chrome 152 本地请求全挂了,真凶是 LNA](#Chrome 152 本地请求全挂了,真凶是 LNA)
-
- 客户那边突然不能用了
- 浏览器为什么突然管这么宽
- [Chrome 版本演进:从宽松到彻底封堵](#Chrome 版本演进:从宽松到彻底封堵)
- 旧方法为什么彻底废了
- [核心解法:Chrome 企业策略](#核心解法:Chrome 企业策略)
- 五个策略,两套场景
-
- [新 LNA 策略(Chrome 142+,HTTPS 场景)](#新 LNA 策略(Chrome 142+,HTTPS 场景))
- [旧 PNA 策略(HTTP 场景 ------ 我们的关键)](#旧 PNA 策略(HTTP 场景 —— 我们的关键))
- 三种平台怎么写
-
- Windows:注册表
- [Linux:JSON 文件](#Linux:JSON 文件)
- [macOS:plist 文件](#macOS:plist 文件)
- 代码里怎么落地
- 验证方式
- 一句话总结
- 往后看
- 两种解法对比
Chrome 152 本地请求全挂了,真凶是 LNA
客户那边突然不能用了
某天客户那边传来消息:终端信息页面一片空白。我们的系统页面是个 HTTP 站点,浏览器里通过 fetch 调本地插件服务 localhost:xxx 拿终端设备信息,一直跑得好好的。
开发机 Chrome 151,没问题。让客户打开开发者工具一看------控制台全是跨网错误,请求根本发不出去。问了下版本,Chrome 152。
你可能也遇到过类似的事。Google 从 Chrome 138 开始逐步收紧一条安全策略,到 152 版本一脚油门把之前的临时方案全堵死了。这篇讲清楚到底发生了什么,以及怎么从根上解决。
浏览器为什么突然管这么宽
浏览器默认不信任外部网站。一个网页请求公网 API 没问题,但如果想请求你电脑上跑的本地服务(比如 localhost:xxx)或者局域网设备(比如 192.168.x.x),安全上是个灰区------万一是恶意网页探测你的内网设备呢?
以前 Chrome 对这类请求基本放行。现在它装了一道门禁:Local Network Access(LNA) 策略。就像外卖员想进小区得刷门禁,Chrome 152 之后,每个网页想调你本地服务也得先过一道闸。
我们的插件就卡在这扇门禁上:系统页面是 HTTP,调用本地服务本来是合法需求,但 Chrome 152 之后不让了。
Chrome 版本演进:从宽松到彻底封堵
近两年 Google 分阶段收紧 Local Network Access(LNA)权限机制:

我们自己的开发机还在 flag=Default 的状态,151 版本上 Default 确实等于关闭 LNA。但到了 152,Google 把这个"后门"删了------Default 现在的意思是"跟随灰度策略",也就是大概率会被拦截。

旧方法为什么彻底废了
之前的临时解法很简单:让用户打开 chrome://flags,把 Local Network Access Restrictions Temporary Opt Out 设为 Enabled,重启浏览器。
这条路到 152 彻底走不通了。一是 flag 本身被移除了,TemporaryOptOut 这个开关在 v152 里已经从 chrome://flags 页面消失,想手动改也没得改。二是就算 flag 还在,也没法用代码自动设置------浏览器的 flag 配置存在内部的 Local State 文件里,Chrome 没有暴露任何官方 API,硬写注册表或 JSON 文件极不可靠,Chrome 运行时会覆盖、可能损坏配置。三是 flag 本身就是临时方案,Google 的公开文档里早就说了,flag 是测试用的,未来版本会逐步清理。
核心解法:Chrome 企业策略
既然改不了 flags,那就得找一个比 flags 优先级更高的机制来覆盖它------这就是企业策略。
Chrome 有三层配置机制,优先级从高到低:

企业策略本来是给公司 IT 管理员批量管控员工浏览器用的------比如强制开启安全浏览、禁止安装某些扩展之类的。但它有几个关键特性对我们来说特别有用:
- 最高优先级 ,写入后直接覆盖浏览器默认行为,不需要改
chrome://flags - 有官方支持,Chrome 启动时自动从系统级位置读取,不依赖浏览器自己的配置文件
- 跨平台一致,Windows 走注册表、Linux 读 JSON 文件、macOS 读 plist
我们要做的就是安装插件的时候,顺便把这组企业策略写进去,放行所有 URL 对本地网络的访问。
五个策略,两套场景
LNA 机制只对 HTTPS 页面生效(安全上下文要求),但我们的系统页面是 HTTP。所以需要两套策略同时生效:
新 LNA 策略(Chrome 142+,HTTPS 场景)
| 策略名 | 值 | 作用 |
|---|---|---|
LocalNetworkAccessAllowedForUrls |
["*"] |
预授权所有域名的 LNA 权限,用户不会看到弹窗 |
LocalNetworkAccessPermissionsPolicyDefaultEnabled |
1 |
默认自动授予 LNA 权限 |
旧 PNA 策略(HTTP 场景 ------ 我们的关键)
| 策略名 | 值 | 作用 |
|---|---|---|
InsecurePrivateNetworkRequestsAllowedForUrls |
["*"] |
允许 HTTP 页面访问本地网络和环回地址 |
InsecurePrivateNetworkRequestsAllowed |
1 |
全局兜底,允许所有 HTTP 来源访问 |
为什么 HTTP 页面走不到 LNA? LNA 要求安全上下文(HTTPS)才能触发权限流程,HTTP 页面直接被旧的 Private Network Access 机制拦截。所以必须同时写入 PNA 策略,才能覆盖 HTTP 来源。
此外再加一个 LocalNetworkAccessRestrictionsTemporaryOptOut = 1,对还在 v152 以下的旧版本 Chrome 有效,双保险。
三种平台怎么写
Windows:注册表
Chrome 从这个路径读策略:
HKLM\SOFTWARE\Policies\Google\Chrome
Edge 同理(内核一样):
HKLM\SOFTWARE\Policies\Microsoft\Edge
注册表结构大概是这样:
LocalNetworkAccessRestrictionsTemporaryOptOut = 1 (DWORD)
InsecurePrivateNetworkRequestsAllowed = 1 (DWORD)
LocalNetworkAccessPermissionsPolicyDefaultEnabled = 1 (DWORD)
LocalNetworkAccessAllowedForUrls\
└── 1 = "*" (String)
InsecurePrivateNetworkRequestsAllowedForUrls\
└── 1 = "*" (String)
注意是 HKLM 不是 HKCU,写入 Local Machine 需要管理员权限------这个好办,安装脚本本身就以管理员身份跑。
Linux:JSON 文件
Chrome 在 Linux 上启动时,会自动扫描 /etc/opt/chrome/policies/managed/ 目录下的所有 .json 文件,把内容加载为企业策略。Edge 则是 /etc/opt/edge/policies/managed/。
所以我们的做法很直接:安装插件时,往这个目录写一个 JSON 文件,把五个策略写进去。文件名自己定,比如 allow-local-network.json,后缀是 .json 就行:
/etc/opt/chrome/policies/managed/allow-local-network.json
JSON 内容就是那五个策略:
json
{
"LocalNetworkAccessAllowedForUrls": ["*"],
"InsecurePrivateNetworkRequestsAllowedForUrls": ["*"],
"InsecurePrivateNetworkRequestsAllowed": 1,
"LocalNetworkAccessRestrictionsTemporaryOptOut": 1,
"LocalNetworkAccessPermissionsPolicyDefaultEnabled": 1
}
写入 /etc 需要 root 权限。
macOS:plist 文件
macOS 的 Chrome 策略通过 defaults write 命令写入 /Library/Managed Preferences/ 下的 plist:
/Library/Managed Preferences/com.google.Chrome.plist
/Library/Managed Preferences/com.microsoft.edge.plist
每条策略一条 defaults write 命令,需要 sudo 权限。
代码里怎么落地
我们用 Go 的 build tag 实现跨平台,每个平台一个文件:
chrome_policy_windows.go // build: windows
chrome_policy_linux.go // build: linux
chrome_policy_darwin.go // build: darwin
chrome_policy_other.go // 空实现,其他平台编译不报错
安装插件时自动调用 SetChromeLNAPolicy(),卸载时 ClearChromeLNAPolicy() 清理掉------用户全程无感。
核心调用就两行:
go
if action == "install" {
util.SetChromeLNAPolicy()
}
if action == "uninstall" {
util.ClearChromeLNAPolicy()
}
验证方式
写完策略后,有三步验证:
第一步:确认策略已加载。 浏览器地址栏输入 chrome://policy,应该能看到上面那五个策略,值都正确。注意这里即使 flag 页面显示 Default 也没关系------企业策略在更高层级生效,不改变 flag 的显示。
第二步:测试请求。 在系统页面 F12 控制台执行:
javascript
fetch("http://localhost:xxx/xxx")
.then(r => r.json())
.then(d => console.log(d))
.catch(e => console.error(e))
正常情况下返回成功。
第三步:重启浏览器。 策略写完必须完全关闭浏览器(任务管理器里结束所有 Chrome 进程)再重新打开,才能生效。
一句话总结
Chrome 152 把手动改 flag 这条路彻底堵死了。如果你的产品也依赖"公网页面调 localhost",别再让用户去改 chrome://flags------装的时候顺便写一组 Chrome 企业策略进去,注册表(Windows)、JSON(Linux)、plist(macOS)三端覆盖,用户全程无感。
往后看
Google 的安全方向很明确------逐步缩小网页能自由访问的范围,把越来越多的网络请求纳入权限管控。依赖"localhost 总是能访问"这个假设的架构,迟早会被 LNA 或类似机制撞上。
企业策略这条路目前有效,因为它走的是 Chrome 官方预留的"管理员管控"通道。但也要关注后续版本有没有进一步收紧------一旦哪天企业策略也开始限制,就得考虑 HTTPS + 权限授权模型的升级了。
两种解法对比
| 对比项 | 手动改 flag | 企业策略方案 |
|---|---|---|
| 操作方式 | 每个用户手动去改 | 插件安装时自动写入 |
| 用户感知 | 要跟客户解释为啥要去改浏览器配置 | 无感 |
| Chrome 152+ | flag 已移除,改不了 | 仍有效 |
| 优先级 | 低 | 高(覆盖 flag 和默认行为) |
| 可编程 | 不可行(无官方 API) | 可行(写注册表/JSON/plist) |
| 卸载清理 | 用户得手动改回去 | 插件卸载自动清除 |
- Chrome Local Network Access 官方文档:https://developer.chrome.com/blog/local-network-access
- Chrome Enterprise Policy 列表:https://cloud.google.com/chrome-enterprise/policies
- Private Network Access 规范:https://wicg.github.io/private-network-access/