Ruby Net::HTTP 在证书续订后以 OpenSSL::SSL::SSLError "certificate verify failed" 响应
Ruby Net::HTTP responds with OpenSSL::SSL::SSLError "certificate verify failed" after certificate renewal
我们最近更新了我们网站的 SSL 证书,以下发生在 Mac OS El Capitan 10.11.3:
require 'net/http'
Net::HTTP.get URI('https://www.google.com')
# => "<HTML>...</HTML>"
# The site whose certificate got renewed
Net::HTTP.get URI('https://www.example.com')
# => OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed
我在 Google 和 Whosebug 上的所有搜索都得到了提示 Ruby 安装有问题的答案,但它们似乎与旧的 Ruby 版本有关,我不知道不认为这里是这种情况。这是我尝试过的:
brew update
brew upgrade openssl
rvm osx-ssl-certs update all
rvm install ruby-2.3.1 --disable-binary --with-openssl-dir="$(brew --prefix openssl)"
(我之前没有这个版本)
rvm requirements
根据 Uzbekjon 的建议,crlrefresh rpv
清除 OSX 系统范围的 CRL 缓存。
我该如何解决这个问题?
备注:
- 新安装的 linux Docker 容器没有 Ruby 2.2.3 时不会出现此问题。所以这可能与 Mac OS 或 SSL 本地缓存有关。
- 此问题可能在证书续订之前就已经存在。我不能确定。但是,正如我在 this question.
中讨论的那样,续订确实导致了我们正在使用的第 3 方的类似问题
- Namecheap 验证证书安装正确,在线检查器显示一切正常,所有主要浏览器都显示证书有效。
解决方案
在 BoraMa 的大力帮助下,现在很清楚发生了什么。 COMODO 添加了一个名为 COMODO RSA Certification Authority
的新根,而不是之前的 COMODO Certification Authority
。新根未在 Mac 的钥匙串中注册,导致此问题。
我们尝试调试的一种方法是 运行:
openssl s_client -connect www.mysite.com:443
显示警告 verify error:num=20:unable to get local issuer certificate
。此警告不是问题,因为 openssl s_client
默认不使用任何证书。 运行 以下内容在下载证书 from COMODO into comodo.pem
(index here 后能够防止警告:
openssl s_client -connect www.mysite.com:443 -CAfile comodo.pem
但是,这不能也没有影响 Ruby OpenSSL 接口。 This article made things much clearer for me, and the SSL doctor script created by its author was also helpful, as it confirmed the hypothesis. The article suggested to look at OpenSSL::X509::DEFAULT_CERT_FILE
, which for me was /usr/local/etc/openssl/cert.pem
. That file did not exist on my machine, which meant Apple's patch for OpendSSL was using the Keychain App. For whatever reason, importing comodo.pem
into my keychain and marking it as trusted based on this post 无效。
因此,解决方案是手动创建 cert.pem
文件。我去了钥匙串应用程序,并将所有系统根证书导出到 system_root.pem
。然后: cat system_root.pem comodo.pem > cert.pem
并将该文件移动到 /usr/local/etc/openssl/
就成功了。 运行 Net::HTTP.get
in Ruby 不再失败。
听起来问题出在您的 OSX 证书缓存上。我猜你在旧证书过期之前更新了证书?
尝试通过 运行 这个命令清除 OSX 系统范围的 CRL 缓存:
crlrefresh rpv
# p - purges cache, r - refreshes them, v - run in verbose mode
这是一个内置的命令行工具,可以更新和维护系统范围的 CRL 缓存。在其 man
页面 (mand crlrefresh
) 中阅读更多相关信息。
我会尝试仔细检查受信任的证书库是否包含 COMODO_RSA_Certification_Authority.pem
证书。在我的 (Linux) 设置中,该站点工作正常,但是当我暂时从证书存储中删除 COMODO 证书颁发机构的证书时,我得到与您完全相同的错误(而在浏览器中它仍然可以正常工作他们自己的证书商店)。
顺便说一句,使用 curl
也可以识别相同的错误,因为它似乎也使用与 ruby 相同的受信任证书存储,因此您可能首先确保该站点在 curl 下工作。
在 linux 中,证书存储通常位于 /etc/ssl/certs
而在 OSX 中,它可能应该是 /System/Library/OpenSSL
(其他选项见 this article ).
您应该会在证书存储目录中看到如下内容:
root@apsara:/etc/ssl/certs$ ls -l | grep COMODO_RSA_Certification_Authority.pem
lrwxrwxrwx 1 root root 73 úno 28 10:24 COMODO_RSA_Certification_Authority.pem -> /usr/share/ca-certificates/mozilla/COMODO_RSA_Certification_Authority.crt
lrwxrwxrwx 1 root root 38 úno 28 10:24 d4c339cb.0 -> COMODO_RSA_Certification_Authority.pem
lrwxrwxrwx 1 root root 38 úno 28 10:24 d6325660.0 -> COMODO_RSA_Certification_Authority.pem
以下是此根 CA 证书的一些属性的片段:
$ openssl x509 -in COMODO_RSA_Certification_Authority.pem -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
4c:aa:f9:ca:db:63:6f:e0:1f:f7:4e:d8:5b:03:86:9d
Signature Algorithm: sha384WithRSAEncryption
Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Certification Authority
Validity
Not Before: Jan 19 00:00:00 2010 GMT
Not After : Jan 18 23:59:59 2038 GMT
Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Certification Authority
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:91:e8:54:92:d2:0a:56:b1:ac:0d:24:dd:c5:cf:
...
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
BB:AF:7E:02:3D:FA:A6:F1:3C:84:8E:AD:EE:38:98:EC:D9:32:32:D4
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha384WithRSAEncryption
...
证书可以从Comodo下载here (index of all certs is here).
更多信息:在调查时,事实证明 Comodo CA 实际上有两个不同的证书认证链。一个是较旧的,是具有上面列出的根 CA 的那个。较新的验证链在链中使用 "External CA root" 个证书。 This forum post 进一步解释,针对 OSX 将这些证书标记为受信任的具体说明。
我整个早上都在为这个错误烦恼。这个问题和答案使我找到了适合我的解决方案。我不会在此处添加新信息,而只是说明我所做的细节,以防在与我的平台类似的平台上出现此错误的任何其他人都可以使用它。
我正在使用:
Ubuntu 16.04
ruby 2.3.0
rails 4.2.7.1
HTTParty
我正在访问使用 COMODO SSL 证书保护的 API。在我的代码中,当我尝试时:
HTTParty.get(secured_url).tap{|response| puts response}
我得到了:
SSL_connect returned=1 errno=0 state=error: certificate verify failed (OpenSSL::SSL::SSLError)
我也使用了上面提到的 SSL doctor 脚本。当我 运行 脚本(用我的实际 api 服务器地址代替 host
)时,我得到:
$ ruby doctor.rb host:443
/home/<redacted>/.rvm/rubies/ruby-2.3.0/bin/ruby (2.3.0-p0)
OpenSSL 1.0.2g 1 Mar 2016: /usr/lib/ssl
SSL_CERT_DIR=""
SSL_CERT_FILE=""
HEAD https://host:443
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed
The server presented a certificate that could not be verified:
subject: <redacted>
issuer: /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
error code 20: unable to get local issuer certificate
在一个单独的终端中,我进入了我的证书目录:
$ cd /etc/ssl/certs
并做了(使用 COMODO_RSA_Organization_Validation_Secure_Server_CA
从上面的 issuer
文本派生而来):
<redacted>:/etc/ssl/certs$ openssl x509 -in COMODO_RSA_Organization_Validation_Secure_Server_CA.pem -noout -text
Error opening Certificate COMODO_RSA_Organization_Validation_Secure_Server_CA.pem
140455648364184:error:02001002:system library:fopen:No such file or directory:bss_file.c:398:fopen('COMODO_RSA_Organization_Validation_Secure_Server_CA.pem','r')
140455648364184:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:400:
unable to load certificate
我去了 COMODO RSA Organization Validation Secure Server CA pem 所在的 COMODO 站点。我将证书复制到桌面上名为 COMODO_RSA_Organization_Validation_Secure_Server_CA.crt
的新文件中(有些说明说使用 crt
扩展名而不是 pem
,即使您需要 pem
证书内容)。
然后,在 these instructions 之后,我做了:
<redacted>:~/Desktop$ sudo cp COMODO_RSA_Organization_Validation_Secure_Server_CA.crt /usr/share/ca-certificates/COMODO_RSA_Organization_Validation_Secure_Server_CA.crt
<redacted>:~/Desktop$ sudo dpkg-reconfigure ca-certificates
然后我做了:
sudo dpkg-reconfigure ca-certificates
然后:
<redacted>:~/Desktop$ ruby doctor.rb host:443
/home/<redacted>/.rvm/rubies/ruby-2.3.0/bin/ruby (2.3.0-p0)
OpenSSL 1.0.2g 1 Mar 2016: /usr/lib/ssl
SSL_CERT_DIR=""
SSL_CERT_FILE=""
HEAD https://host:443
OK
之后我的代码 运行 没问题。谢谢谢谢谢谢!
我们最近更新了我们网站的 SSL 证书,以下发生在 Mac OS El Capitan 10.11.3:
require 'net/http'
Net::HTTP.get URI('https://www.google.com')
# => "<HTML>...</HTML>"
# The site whose certificate got renewed
Net::HTTP.get URI('https://www.example.com')
# => OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed
我在 Google 和 Whosebug 上的所有搜索都得到了提示 Ruby 安装有问题的答案,但它们似乎与旧的 Ruby 版本有关,我不知道不认为这里是这种情况。这是我尝试过的:
brew update
brew upgrade openssl
rvm osx-ssl-certs update all
rvm install ruby-2.3.1 --disable-binary --with-openssl-dir="$(brew --prefix openssl)"
(我之前没有这个版本)rvm requirements
根据 Uzbekjon 的建议,crlrefresh rpv
清除 OSX 系统范围的 CRL 缓存。
我该如何解决这个问题?
备注:
- 新安装的 linux Docker 容器没有 Ruby 2.2.3 时不会出现此问题。所以这可能与 Mac OS 或 SSL 本地缓存有关。
- 此问题可能在证书续订之前就已经存在。我不能确定。但是,正如我在 this question. 中讨论的那样,续订确实导致了我们正在使用的第 3 方的类似问题
- Namecheap 验证证书安装正确,在线检查器显示一切正常,所有主要浏览器都显示证书有效。
解决方案
在 BoraMa 的大力帮助下,现在很清楚发生了什么。 COMODO 添加了一个名为 COMODO RSA Certification Authority
的新根,而不是之前的 COMODO Certification Authority
。新根未在 Mac 的钥匙串中注册,导致此问题。
我们尝试调试的一种方法是 运行:
openssl s_client -connect www.mysite.com:443
显示警告 verify error:num=20:unable to get local issuer certificate
。此警告不是问题,因为 openssl s_client
默认不使用任何证书。 运行 以下内容在下载证书 from COMODO into comodo.pem
(index here 后能够防止警告:
openssl s_client -connect www.mysite.com:443 -CAfile comodo.pem
但是,这不能也没有影响 Ruby OpenSSL 接口。 This article made things much clearer for me, and the SSL doctor script created by its author was also helpful, as it confirmed the hypothesis. The article suggested to look at OpenSSL::X509::DEFAULT_CERT_FILE
, which for me was /usr/local/etc/openssl/cert.pem
. That file did not exist on my machine, which meant Apple's patch for OpendSSL was using the Keychain App. For whatever reason, importing comodo.pem
into my keychain and marking it as trusted based on this post 无效。
因此,解决方案是手动创建 cert.pem
文件。我去了钥匙串应用程序,并将所有系统根证书导出到 system_root.pem
。然后: cat system_root.pem comodo.pem > cert.pem
并将该文件移动到 /usr/local/etc/openssl/
就成功了。 运行 Net::HTTP.get
in Ruby 不再失败。
听起来问题出在您的 OSX 证书缓存上。我猜你在旧证书过期之前更新了证书?
尝试通过 运行 这个命令清除 OSX 系统范围的 CRL 缓存:
crlrefresh rpv
# p - purges cache, r - refreshes them, v - run in verbose mode
这是一个内置的命令行工具,可以更新和维护系统范围的 CRL 缓存。在其 man
页面 (mand crlrefresh
) 中阅读更多相关信息。
我会尝试仔细检查受信任的证书库是否包含 COMODO_RSA_Certification_Authority.pem
证书。在我的 (Linux) 设置中,该站点工作正常,但是当我暂时从证书存储中删除 COMODO 证书颁发机构的证书时,我得到与您完全相同的错误(而在浏览器中它仍然可以正常工作他们自己的证书商店)。
顺便说一句,使用 curl
也可以识别相同的错误,因为它似乎也使用与 ruby 相同的受信任证书存储,因此您可能首先确保该站点在 curl 下工作。
在 linux 中,证书存储通常位于 /etc/ssl/certs
而在 OSX 中,它可能应该是 /System/Library/OpenSSL
(其他选项见 this article ).
您应该会在证书存储目录中看到如下内容:
root@apsara:/etc/ssl/certs$ ls -l | grep COMODO_RSA_Certification_Authority.pem
lrwxrwxrwx 1 root root 73 úno 28 10:24 COMODO_RSA_Certification_Authority.pem -> /usr/share/ca-certificates/mozilla/COMODO_RSA_Certification_Authority.crt
lrwxrwxrwx 1 root root 38 úno 28 10:24 d4c339cb.0 -> COMODO_RSA_Certification_Authority.pem
lrwxrwxrwx 1 root root 38 úno 28 10:24 d6325660.0 -> COMODO_RSA_Certification_Authority.pem
以下是此根 CA 证书的一些属性的片段:
$ openssl x509 -in COMODO_RSA_Certification_Authority.pem -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
4c:aa:f9:ca:db:63:6f:e0:1f:f7:4e:d8:5b:03:86:9d
Signature Algorithm: sha384WithRSAEncryption
Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Certification Authority
Validity
Not Before: Jan 19 00:00:00 2010 GMT
Not After : Jan 18 23:59:59 2038 GMT
Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Certification Authority
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:91:e8:54:92:d2:0a:56:b1:ac:0d:24:dd:c5:cf:
...
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
BB:AF:7E:02:3D:FA:A6:F1:3C:84:8E:AD:EE:38:98:EC:D9:32:32:D4
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha384WithRSAEncryption
...
证书可以从Comodo下载here (index of all certs is here).
更多信息:在调查时,事实证明 Comodo CA 实际上有两个不同的证书认证链。一个是较旧的,是具有上面列出的根 CA 的那个。较新的验证链在链中使用 "External CA root" 个证书。 This forum post 进一步解释,针对 OSX 将这些证书标记为受信任的具体说明。
我整个早上都在为这个错误烦恼。这个问题和答案使我找到了适合我的解决方案。我不会在此处添加新信息,而只是说明我所做的细节,以防在与我的平台类似的平台上出现此错误的任何其他人都可以使用它。
我正在使用:
Ubuntu 16.04
ruby 2.3.0
rails 4.2.7.1
HTTParty
我正在访问使用 COMODO SSL 证书保护的 API。在我的代码中,当我尝试时:
HTTParty.get(secured_url).tap{|response| puts response}
我得到了:
SSL_connect returned=1 errno=0 state=error: certificate verify failed (OpenSSL::SSL::SSLError)
我也使用了上面提到的 SSL doctor 脚本。当我 运行 脚本(用我的实际 api 服务器地址代替 host
)时,我得到:
$ ruby doctor.rb host:443
/home/<redacted>/.rvm/rubies/ruby-2.3.0/bin/ruby (2.3.0-p0)
OpenSSL 1.0.2g 1 Mar 2016: /usr/lib/ssl
SSL_CERT_DIR=""
SSL_CERT_FILE=""
HEAD https://host:443
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed
The server presented a certificate that could not be verified:
subject: <redacted>
issuer: /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
error code 20: unable to get local issuer certificate
在一个单独的终端中,我进入了我的证书目录:
$ cd /etc/ssl/certs
并做了(使用 COMODO_RSA_Organization_Validation_Secure_Server_CA
从上面的 issuer
文本派生而来):
<redacted>:/etc/ssl/certs$ openssl x509 -in COMODO_RSA_Organization_Validation_Secure_Server_CA.pem -noout -text
Error opening Certificate COMODO_RSA_Organization_Validation_Secure_Server_CA.pem
140455648364184:error:02001002:system library:fopen:No such file or directory:bss_file.c:398:fopen('COMODO_RSA_Organization_Validation_Secure_Server_CA.pem','r')
140455648364184:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:400:
unable to load certificate
我去了 COMODO RSA Organization Validation Secure Server CA pem 所在的 COMODO 站点。我将证书复制到桌面上名为 COMODO_RSA_Organization_Validation_Secure_Server_CA.crt
的新文件中(有些说明说使用 crt
扩展名而不是 pem
,即使您需要 pem
证书内容)。
然后,在 these instructions 之后,我做了:
<redacted>:~/Desktop$ sudo cp COMODO_RSA_Organization_Validation_Secure_Server_CA.crt /usr/share/ca-certificates/COMODO_RSA_Organization_Validation_Secure_Server_CA.crt
<redacted>:~/Desktop$ sudo dpkg-reconfigure ca-certificates
然后我做了:
sudo dpkg-reconfigure ca-certificates
然后:
<redacted>:~/Desktop$ ruby doctor.rb host:443
/home/<redacted>/.rvm/rubies/ruby-2.3.0/bin/ruby (2.3.0-p0)
OpenSSL 1.0.2g 1 Mar 2016: /usr/lib/ssl
SSL_CERT_DIR=""
SSL_CERT_FILE=""
HEAD https://host:443
OK
之后我的代码 运行 没问题。谢谢谢谢谢谢!