Chrome 152 升级后本地请求全挂了?是 LNA 策略在搞事

文章目录

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)
卸载清理 用户得手动改回去 插件卸载自动清除
相关推荐
JarvanMo1 小时前
让 3D 在 Flutter 中焕发生机:Flutter GPU 与 flutter_scene 实战经验
前端
狂师2 小时前
太强了!GitHub上开源了一款AI自动化测试框架,0代码搞定前后端测试!
前端·后端·测试
只睡四小时2 小时前
Local-First 数据契约:一张表装下 4 类数据
前端·javascript·架构设计·local-first·数据契约
迅猛龙办公室2 小时前
Python函数实现反转一个只有3位数的整数
开发语言·前端·python
我星期八休息2 小时前
Redis 的原理和使用(2)
前端·数据库·redis·python·mysql·缓存·bootstrap
Java后端的Ai之路2 小时前
19-ReactJS最佳实践
前端·react.js·前端框架
溪语流沙2 小时前
【Web全栈进阶】文件上传与图片展示:早报站的第一张图片
前端·vue.js·python·fastapi
alwaysrun2 小时前
Web之wasm-bindgen详解
前端·wasm·bindgen
鬼手点金2 小时前
如何选择模型
java·前端·人工智能·git·深度学习