为什么Ruby无法validationSSL证书?

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

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

search周围我发现了一些人得到了这个错误。 通常是自签名证书,他们只是希望它消失,所以他们做一些像猴子补丁XMLRPC ::客户端打开它的http会话的方式。

我第一次认为这只是客户不关心证书是否有效,所以我继续我的search,并遇到了这个gem 。 它只是强制所有的SSL证书的validation,如果它不能够,也会抛出一个硬错误。 这正是我想要的。 我包括它,再次运行代码,现在我得到这个:

 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或者你的浏览器一样,那么你可以跳到最后一节,我将在后面的内容中进行详细的介绍。

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

  • 商店#add_file获取PEM / DER编码证书的path
  • 商店#add_cert获取X509 ::证书的一个实例
  • Store#add_path将path指向可以find可信证书的目录

“浏览器”方法

这与方法浏览器,Java(cacerts)或具有自己内部存储的可信证书的Windows相反。 在软件供应商看来,软件预装了一套被认为是“好”的可信证书。 通常这不是一个坏主意,但是如果你真的关注这些集合,那么你很快就会注意到证书太多了。 一个人不能真正知道所有这些证书是否应该盲目地被信任。

Ruby方法

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

Ruby方法有好处 – 尽pipe它需要更多的手工工作,但最终你会得到一个手工定制的解决scheme,它完全信任在给定的应用程序上下文中应该信任的证书。 这很乏味,但是安全性要高得多,因为你暴露的攻击面less得多。 以最近的事件为例:如果您从未将DigiNotar或任何其他受损的根包括在您的信任集中,那么这样的违规行为不会影响您。

但是,正如您已经注意到的那样,缺点是默认情况下,如果您不主动添加可信证书,则OpenSSL扩展将根本无法validation任何对等证书。 为了使事情正常工作,您必须手动设置configuration。

这种不便引起了很多可疑的措施来规避它,最糟糕的是全局设置OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE 。 请不要这样做。 我们甚至开玩笑说如果我们遇到那个黑客,添加代码会让你的应用程序随机崩溃:)

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

为什么s_client可以validation证书

OpenSSL对浏览器和Windows使用类似的方法。 一个典型的安装会在你的硬盘上放置一些信任的证书(类似于/etc/ssl/certs/ca-bundle.crt ),这将作为默认的可信任证书。 这就是s_client在需要validation对等证书时的样子,这就是为什么您的实验成功了。

使Ruby的行为像s_client

如果您仍然希望在使用Rubyvalidation证书时具有相同的舒适性,则可以通过调用OpenSSL::X509::Store#set_default_paths来告诉它使用OpenSSL可信证书(如果可用)。 更多信息可以在这里find。 要在XMLRPC::Client使用它,只需确保set_default_paths在它使用的X509::Store上被调用。

如果你有一个ca-certificates文件,只需要这样做:

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