您能给一些建议吗?
这里有一个更详细的答案,以及如何在Ruby中修复问题,而不是使用可悲的OpenSSL::SSL::VERIFY_NONE
。
$ openssl s_client -connect 64.103.26.61:443 | openssl x509 -text -noout
depth=2 C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2
...
Subject: C=US, ST=CA, L=San Jose, O=Cisco Systems, Inc., CN=msesandbox.cisco.com
...
X509v3 Subject Alternative Name:
DNS:msesandbox.cisco.com
所以该设备具有 msesandbox.cisco.com 的 DNS 名称。nslookup
告诉您这是一个良好的主机名:
$ nslookup msesandbox.cisco.com
Server: 192.168.1.1
Address: 192.168.1.1
Non-authoritative answer:
Name: msesandbox.cisco.com
Address: 64.103.26.61
因此,你首先要做的是通过DNS名称连接它,而不是IP地址。
如果您为cisco.com
域发行证书(或可以提出请求),那么您可以要求将IP地址64.103.26.61添加为主题备用名称(SAN)。因此,证书中将会有两个SAN。
现在,如果你回到openssl
命令:
$ openssl s_client -connect 64.103.26.61:443 | openssl x509 -text -noout
depth=2 C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2
verify error:num=19:self signed certificate in certificate chain
...
Issuer: C=US, O=HydrantID (Avalanche Cloud Corporation), CN=HydrantID SSL ICA G2
...
Subject: C=US, ST=CA, L=San Jose, O=Cisco Systems, Inc., CN=msesandbox.cisco.com
您会看到证书的颁发者和主题不同。这意味着这不是自签名证书。HydrantID(Avalanche Cloud Corporation)颁发了该证书。
如果您进一步查看,您会发现颁发者的公钥(授权密钥标识符)与主题的公钥(主题密钥标识符)不同:
X509v3 Authority Key Identifier:
keyid:98:6A:B6:2D:2E:BF:A7:AA:9F:F6:F7:D6:09:AF:D5:8B:57:F9:8A:B7
...
X509v3 Subject Key Identifier:
B5:3D:50:53:0A:A2:06:9E:9A:29:89:7A:AB:96:90:FE:9D:6B:57:A0
再次强调,它不是自签名的。
如果你回到 OpenSSL 命令,你会看到颁发者是 HydrantID SSL ICA G2
,它的颁发者是 QuoVadis Root CA2 G3
:
depth=2 C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2
verify return:1
depth=1 C = US, O = HydrantID (Avalanche Cloud Corporation), CN = HydrantID SSL ICA G2
verify return:1
depth=0 C = US, ST = CA, L = San Jose, O = "Cisco Systems, Inc.", CN = msesandbox.cisco.com
verify return:1
这意味着QuoVadis Root CA2 G3
颁发了HydrantID SSL ICA G2
; 而HydrantID SSL ICA G2
又颁发了msesandbox.cisco.com
。 QuoVadis Root CA2 G3
是食物链的顶端。
您可以从QuoVadis CA证书下载获取QuoVadis Root CA2 G3
:
$ curl -O -J -L https://www.quovadisglobal.bm/Repository/~/media/Files/Roots/quovadis_rca2g3_der.ashx
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1380 100 1380 0 0 1808 0 --:--:-- --:--:-- --:--:-- 5726
curl: Saved to filename 'quovadis_rca2g3_der.cer'
$ openssl x509 -in quovadis_rca2g3_der.cer -inform DER -out quovadis-ca.pem -outform PEM
$ cat quovadis-ca.pem
-----BEGIN CERTIFICATE-----
MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL
BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00
...
-----END CERTIFICATE-----
如果你信任QuoVadis对这个设备进行认证,那么:
$ openssl s_client -connect msesandbox.cisco.com:443 -CAfile quovadis-ca.pem
CONNECTED(00000003)
depth=2 C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2
verify return:1
depth=1 C = US, O = HydrantID (Avalanche Cloud Corporation), CN = HydrantID SSL ICA G2
verify return:1
depth=0 C = US, ST = CA, L = San Jose, O = "Cisco Systems, Inc.", CN = msesandbox.cisco.com
verify return:1
...
Start Time: 1420616960
Timeout : 300 (sec)
Verify return code: 0 (ok)
注意OpenSSL完成并显示Verify return code: 0 (ok)
,这表明您已获得了一个良好的证书链。OpenSSL不执行主机名匹配,但我们已经知道证书中的主机名是正确的。
现在,对于Ruby代码,您只需要将CA插入Ruby即可:
#!/usr/bin/ruby
require 'net/http'
require 'net/https'
require 'openssl'
uri = URI('https://msesandbox.cisco.com:443')
options_mask = OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 | OpenSSL::SSL::OP_NO_COMPRESSION
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
if uri.scheme == "https"
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.ca_file = File.join(File.dirname(__FILE__), "quovadis-ca.pem")
end
response = http.request request
这里有一次奔跑:
$ ./Connect-Test.rb
$
没有例外,也不要使用 OpenSSL::SSL::VERIFY_NONE
。
你应该尝试使用 options_mask
,因为它会删除弱/受损/破碎的协议。但是由于 Ruby 有时太过混乱和未记录,我从未能够让它正常工作。
我能够使用 OpenSSL 对 HydrantID SSL ICA G2
和 QuoVadis Root CA2 G3
进行根信任(意味着我从 OpenSSL 得到了 Verify Result 0 (OK)
)。但是 Ruby 只能处理 QuoVadis Root CA2 G3
(它无法构建到 HydrantID SSL ICA G2
的链)。更多的 Ruby 混乱。