这是我第一次尝试使用 XMLRPC::Client 库与远程 API 交互,但我不断收到此错误:
warning: peer certificate won't be verified in this SSL session
环顾四周,我发现很多人都遇到了这个错误。通常它带有自签名证书,他们只是想让它消失,所以他们做了一些肮脏的事情,比如 XMLRPC::Client 打开它的 http session 的方式。
我首先假设这只是客户端不关心证书是否有效,所以我继续搜索并遇到了 this gem .它只是强制验证所有 SSL 证书,如果它也无法验证,则会抛出一个硬错误。这正是我想要的。我包含它,再次运行代码,现在我得到了这个:
OpenSSL:SSL::SSLError:
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B:
certificate verify failed
当然!证书不好!但我仔细检查只是为了确保使用 openssl 的内置 s_client 像这样:
openssl s_client -connect sub.example.com:443
我能得到什么:
CONNECTED(00000003)
---
Certificate chain
<snip>
Verify return code: 0 (ok)
所以现在我们开始我的问题。 OpenSSL(命令行版本)表示证书很好。 OpenSSL(Ruby 库)不同意。我所有的网络浏览器都说证书很好。
一些可能有用的其他细节。证书是通配符,但对域有效。 openssl s_client 与 Ruby 代码在同一台机器上运行几秒钟。这是与 RVM 一起安装的 Ruby 1.8.7 p357。
Ruby 是否使用主机操作系统提供的 CA 包以外的其他东西?有没有办法告诉 Ruby 使用特定的 CA 包或系统包?
最佳答案
如果您只对如何使 Ruby 的行为与 OpenSSL 相同 s_client
感兴趣或者您的浏览器有问题,您可以跳到最后一部分,我将在接下来的内容中详细说明。
默认情况下,OpenSSL::X509::Store
用于建立连接根本不使用任何受信任的证书。根据您对应用程序领域的了解,您通常会提供一个 X509::Store
的实例。使用与您的应用程序相关的可信证书。有几种选择:
“浏览器”方法
这与浏览器、Java (cacerts) 或具有自己内部可信证书存储的 Windows 所采用的方法形成对比。在那里,软件预先配备了一组受软件供应商认为“良好”的可信证书。一般来说,这不是一个坏主意,但如果你真的研究这些集合,那么你很快就会注意到证书太多了。个人无法真正判断是否应该盲目信任所有这些证书。
Ruby 方法
另一方面,典型 Ruby 应用程序的需求与浏览器的需求大不相同。浏览器必须能够让您导航到任何带有 TLS 证书并通过 https 提供服务的“合法”网站。但在典型的 Ruby 应用程序中,您只需处理少数使用 TLS 或需要证书验证的服务。
Ruby 方法还有一个好处——虽然它需要更多的手动工作,但您最终会得到一个手工定制的解决方案,该解决方案完全信任它在给定应用程序上下文中应该信任的证书。这很乏味,但这种方式的安全性要高得多,因为您暴露的攻击面要少得多。以最近的事件为例:如果您从未将 DigiNotar 或任何其他受损的根包含在您的信任集中,那么此类违规行为就不会影响您。
然而,正如您已经注意到的那样,这样做的缺点是,默认情况下,如果您不主动添加受信任的证书,OpenSSL 扩展将根本无法验证任何对等证书。为了使事情正常工作,您必须手动设置配置。
这种不便导致了很多可疑的措施来规避它,最糟糕的是全局设置
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
.请不要这样做。我们甚至开玩笑说,如果我们遇到这种 hack,添加代码会让您的应用程序随机崩溃:)如果手动信任设置看起来太复杂,我现在将提供一个简单的替代方法,使 OpenSSL 扩展的行为与 OpenSSL CLI 命令(如
s_client
)完全相同。 .为什么s_client可以验证证书
OpenSSL 使用与浏览器和 Windows 类似的方法。典型的安装会将一组受信任的证书放在硬盘上的某个位置(例如
/etc/ssl/certs/ca-bundle.crt
),这将用作默认的受信任证书集。那就是s_client
查看何时需要验证对等证书,这就是您的实验成功的原因。使 Ruby 表现得像 s_client
如果您在使用 Ruby 验证证书时仍然希望获得同样的舒适度,您可以通过调用
OpenSSL::X509::Store#set_default_paths
告诉它使用 OpenSSL 可信证书包(如果您的系统在您的系统上可用)。 .更多信息可以在 here 中找到.与 XMLRPC::Client
一起使用,只需确保 set_default_paths
在 X509::Store
上被调用它用。
关于ruby - 为什么 Ruby 无法验证 SSL 证书?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9199660/