在 Node JS 中为 WebSocket (ws) 使用自签名 CA 证书
Posted
技术标签:
【中文标题】在 Node JS 中为 WebSocket (ws) 使用自签名 CA 证书【英文标题】:Using a Self-Signed CA Certificate for WebSocket (ws) in Node JS 【发布时间】:2020-01-14 21:00:39 【问题描述】:我需要使用 Node JS 中的ws 客户端连接到单独的 WebSocket 服务器。
我能够使用 Chrome 中的示例程序进行连接,因为我在计算机上的受信任的根证书颁发机构商店中安装了自签名根 CA。
我知道 Node JS 使用硬编码的根 CA 列表(愚蠢),但我希望有某种方法可以导入我自己的。
我试过了:
使用the CLI option mentioned in the Node JS documentation export NODE_EXTRA_CA_CERTS=C:\\Users\\IT1\\Documents\\security\\rootCA.pem
使用许多论坛帖子中建议的ssl-root-cas 库,但我认为它可能不适用于这里,因为它不会更改我正在使用的ws 客户端的https。 (我想,我在这一点上吐口水)
使用 WebSocket 构造函数可用的 ca、cert 和 key 选项。
// Using just ca
var test = new WebSocket(uri,
ca: fs.readFileSync("C:\\Users\\IT1\\Documents\\security\\rootCA.pem")
);
// Using cert and key
var test = new WebSocket(uri,
cert: fs.readFileSync("C:\\Users\\IT1\\Documents\\security\\rootCA.crt"),
key: fs.readFileSync("C:\\Users\\IT1\\Documents\\security\\rootCA.key")
);
// Using ca, cert and key
var test = new WebSocket(uri,
ca: fs.readFileSync("C:\\Users\\IT1\\Documents\\security\\rootCA.pem"),
cert: fs.readFileSync("C:\\Users\\IT1\\Documents\\security\\rootCA.crt"),
key: fs.readFileSync("C:\\Users\\IT1\\Documents\\security\\rootCA.key")
);
不管怎样,我总是收到以下错误消息:
events.js:200
throw er; // Unhandled 'error' event
^
Error: unable to verify the first certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1321:34)
at TLSSocket.emit (events.js:223:5)
at TLSSocket._finishInit (_tls_wrap.js:794:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:608:12)
Emitted 'error' event on WebSocket instance at:
at ClientRequest.<anonymous> (C:\Users\IT1\source\repos\WebSocketTest\WebSocketTest\node_modules\ws\lib\websocket.js:554:15)
at ClientRequest.emit (events.js:223:5)
at TLSSocket.socketErrorListener (_http_client.js:406:9)
at TLSSocket.emit (events.js:223:5)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:81:21)
code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
另外,我不能使用rejectUnauthorized: true
。我需要它来获得授权,所以请不要将其作为解决方案。
请帮忙,我真的在这个问题上摸不着头脑。
【问题讨论】:
【参考方案1】:在摸索了一两天之后,我决定在 OpenSSL 中验证证书。事实证明,证书使用了不同的加密算法(SHA 256 与 DES3 或类似的算法)。它在浏览器中运行良好的原因是因为我之前已经为该域安装了不同的证书。
故事的寓意:
-
在尝试在代码中使用 SSL 证书之前,请务必先使用 OpenSSL 测试您的 SSL 证书。与 NodeJS、Java 或任何运行时环境相比,OpenSSL 总是会提供更多关于为什么您的证书无法正常工作的信息。
在测试根证书之前,从受信任的根存储中删除域的所有证书。
我在网上关注有关在 Windows 中生成自签名根 CA 的教程,但我发现的教程并没有提供很多关于我在做什么的信息,更多的是“这就是你的做法”。这是我出错的地方,因为我遵循了几个教程并结合信息来寻找解决方案。这意味着我使用一个教程生成了根证书和私钥,然后使用另一个教程签署了其他证书(该教程指定了不同的算法,但没有说明算法必须与根 CA 和签名证书匹配)。
在深入了解自签名根 CA 之前,对 SSL 和根证书的工作原理有一定的了解会有所帮助。不是从技术角度,而是从为什么存在 Root CA、它们如何在现实世界中使用以及它如何应用于作为开发人员的应用程序的角度。 I found this article extremely helpful.
【讨论】:
以上是关于在 Node JS 中为 WebSocket (ws) 使用自签名 CA 证书的主要内容,如果未能解决你的问题,请参考以下文章
如何在 vue-cli 应用程序中为 WebSocket 代理正确设置 devServer