为什么Ruby无法验证SSL证书?

时间:2012-02-08 18:56:06

标签: ruby api openssl certificate

这是我第一次尝试使用XMLRPC :: Client库与远程API进行交互,并且我一直收到此错误:

warning: peer certificate won't be verified in this SSL session

在我周围搜索我发现了很多人犯了这个错误。通常它带有自签名证书,他们只是想让它消失,所以他们做了像Monkey patch那样脏的东西,就像XMLRPC :: Client打开它的http会话一样。

我首先假设这只是客户不关心证书是否有效,所以我继续搜索并遇到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代码几秒钟的同一台机器上运行。这是与Windows一起安装的Ruby 1.8.7 p357。

Ruby是否使用主机操作系统提供的CA捆绑以外的东西?有没有办法告诉Ruby使用特定的CA捆绑包或系统?

2 个答案:

答案 0 :(得分:111)

如果您只对如何使Ruby的行为与OpenSSL s_client或浏览器的行为一样感兴趣,您可以跳到最后一部分,我将在下面的内容中介绍细则。

默认情况下,用于建立连接的OpenSSL::X509::Store根本不使用任何受信任的证书。根据您对应用程序域的了解,您通常会为X509::Store的实例提供与您的应用程序相关的可信证书。有几种选择:

  • Store#add_file采用PEM / DER编码证书的路径
  • 商店#add_cert采用X509 ::证书
  • 的实例
  • Store#add_path采用可以找到可信证书的目录的路径

“浏览器”方法

这与方法浏览器,Java(cacerts)或具有自己的可信证书内部存储的Windows相反。在那里,软件预先配备了一组可信证书,在软件供应商看来,这些证书被认为是“好的”。一般来说,这不是一个坏主意,但如果您真正研究这些集合,那么您很快就会注意到证书太多了。个人无法确定是否应盲目信任所有这些证书。

Ruby方法

另一方面,典型Ruby应用程序的要求与浏览器的要求有很大不同。浏览器必须能够让您导航到任何带有TLS证书的“合法”网站,并通过https提供。但是在典型的Ruby应用程序中,您只需要处理一些使用TLS的服务,否则需要进行证书验证。

Ruby方法的好处 - 虽然它需要更多的手动工作,但最终会得到一个手动定制的解决方案,它完全信任它在给定应用程序上下文中应该信任的证书。这很乏味,但这种方式的安全性要高得多,因为你暴露了更少的攻击面。最近的事件:如果您从未在您的信任集中包含DigiNotar或任何其他受到破坏的根,那么这些违规行为不会对您产生影响。

然而,正如您已经注意到的那样,默认情况下,如果您不主动添加受信任证书,OpenSSL扩展将无法验证任何对等证书一点都不为了使工作正常,您必须手动设置配置。

这种不便导致了许多可疑的措施来规避它,最糟糕的是全球设定OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE。请不要这样做。我们甚至开了一些关于添加代码的笑话,如果我们遇到黑客攻击,你的应用程序会随机崩溃:)

如果手动信任设置看起来过于复杂,我现在提供一个简单的替代方案,使OpenSSL扩展的行为与s_client等OpenSSL CLI命令完全相同。

为什么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上进行调用。

答案 1 :(得分:0)

如果您有ca-certificates文件,请执行以下操作:

http.ca_file = <YOUR CA-CERT FILE PATH>
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.verify_depth = 5