SSLError: hostname "W.X.Y.Z" does not match the server certificate
Asked Answered
V

3

5

I just started to learn Ruby and after some basic things, I'm trying to understand making REST calls to a service in ruby. I can make get requests to foursquare API without any trouble. On the other hand calls to Cisco CMX API give error. My ruby version is 2.1.2. I searched many solutions on the web but still got problem. This my shell command that I run.

Working One

$resclient
>> RestClient.get 'https://api.foursquare.com/v2/venues/search?ll=40.7,-74&oauth_token=0ZDO1JMJ0PW2QTCDK50OGZ21UENHZ0Y3KIDQZJLLURTQNRQ2&v=20150106'

This gives error

$restclient
>> RestClient.get 'https://learning:[email protected]/api/contextaware/v1/maps/.json'

My error log:

OpenSSL::SSL::SSLError: hostname "64.103.26.61" does not match the server certificate
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/2.1.0/openssl/ssl.rb:139:in `post_connection_check'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/2.1.0/net/http.rb:922:in `connect'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/2.1.0/net/http.rb:863:in `do_start'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/2.1.0/net/http.rb:852:in `start'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/rest-client-1.7.2/lib/restclient/request.rb:413:in `transmit'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/rest-client-1.7.2/lib/restclient/request.rb:176:in `execute'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/rest-client-1.7.2/lib/restclient/request.rb:41:in `execute'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/rest-client-1.7.2/lib/restclient.rb:65:in `get'
from (irb):3
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/rest-client-1.7.2/bin/restclient:93:in `<top (required)>'
from /Users/apple/.rbenv/versions/2.1.2/bin/restclient:23:in `load'
from /Users/apple/.rbenv/versions/2.1.2/bin/restclient:23:in `<main>'

Could you please give some advise? Thank you

Vingtetun answered 6/1, 2015 at 9:17 Comment(0)
C
14

Could you please give some advise?

Here's a more detailed answer and how to fix the problem in Ruby with something other than the pathetic 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

So the appliance has a DNS name of msesandbox.cisco.com. nslookup tells you its a good hostname:

$ nslookup msesandbox.cisco.com
Server:     192.168.1.1
Address:    192.168.1.1#53

Non-authoritative answer:
Name:   msesandbox.cisco.com
Address: 64.103.26.61

So the first thing you have to do is connect to it by its DNS name, and not an IP address.

If you issue certificates for the cisco.com domain (or can make a request), then you can ask that the IP address 64.103.26.61 be added as a Subject Alternative Name (SAN). So there will be two SANs in the certificate.


Now, if you go back to the openssl command:

$ 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

You will see the issuer and subject are different. That means this is not a self signed certificate. The certificate was issued by HydrantID (Avalanche Cloud Corporation).

If you look further, you will see the Issuer's public key (Authority Key Identifier) is different than the Subject's public key (Subject Key Identifier):

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

Again, its not self signed.


If you go back to the OpenSSL command again, you will see the issuer is HydrantID SSL ICA G2, and its issuer is 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

That means QuoVadis Root CA2 G3 issued HydrantID SSL ICA G2; and HydrantID SSL ICA G2 issued msesandbox.cisco.com. QuoVadis Root CA2 G3 is the top of the food chain.

You can fetch QuoVadis Root CA2 G3 from QuoVadis CA Certificate Download:

$ 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-----

IF you trust QuoVadis to certify the appliance, then:

$ 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)

Notice OpenSSL finished with Verify return code: 0 (ok). That tells you you got a good chain. OpenSSL does not perform hostname matching, but we already know that the hostname in the certificate is good.


Now, for Ruby code. All you need to do is plug the CA into 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")
  # http.ssl_options = options_mask
end

response = http.request request

And here's a run:

$ ./Connect-Test.rb 
$ 

No exceptions, and no OpenSSL::SSL::VERIFY_NONE.

You should try to use options_mask since it removes weak/wounded/broken protocols. But Ruby's so broken and undocumented at times, I have never been able to get it to work.


I was able to root trust in both HydrantID SSL ICA G2 and QuoVadis Root CA2 G3 with OpenSSL (meaning I got a Verify Result 0 (OK) from OpenSSL). But Ruby could only handle QuoVadis Root CA2 G3 (it could not build a chain to HydrantID SSL ICA G2). More Ruby broken-ness.

Cary answered 7/1, 2015 at 7:51 Comment(1)
Thank you for your detailed answer. I now understand the issue. It looks like this self-signed certificate is not proper for my localhost. I installed a gem called certified which handles this problem (I don't know how it works) I removed OpenSSL::SSL::VERIFY_NONE from my code. As you said, for production I'm going to download the certificate from QuoVadis CA Certificate DownloadVingtetun
A
1

If you go to your Host with an browser, like

>  https://64.103.26.61/

you will see you will get the same error. The certificate on this server is not valid, as the server responds on another hostname than the one written in the certificate.

You can look up a more complex description if you enter the Server address at Digicert Helpcenter. The Certificate has been issued to msesandbox.cisco.com. If this is the address you are trying to reach, use this one instead of the IP. If this is your Server, Change the Response Name

Argillite answered 6/1, 2015 at 9:23 Comment(3)
Unfortunately, it is not mine.Vingtetun
Then, try to setup your Connection via RestClient.get 'learning:[email protected]/api/contextaware/v1/maps/…' or try to contact the adminArgillite
Well, thats the way you could do it, but it is pretty unsafe, thats why i did not recommend this to youArgillite
V
-2

One almost always bad workaround is to ignore the SSL certificate checks:

:verify_ssl => OpenSSL::SSL::VERIFY_NONE

UPDATE: This workaround almost never be preferred, since it's usually summing up to be a glaring security hole that is easy to forget. In most cases where you'd think you want SSL without checking the certificate, you would do better by generating a self-signed certificate and lock both sides to use the same.

Vingtetun answered 6/1, 2015 at 9:45 Comment(2)
No, that's not a solution. It could be part of a solution, like Public Key Pinning. But as a stand alone measure, its no solution at all.Cary
I think it's an OK solution if you know what you're doing, or in a controlled environment, or trying to communicate to localhost. Not like SSL solves every security issue or anything that doesn't use it is automatically super insecure.Springbok

© 2022 - 2024 — McMap. All rights reserved.