前端资源彻底不发网络请求需三层面堵死:构建时剥离远程依赖并检查包逻辑;运行时用CSP+脚本覆盖禁用连接;静态资源全内联。Node.js需patch http模块、清查依赖。Electron须禁用nodeIntegration并拦截外网请求。
如何让前端资源彻底不发任何网络请求
浏览器加载页面时,默认会尝试加载所有声明的外部资源:script、link[rel="stylesheet"]、img、iframe,甚至 css 里的 url() 和 js 中的 fetch/xmlhttprequest。全内网部署下,只要有一处漏掉,就可能触发 dns 查询或 tcp 连接失败,暴露环境特征或引发超时阻塞。
实操上不能只靠“不写外链”,得从三层面堵死:
- 构建时剥离所有远程依赖:用 Webpack/Vite 的
externals配置把axios、lodash等包打成空对象,或直接替换为本地打包副本;检查package.json中的dependencies是否含带网络调用逻辑的库(比如某些 SDK 自动上报) - 运行时拦截:在 HTML 顶部插入
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; connect-src 'none'; img-src 'self' data:;">,强制禁止fetch、WebSocket、new Image()等发起连接 - 静态资源兜底:把所有字体、图标、图片转成
data:URI 或 base64 内联;CSS 中避免@import url(...),改用构建时合并
Node.js 后端如何关闭所有出向 HTTP 客户端行为
Node.js 服务即使没主动写 https.request,也可能被依赖偷偷调用:日志上报、健康检查探针、配置中心 SDK、甚至某些 ORM 的自动版本提示。禁用必须从进程级下手。
最可靠方式是启动时加 --no-http-parser 不起作用,真正有效的是:
- 用
process.env.NODE_OPTIONS='--no-warnings'仅隐藏提示,不解决问题;应改用process.env.HTTP_PROXY=''+process.env.NO_PROXY='*'阻断代理链路 - 重写全局
require,在入口文件最顶部 patchhttp和https模块:const http = require('http'); http.request = http.get = () => { throw new Error('Outbound HTTP disabled'); }; - 检查
node_modules中是否含got、node-fetch、axios—— 它们默认走系统代理,且部分版本不响应NO_PROXY,需在代码中显式配置agent: false或直接删掉依赖
为什么 CSP 的 connect-src 'none' 在某些浏览器里不生效
connect-src 'none' 是理想写法,但 Chrome 110+ 才完全支持 'none' 关键字;旧版 Chrome、Firefox 会把它当语法错误而忽略整条策略。更麻烦的是,Safari 对 connect-src 的覆盖范围比标准窄:它不管 fetch,但管 XMLHttpRequest,而 WebSocket 则完全不受控。
稳妥方案不是赌关键字兼容性:
- 用
connect-src 'self' data:替代'none',再配合服务端不提供任何可被fetch的接口路径 - 对关键页面额外注入脚本,覆盖原生构造函数:
window.fetch = window.WebSocket = window.XMLHttpRequest = () => { throw new Error('Network access blocked'); }; - 内网网关层同步做出口防火墙策略,丢弃所有非
127.0.0.1/10.0.0.0/8/192.168.0.0/16的 TCP 连接,形成双重保险
Electron 应用怎样防止渲染进程偷偷连外网
Electron 渲染进程本质是 Chromium,但默认允许 nodeIntegration: true,这意味着 JS 可直接调用 require('child_process').exec('curl') 或读取本地 hosts 文件绕过 CSP。光靠前端策略远远不够。
必须组合设置:
- 主进程创建窗口时强制关闭高危能力:
webPreferences: { nodeIntegration: false, contextIsolation: true, sandbox: true, webSecurity: true } - 在
session.webRequest.onBeforeRequest中拦截所有非内网域名请求:if (!/^(10\.|192\.168\.|127\.|localhost)/.test(details.url)) { return { cancel: true }; } - 禁用
chrome://dino等内置页访问:通过app.commandLine.appendSwitch('disable-features', 'ChromeHome')减少攻击面
内网隔离不是加个开关就能完事——每个模块的“默认开启”行为都得手动关一遍,而且得验证关没关干净。最容易被忽略的是开发时留下的 console.log 里带的调试 URL、source map 文件里的原始路径、甚至 build 工具自动生成的 webpack:// 协议请求。真要锁死,就得把整个产物当成黑盒,用抓包工具跑一遍所有操作路径。

















