node --inspect 无法绕过 HTTP2 证书错误,因其仅控制 DevTools 协议通信,而 http2.createSecureServer() 的 TLS 握手校验发生在协议层,早于调试器介入;必须在 server options 中显式设 rejectUnauthorized: false 并配合 ca 或系统证书信任链。

VSCode 调试 Node.js 的 HTTP2 服务器时,默认会因证书校验失败而卡在连接阶段,必须显式禁用 TLS 验证,且仅靠 node --inspect 启动参数无法解决。
为什么 node --inspect 无法绕过 HTTP2 的证书错误
HTTP2 的 http2.createSecureServer() 使用的是 Node.js 原生 TLS 层,其证书校验发生在协议握手阶段,早于 V8 inspector 的调试代理启动。VSCode 的 node 调试器只接管 JS 执行上下文,不干预底层 TLS 行为。
- 常见现象:断点能命中,但浏览器或 curl 访问
https://localhost:8443直接报ERR_SSL_UNRECOGNIZED_NAME_ALERT或连接重置 - 关键区别:
--inspect控制的是 DevTools 协议通信,而http2的证书校验由tls.connect()或服务端secureContext决定 - 如果你用的是自签名证书(如
mkcert生成),必须让 Node.js 进程本身信任它,而非仅让 VSCode 忽略
http2.createSecureServer 中绕过证书校验的正确写法
不能依赖环境变量或全局 flag;必须在创建 server 实例时通过 options 显式控制。最稳妥的方式是设置 rejectUnauthorized: false 并传入自定义 ca(可选)。
- 错误示范:
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'—— 在某些 Node.js 版本(v18.17+)已被废弃,且对http2无效 - 正确写法(server 端):
const fs = require('fs'); const http2 = require('http2'); <p>const options = { key: fs.readFileSync('./localhost-key.pem'), cert: fs.readFileSync('./localhost.pem'), rejectUnauthorized: false, // ✅ 关键:禁用客户端证书验证(仅用于调试) // ca: [fs.readFileSync('./local-ca.pem')], // 若需验证客户端证书,才设此字段 };</p><p>const server = http2.createSecureServer(options, (req, res) => { res.end('Hello over HTTP/2'); }); - 注意:
rejectUnauthorized: false只影响该 server 实例的客户端连接行为,不影响 VSCode 调试器自身与 Node 进程的 inspector 通信
launch.json 中必须补充的两个字段
VSCode 的 node 调试器默认不继承 shell 环境变量,也默认不加载本地证书,因此需在配置中显式注入信任链和禁用策略。
-
"env": { "NODE_EXTRA_CA_CERTS": "./localhost.pem", "NODE_TLS_REJECT_UNAUTHORIZED": "0" }——NODE_EXTRA_CA_CERTS用于让 Node.js 识别你的自签名根证书;NODE_TLS_REJECT_UNAUTHORIZED是兜底(尽管不推荐单独依赖它) -
"runtimeArgs": ["--trace-warnings"]—— 强烈建议加入,一旦证书相关警告被触发(如UNABLE_TO_VERIFY_LEAF_SIGNATURE),会在调试控制台立刻暴露,避免静默失败 - 不要设
"protocol": "inspector":这是旧版遗留字段,VSCode 2026 默认使用 inspector 协议,显式声明反而可能干扰 WebSocket Debug Tunnel 握手
浏览器访问时仍提示“不安全”怎么办
这是浏览器层面的安全策略,与 Node.js 或 VSCode 无关。绕过方式取决于你用的证书来源:
- 若用
mkcert生成:确保已运行mkcert -install将根证书装入系统信任库(macOS Keychain / Windows Cert Store / Linux trust store) - 若用 OpenSSL 自签:浏览器不会自动信任,必须手动将
localhost.pem导入浏览器证书管理器(Chrome → 设置 → 隐私与安全 → 安全 → 管理证书 → 证书颁发机构 → 导入) - 开发阶段更推荐直接用
http://localhost:8080+ HTTP/1.1 调试逻辑,等核心功能跑通后再切 HTTP2 —— 大多数 Node.js HTTP2 的调试痛点其实来自 TLS,而非协议本身
真正容易被忽略的是:HTTP2 的 ALPN 协商失败也会表现为“连接被拒绝”,但它不抛 TLS 错误,而是静默关闭 socket。遇到这类问题,先用 curl -v --http2 https://localhost:8443 看是否出现 * ALPN, offering h2,再检查 Node.js 版本是否 ≥ v15.10(ALPN 支持稳定起点)。


















