Socket.io + SSL + 自签名 CA 证书在连接时出错

Posted

技术标签:

【中文标题】Socket.io + SSL + 自签名 CA 证书在连接时出错【英文标题】:Socket.io + SSL + self-signed CA certificate gives error when connecting 【发布时间】:2013-02-28 05:37:25 【问题描述】:

我正在使用使用自签名 CA 证书创建的证书运行 https 服务器。

现在我想将 Socket.io 客户端连接到附加到 https 服务器的 Socket.io 服务器。不幸的是,我收到一个错误,告诉我:

Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE
    at SecurePair.<anonymous> (tls.js:1271:32)
    at SecurePair.EventEmitter.emit (events.js:92:17)
    at SecurePair.maybeInitFinished (tls.js:883:10)
    at CleartextStream.read [as _read] (tls.js:421:15)
    at CleartextStream.Readable.read (_stream_readable.js:293:10)
    at EncryptedStream.write [as _write] (tls.js:330:25)
    at doWrite (_stream_writable.js:211:10)
    at writeOrBuffer (_stream_writable.js:201:5)
    at EncryptedStream.Writable.write (_stream_writable.js:172:11)
    at write (_stream_readable.js:547:24)
    at flow (_stream_readable.js:556:7)

基本上,这个错误告诉我证书无法成功验证。这是因为相应的 CA 证书是自签名的。使用 https 请求时,我可以指定我信任的 CA。

在这种情况下如何让 Socket.io 连接?

PS:我正在运行 Node.js 0.10.0 和 Socket.io 0.9.13。

【问题讨论】:

【参考方案1】:

四年后,但如果您需要强制客户端套接字不拒绝自签名服务器证书,那么对于任何像我一样发现这篇文章的人,您需要 rejectUnauthorized: false 如在 const socket = require('socket.io-client')('https://192.168.0.31', transports: ['websocket'], rejectUnauthorized: false ) 来自https://github.com/socketio/engine.io-client#methods

现在还有一个很好的免费证书来源,所以现在你甚至不必成为“便宜的 d*ck”https://letsencrypt.org/

【讨论】:

我刚刚发现rejectUnauthorized...适用于任何websocket,而不仅仅是socket.io。 Wii 也解决了其他证书的问题(如果您真的不需要对您的 ssl 连接进行高度保护) 这个稍加修改的版本对我有用:const socket = io('https://192.168.0.31:3000', transports: ['websocket'], rejectUnauthorized: false );【参考方案2】:

对于 socket.io 1.0(不确定 0.9),这里有如何让节点客户端连接到无效证书的详细信息:https://***.com/a/24235426。 (感谢@3rdEden 上面的评论。)我发现自签名 SSL 证书可以方便开发服务器。

【讨论】:

【参考方案3】:

查看here,了解如何为Certificate Signing Request 使用自签名证书。您必须指定以下内容以允许使用自签名证书进行连接:

    key:一个字符串或 Buffer,包含 PEM 格式的客户端私钥。 cert:一个字符串或缓冲区,其中包含 PEM 格式的客户端证书密钥。 ca:受信任证书的字符串或缓冲区数组。如果省略,将使用几个众所周知的“根”CA,例如 VeriSign。这些用于授权连接。

要使用 CSR 创建自签名证书,请执行以下操作:

openssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem

在客户端,套接字应该被用作

var socket = io.connect('https://localhost', secure: true);

【讨论】:

这正是我所做的,但它不起作用。我总是收到 UNABLE_TO_VERIFY_LEAF_SIGNATURE 错误(我试图从 Node.js 中使用 socket.io-client 进行连接,而不是从浏览器中)。我需要的是有可能以编程方式告诉 Socket.io 哪些 CA 证书是好的。看起来,这种可能性是缺失的。 SockJS 的行为方式相同,并且那里也缺少这种可能性:-( 这个答案没有回答如何让有效的自签名证书在 NodeJS 中正常工作的问题。 这不是问题的答案,这是how to create self-signed certificate【参考方案4】:

不要使用自签名证书。只是不要,有些浏览器在使用 WebSockets 时无法让您接受它们。而且你看起来像一个没有购买适当证书的廉价 d*ck。

来自They see me pollin, they hatin (p. 23)。 Socket.IO 的核心团队成员 Arnout Kazemier (3rdEden) 的演讲。

【讨论】:

那么这如何解决开发/暂存案例?我应该为我的所有登台服务器、Vagrant VM 和生产服务器购买证书吗? Node.js 0.10 已配置为自动拒绝自签名的 SSL 证书。您可以通过添加以下 ENV 变量来“撤消”它以进行开发:NODE_TLS_REJECT_UNAUTHORIZED=0 另外,是的,我对 SSL 的看法很狭窄;)但正如您可能已经经历过的那样,自签名证书会导致很多问题可以通过适当的证书来防止。至于开发/登台,购买通配符 ssl 证书或编辑您的 /etc/hosts ? ;) @3rdEden 这有点奇怪不是吗? “自动拒绝自签名的 SSL 证书”......我的意思是当有人向options:ca : [self-signed.pem] 添加自签名证书时......不应该通过检查而不是失败吗?从客户端发出的nodejs请求的角度来看,就是。 在某些情况下使用自签名证书可能非常重要。您甚至无法从浏览器访问 socket.io。如果你想进行自动化测试,你不应该使用真正的生产站点密钥,任何人都应该能够运行测试。 @hg — 完全正确!说“只是不要使用自签名证书”似乎非常狭隘。我的用例是 Swift nodejs+socket.io。有人知道在过去两年里这个话题是否发生了变化?

以上是关于Socket.io + SSL + 自签名 CA 证书在连接时出错的主要内容,如果未能解决你的问题,请参考以下文章

如何生成自签名双向认证证书 ssl

生成自签名CA+SSL证书

什么是自签名SSL证书?

SSL 握手失败 - 一个威瑞信链证书 - 包含两个 CA 签名证书和一个自签名证书

如何创建一个自签名的SSL证书(X509)

如何创建一个自签名的SSL证书