openssl s_client Error: verify error:num=2:unable to get issuer certificate - ssl

I need to connect to some https://website.com. So, the site is available via VPN. I'm connected to the VPN and I can open the site in browser.
I've downloaded certificates from browser:
Then I cat both file into one certificate.pem
But when I'm trying to execute command
openssl s_client -connect website.com:443 -CAfile /path/to/certificate.pem
When I execute it in a terminal I have an error.
CONNECTED(00000003)
depth=1 /C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
verify error:num=2:unable to get issuer certificate
issuer= /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
verify return:0
---
Certificate chain
0 s:/C=AU/ST=Wales/L=Place/O=Company
Ltd/OU=D&D/CN=website.com
i:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
---
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject=/C=AU/ST=Wales/L=Place/O=Company
Ltd/OU=D&D/CN=website.com
issuer=/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 2034 bytes and written 328 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES128-SHA
Session-ID: 1533BA958D51B9FEAE4C3534F4A417A5896ED17DCAAE83E89E6C2A7F615A583A
Session-ID-ctx:
Master-Key: 5CF D4ACA242B602AAFSDF1234X23E99BD4C62862888947FACFF0E7503BA34C2DD0EC193FA525204A539
Key-Arg : None
Start Time: 1509781851
Timeout : 300 (sec)
Verify return code: 0 (ok)

openssl historically and by default validates a certificate chain only if it ends at a root. Having the server aka end-entity or leaf cert in the truststore is useless, and the intermediate(s) should not be needed because RFCs require the server to send it(them), but your server is apparently defective or misconfigured because it does not. Thus for your server having the intermediate and root, but not the server cert, in the file used for -CAfile will work, assuming they are in PEM format.
Alternatively, recent (and supported) releases 1.0.2 and 1.1.0 add an option -partial_chain. If specified, this validates if the truststore has any anchor, not just a root. For your server, having either the server cert or the intermediate in the file used for -CAfile is sufficient, again in PEM format.
These cases are described on the man page for verify(1) which is referenced from the man page for s_client(1). Some systems may make the section 1ssl or similar, and if your system is not properly installed or is Windows, they are on the web here.
Remember that openssl historically and by default does not check the server name in the cert. 1.1.0 has new options -verify_name and -verify_hostname that do so. These are described on the man page for verify and referenced on that for s_client.
Also remember that many servers, though apparently not yours, now use Server Name Indication (SNI) extension to support multiple 'virtual' hosts with different certificates, and will either give a wrong cert or reject or fail the connection if SNI is missing. openssl s_client does not send SNI by default, but the option -servername does so; this is described on the man page. Update: OpenSSL 1.1.1 in 2018 s_client now does send SNI by default.
In general looking at the man pages for a program tells you useful information about how the program works and how to use it, and is recommended.
Especially since this is not a programming or development question, and really off-topic for StackOverflow; I would try to propose migration to SuperUser or ServerFault, but they already have numerous dupes.

This error means that openssl is looking for the issuer certificate with the subject "/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA" but it is not provided in the file /path/to/certificate.pem. Suggest to run "openssl x509 -in /path/to/certificate.pem -text" to see the subject of the certificate in this file - should be different from the requested one.

Related

There is a possibility to use let's encrypt certificate for RabbitMQ server?

I currently have a domain named "rabbitmq.<server>.com". I wan't to add SSL certificates to do a AMQPS connection.
I took my nginx certificates generated by certbot (let's encrypt) for the rabbitmq dashboard and i put them into rabbitmq configurations:
#listeners.tcp = none
listeners.ssl.default = 5671
ssl_options.cacertfile = /etc/rabbitmq/certs/fullchain.pem
ssl_options.certfile = /etc/rabbitmq/certs/cert.pem
ssl_options.keyfile = /etc/rabbitmq/certs/privkey.pem
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true
After a restart rabbitmq work and i can diagnostic my connection with openssl on my client computer:
openssl s_client -connect rabbitmq.<server>.com:5671 -cert cert.pem -key privkey.pem -CAfile fullchain.pem -verify 8 -verify_hostname rabbitmq.<server>.com
But openssl raise an error:
00864C1001000000:error:0A000418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:ssl/record/rec_layer_s3.c:1588:SSL alert number 48
I tried to change the verify_peer by verify_none and the SSL client work:
...
SSL handshake has read 4579 bytes and written 405 bytes
Verification error: unable to get issuer certificate
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 2 (unable to get issuer certificate)
---
...
AMQP closed
But i don't appreciate to remove security. And my python pika client doesn't work.
My first question is i am doing the job well ? Do i need to take the server certificates (ca, cert, key) or i need to regenerate another for the client ?
SSL alert number 48 means "unknown_ca". The server cannot verify the client certificate you've sent because it does not find any path to the CA's trusted by the server. You might be missing the root CA for cert the signer of your cert?

unable to make tls1.2 connection via CLI

When I do openssl s_client -CApath ~/cacert.pem -crlf -connect getcomposer.org:443 -servername getcomposer.org I get the following output:
CONNECTED(00000003)
depth=1 C = US, O = Let's Encrypt, CN = R3
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/CN=getcomposer.org
i:/C=US/O=Let's Encrypt/CN=R3
1 s:/C=US/O=Let's Encrypt/CN=R3
i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFTzCCBDegAwIBAgISA4wAKXUPtnZXoYnne5MGiWlHMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yMTA5MzAxMDI5MDlaFw0yMTEyMjkxMDI5MDhaMBoxGDAWBgNVBAMT
D2dldGNvbXBvc2VyLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AMSpt0JoJU7PJQYHYWV5FRTheIQSFi3SM/qyt2RDwKG4g7QssLjmsAXKQ5ZgGNc2
0JOaJ6NS3LgckijVOBOgBpywXTBJ0XOF6JJpjmuivdHXw0tssD+7BD+9Z30M9vCV
i5OU2dw6VmPi7M/J9haO+/ONuMpojmPTI2IKQl7w13y+AN+EqOVn5tWKgMpKxY9y
dydsbqgGffa7aSuN4Rc6UXZ4ix4mfSdjrAxFsKeOAmVh8NfQ49PoEpNAIce7ZQkF
hzq1AZmBtpe76LYrNEO55bPbg5Z9NPBReBpVG4tpLVWPUrarxdhCLD+F5b3s7Ko/
SzAWf/mX/K89Zdd3G8q52gECAwEAAaOCAnUwggJxMA4GA1UdDwEB/wQEAwIFoDAd
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNV
HQ4EFgQU6Z7XW6cbc9xNki5IDKUmJEgZrJ8wHwYDVR0jBBgwFoAUFC6zF7dYVsuu
UAlA5h+vnYsUwsYwVQYIKwYBBQUHAQEESTBHMCEGCCsGAQUFBzABhhVodHRwOi8v
cjMuby5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9yMy5pLmxlbmNyLm9y
Zy8wQwYDVR0RBDwwOoISY2EuZ2V0Y29tcG9zZXIub3Jngg9nZXRjb21wb3Nlci5v
cmeCE3d3dy5nZXRjb21wb3Nlci5vcmcwTAYDVR0gBEUwQzAIBgZngQwBAgEwNwYL
KwYBBAGC3xMBAQEwKDAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlw
dC5vcmcwggEGBgorBgEEAdZ5AgQCBIH3BIH0APIAdwBc3EOS/uarRUSxXprUVuYQ
N/vV+kfcoXOUsl7m9scOygAAAXw2dyOHAAAEAwBIMEYCIQCOGcPZTl5eD4E03Ted
RabOF+lXzyXOPBT3xDtrIYmgxgIhAJAJJzdWzyzX8f6TdbIzGr7xQFhQAIHn/3+1
8ffWn/FjAHcAfT7y+I//iFVoJMLAyp5SiXkrxQ54CX8uapdomX4i8NcAAAF8Nncj
ywAABAMASDBGAiEA97oAvcGhneZl1n+meqzcb6OK5SJoUxYmdlz5LO15BpICIQCL
jrrvGdWMIV/ujHDMAvQ4QUn25GBjf6kps6d6SO6xADANBgkqhkiG9w0BAQsFAAOC
AQEAciXzEuFF5zwYpwv65AkhD1yYGvsqjRNCAe+AqvBVPEfqES/kCBCKeM5UDpAV
+TuJq7OQAGyUHbSAf0JK9DGTN0chTJVShaJEAXgIvnykolab/eNwpxrEOG5wTpRz
p5bJQfR+kVVIyjg0BknDQZMopH1MtWny8LT3jqhBV9eAFaaBh/X46liDACe2VmRv
/MHYGZtMtVnYIcm4iqPMZShMrWkPB7mO6PrUo0QzAUhMpb/KCRb/2XIf+H2I9zzJ
Y5MhKksA3NqDLFW3dD/KrnLKkqtKiOsUGgG1yDR9+S64lNS+IswcsodirXyrtbac
pZAfDeIuhhZ8uGqZhfcdC2OONw==
-----END CERTIFICATE-----
subject=/CN=getcomposer.org
issuer=/C=US/O=Let's Encrypt/CN=R3
---
No client certificate CA names sent
---
SSL handshake has read 3183 bytes and written 455 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: 222874F43D8C5CD5C5EBCE9519D767FC0847D4BCE75261020AEDA2337E84CE87
Session-ID-ctx:
Master-Key: 4C7B19187830AF58A6D03B37163A5C2CEF3222F6BC048D569B122DF372DFCA4CB7FAA0103AAE0C87B5C008E0692C48AD
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1634183395
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---
closed
I don't understand this error. I just got cacert.pem by doing wget --no-check-certificate -O ~/cacert.pem https://curl.se/ca/cacert.pem and doing vim ~cacert.pem verifies that the newly created file is non-empty.
Since the community seems to have accepted this as ontopic:
As I commented, to use in openssl commandline a 'bundle' file in the format supplied by https://curl.se/ca/cacert.pem you must use -CAfile not -CApath.
-CApath works instead with a directory containing a separate file for each cert named by its subject hash, as described in man 1 verify on older versions or man 1 openssl-verification-options on 3.0 also here on the web and which you can use c_rehash to help create if that is really wanted for some reason.
This is a stab in the dark, as I don't understand that openssl output much, but judging by the timing and the keywords 'openssl' and 'Lets Encrypt' this has a reasonably high chance of success.
On September 30, 2021 Let's Encrypt's old Root Certificate has expired. This had a major implication that now they have started to use their own root cert which should be trusted by most devices. 'Most' part was troublesome as there are some devices alive which did not receive updates in years. So the people at Let's Encrypt found a way to still remain supported/trusted on those devices, just under one condition - its openssl version must be 1.1.0+ (which is already 4+ years old). Another important detail is that this openssl version requirement also applies to systems that would have otherwise trusted LE's new cert.
So I've seen numerous people over October scrambling to get LE issued certificates to be trusted again by their systems and the answer was always as simple as: Get your openssl / libopenssl updated to v1.1.0+

Unable To Trust Self-Signed SSL Certificate

I have an application running on Centos7 that needs to connect to a remote host over HTTPS. However, it is unable to verify the certificate and fails. Also, if I try to download a file from the server using wget, I get the below error:
[root#foo:~]# wget https://10.65.127.9/index.html
--2017-05-22 09:03:01-- https://10.65.127.9/index.html
Connecting to 10.65.127.9:443... connected.
ERROR: cannot verify 10.65.127.9's certificate, issued by ‘/CN=us6877vnxe7827’:
Unable to locally verify the issuer's authority.
To connect to 10.65.127.9 insecurely, use `--no-check-certificate'.
So I get the certificate from the host:
openssl s_client -connect 10.65.127.9:443 <<<'' | openssl x509 -out /etc/pki/ca-trust/source/anchors/mycert.pem
And execute the following to process it:
update-ca-trust extract
This however results in the same issue.. If I run:
openssl s_client -connect 10.65.127.9:443 -showcerts -debug
I do get some errors and various messages:
depth=0 CN = us6877vnxe7827
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = us6877vnxe7827
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/CN=us6877vnxe7827
i:/CN=us6877vnxe7827
Server certificate
subject=/CN=us6877vnxe7827
issuer=/CN=us6877vnxe7827
---
No client certificate CA names sent
---
Verify return code: 21 (unable to verify the first certificate)
Any ideas what I may be missing? If any further info helps, please let me know.
For wget you need to provide the certificate authority (CA) certificate(s) that signed the https server certificate. If you have those CA certificates - add them under --ca-certificate=file or --ca-directory=directory options
If you don't have them and you want to skip https server certificate verification (unsecure and can be dangerous) then use --no-check-certificate option.
I had the same problem with Jenkins trying to connect to our GitLab server.
The server does have a valid official certificate in our case, but Java didn't except it.
You are right about downloading the certificate.
However, the application you are mentioning is probably running inside a Java Virtual Machine (as a lot of applications are).
So from the point that you downloaded the certificate to a PEM file, you may have to add it to the VM's trusted certificates instead.
This article describes how to do that. Hope it helps.

Installing SSL cert on Amazon EC2 ELB

I'm new to Amazon Web Services and have been trying to install a SSL certificate on the EC2 instance. I tried following AWS documentation, but found it baffling. I then followed the guide at http://www.robertbrewitz.com/2014/09/aws-and-setting-up-a-custom-ssl-certificate/.
I bought my SSL cert with Go Daddy, and generated 2 files using openssl:
server.key
server.csr
The guide said I should expect 3 certificates:
DigiCertCA.crt
TrustedRoot.crt
star_yourdomain_com.crt
Instead, I confusingly received 2 files named:
f6f65901b1708ae5.crt
gd_bundle-g2-g1.crt
I assume f6f65901b1708ae5.crt is my domain cert (but I'm not certain). Anyway, the guide says I need an Elastic Load Balancer in order to install an SSL cert so I created one.
I generated the private key with:
openssl rsa -in server.key -text
and the public key certficate with:
openssl x509 -inform PEM -in f6f65901b1708ae5.crt
I was also required to enter a Certificate Chain. I wasn't sure what this was and how to get it, so I guessed the command:
openssl x509 -inform PEM -in gd_bundle-g2-g1.crt
and entered the resulting certificate key that began with “-----BEGIN CERTIFICATE-----”
The guide continues, saying I then need to set up Cloudfront. I installed the aws command line tool and in order to generate the PEMs I ran:
openssl rsa -in server.key -text > aws_private.pem
openssl x509 -inform PEM -in f6f65901b1708ae5.crt > aws_public.pem
openssl x509 -inform PEM -in gd_bundle-g2-g1.crt > aws_public.pem
I uploaded the SSL cert with:
aws iam upload-server-certificate --server-certificate-name mydomain_com \
--certificate-body file://aws_public.pem --private-key file://aws_private.pem \
--certificate-chain file://aws_chain.pem --path /cloudfront/mydomain_com/
This was successful.
I then had to create a Cloudfront distribution, which I did, choosing the SSL cert.
However when I go to my https url (https://www.example.org/), it's not working. http://www.example.org/ however does work.
As there are an extraordinarily large amount of steps just for installing an SSL cert, I suspect I've made a mistake along the way. The problem is, I don't know where. Has anybody any pointers?
Also, are there not any simpler ways for installing an SSL cert? It seems to be ridiculously complex for something so common. I'd be willing to pay an expert to do it for me (I'm a software developer with almost no knowledge of anything SSL related), but its difficult to find anyone for such a task (and there is the problem of having to hand over login details etc). Any help greatly appreciated.
EDIT
The suggestion below is that I should use AWS Certificate Manager. I've had a look and this seems like a far more painless option. However, I did spend 86 euro on an SSL cert from Go Daddy so I'd prefer if that didn't go to waste. Is any of my work salvageable? Are there mean to resell SSL certs?
EDIT
I still haven't found a real solution to this. To clarify, I have a very niche site that will have very few visitors. I have the site on a EC2 instance. I followed the site above which advised using a Load Balancer and Cloudfront in order to encrypt with SSL. However, it's not working and it's probably overkill anyway. Can anyone help me with this? I'd like to use the SSL cert I paid for, but if not, should I use something like Lets Encrypt?
You mentioned the guide saying to expect 3 files, including a "DigiCertCA.crt" file; sounds like it was written with DigiCert as your cert provider in mind, rather than GoDaddy.
Certificates
First, to make sure that that "f6f65901b1708ae5.crt" contains your requested certificate (and lay to rest any doubts there). To do this, you can compare the data (e.g. Common Name (CN), DNS Subject Alternative Names (SANs), etc) in your "server.csr" file (that's the Certificate Signing Request) with what's in that "f6f65901b1708ae5.crt" file:
$ openssl req -noout -text < server.csr
This should display human-readable text about the details for your domain in the CSR file. Compare that with:
$ openssl x509 -noout -text < f6f65901b1708ae5.crt
This should display similar human-readable text, with more details/fields filled in. But they should roughly have what you expect. Note that if you see an error similar to this:
51299:error:0906D06C:PEM routines:PEM_read_bio:no start line:/SourceCache/OpenSSL098/OpenSSL098-52.40.1/src/crypto/pem/pem_lib.c:648:Expecting: TRUSTED CERTIFICATE
Then it suggests that your "f6f65901b1708ae5.crt" file is in DER format, not PEM format. If not, then you already have a PEM file, which is what AWS ELBs expect. If you have a DER formatted cert, it's easy to convert to PEM format, using:
$ openssl x509 -in f6f65901b1708ae5.crt -inform DER -out f6f65901b1708ae5.pem -outform PEM
I just wanting to be thorough by mentioning this part.
Assuming, now, that we know that that "f6f65901b1708ae5.crt" contains the PEM formatted certificate for your domain, we're ready to handle the "certificate chain" part.
I looked at GoDaddy's online certificate repository, to see if the "gd_bundle-g2-g1.crt" file you mentioned was there, and it was. (It's OK for these files to be publicly available, as they contain the public certificates which are meant for anyone/everyone to use.) Looking at that gd_bundle-g2-g1.crt file, I found that it contains multiple certificates. This is important.
See, a "certificate chain" is a list of files which provide a trust path (or "chain"), from that "f6f65901b1708ae5.crt" certificate you have to the trusted root GoDaddy CA certificate. Each certificate has a subject (who it was issued to), and an issuer (who issued it). This means that you can walk "backward", from your certificate to the issuer's certificate, to that certificate's issuer's certificate, etc. This walking backward is the "certificate chain".
The fact that that "gd_bundle-g2-g1.crt" file contains multiple certificates implies that that file contains the certificate chain you need. It also means that you do not want to do this:
$ openssl x509 -inform PEM -in gd_bundle-g2-g1.crt > aws_public.pem
because openssl x509 only reads the first certificate in the specified file, and you need all of them.
Given all of the above, you might need only the following (to make sure that your private key is PEM formatted):
$ openssl rsa -in server.key -text > aws_private.pem
And then, since we'll assume that "f6f65901b1708ae5.crt" is already PEM formatted (and if not, you know how to convert it above), and we know that "gd_bundle-g2-g1.crt" is already PEM formatted, we'll now be ready to upload these to the AWS ELB.
AWS ELB
To upload the certificates and key for use by the ELB, use something like this:
$ aws iam upload-server-certificate \
--server-certificate-name redmatterapp_com2 \
--certificate-body file://f6f65901b1708ae5.crt \
--private-key file://aws_private.pem \
--certificate-chain file://gd_bundle-g2-g1.crt \
--path /cloudfront/redmatterapp_com/
Note that I used a different --server-certificate-name, just to make sure it didn't override/conflict with your existing configuration. As a suggestion, you might include the date of when the cert being uploaded was created (or, better, when it will expire), as part of the name, as a hint to your future self of when that cert was added, e.g. "redmatterapp_com-2016-02-18".
Also note that if you are not using CloudFront, then you should not use the --path option. If you were using CloudFront and then removed it, I'd highly recommend doing the above aws iam upload-server-certificate command again, only with a different --server-certificate-name and no --path option (and removing the previous name). This may mean re-configuring any existing ELB HTTPS listeners to use the new certificate name, but it may be necessary, as that --path affects SSL handling.
Once the above is done, using the e.g. AWS Console, you should be able to configure your AWS ELB, and under the "Listeners" tab, click "Edit". Add a Listener e.g. for "https". When adding any SSL-capable listener, you'll see a "Change" link appear under the "SSL Certificate" column/tab. Click that "Change", and choose the "existing certificate" button. Under the "Certificate Name" dropdown, then, you should see an entry for the --server-certificate-name string/label you used above. Choose that entry, then click "Save". Now connections to that Listener, on your AWS ELB, should be properly configured for SSL/TLS connections that browsers will trust.
Thus the HTTPS Listener configuration would look something like:
Load Balancer Protocol: HTTPS
Load Balancer Port: 443
Instance Protocol: HTTP
Instance Port: 80
Cipher: (default policy)
SSL Certificate: (--server-certificate-name name)
Note that you do not want to use port 443 for the instance port as well; if you do, that says that you want HTTPS from the ELB to your instance, which is not usually needed. (Some secure sites want this, but that's a different topic/store.) Thus the above configures the ELB to handle the SSL termination; to your Node.js server on the instance, it only ever receives plain HTTP requests on port 80:
client ---> HTTP ---> ELB port 80 ---> HTTP ---> server port 80
client ---> HTTPS --> ELB port 443 --> HTTP ---> server port 80
If your server needs to know whether the original request was HTTP or HTTPS, look for the X-Forwarded-For (and other request headers) that the AWS ELB will automatically add to the request.
Now, once you have the ELB configured, it's a good step to verify that it's working properly. First, you can use openssl s_client to verify that the SSL handshake works:
$ openssl s_client -connect example.com:443
CONNECTED(00000003)
depth=3 /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
verify error:num=19:self signed certificate in certificate chain
verify return:0
---
Certificate chain
0 s:/OU=Domain Control Validated/CN=redmatterapp.com
i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
2 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
3 s:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/CN=example.com
issuer=/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
---
No client certificate CA names sent
---
SSL handshake has read 4929 bytes and written 456 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : AES128-SHA
...
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
The above shows that we successfully completed an SSL handshake, and you can see that it shows the cert chain with the GoDaddy names; the "Server certificate" section should match the "f6f65901b1708ae5.crt" PEM file you loaded.
HTTPS and DNS
Now to test the HTTPS part; for this, I like to use curl, like so:
$ curl -kv https://example.com/
The -v option display more information, in particular whether the certificate matches the DNS name or not; the -k tells curl to ignore any certificate mismatches/issues, so that we can then see the verbose information about things.
This is where a little more configuration is necessary. If you use the auto-generated ELB DNS name in your curl command (or in your browser), then you will most likely see security warnings/issues. Why? Because part of HTTPS is verifying that the DNS name you use in your URL matches the domain/host name in your server certificate, either as the Common Name (CN) in your certificate, or as one of the DNS Subject Alternative Names (SANs). And you probably didn't include the ELB DNS name in your Certificate Signing Request (CSR) to GoDaddy.
This means, then, that the next step is to configure a DNS CNAME record that points to the AWS ELB name, e.g.:
www.example.com CNAME to aws-elb-1.elb.amazonaws.com
If you're using AWS for DNS, then you could do this using e.g. Route 53. Then you retry your curl command (or browser):
curl -kv https://www.example.com/
Another important thing to watch for (and you can see this in the curl -v output) is the contents of the Host request header. Some HTTP servers (i.e. the one running on your backend instance) are very picky about the value there; they want the Host header to match something in their configuration, and if it doesn't, they may refuse the request.
Another common gotcha is:
HTTP 503 Service Unavailable: Back-end server is at capacity
If you get this response from your ELB, it usually means that your backend servers are not responding or are failing to respond to the ELB healtcheck. Double-check that the port and path/URL used for the ELB healtcheck are correct, and that any firewalls or AWS Security Groups allow connectivity from the ELB to your instances.
So, now you should have an ELB which forwards port 80 (HTTP) and port 443 (HTTPS) to your backend instances. And you have a CNAME record for "www.example.com" in DNS that points to that ELB name. What's left?
HTTP Redirects
I highly recommend configuring your HTTP server to always redirect to the HTTPS equivalent of the same URL. Why?
For security of the data between your clients and your server, using SSL/TLS is now expected. So much so that more and more browsers automatically try HTTPS first, and only begrudgingly use HTTP as a fallback. Browsers like Chrome (and others) want to avoid this HTTP fallback so much so that they've introduced mechanisms like HTTP Strict Transport Security: a way for your site to tell the browser to only ever use HTTPS for the site, never HTTP. Plus it's always a better marketing story; in fact, you can expect to get negative reactions from your clients/users if you don't use HTTPS.
There's another thing that using HTTPS for all your site's traffic protects you from: someone else using their DNS name and your ELB. You have a CNAME record for "www.example.com" that points to "aws-elb-1.elb.amazonaws.com". But what if I also create my own CNAME for "www.evilco.com", which points to the same "aws-elb-1.elb.amazonaws.com"? Folks going to "www.evilco.com" will see your site, and think it's mine!
By forcing all traffic for your site to be HTTPS, you force all of the HTTPS clients to verify that the certificate presented by the server (i.e. your "f6f65901b1708ae5.crt" file) contains a Common Name (CN) or DNS Subject Alternative Name (SAN) that matches the domain name the client used in its URL. Obviously your certificate does not contain CN or DNS SANs for "www.evilco.com", and thus that verification process would fail -- and the end user would see that something is fishy. But if you allow HTTP traffic as well for your site, this phenomenon could happen -- and you, looking at your site's logs, would never know!
Postscript
I've not used the AWS Certificate Manager, or CloudFront, myself (so I can't comment on them), but I have used the above process, multiple times, for various certificate provisioning of multiple domains, at multiple jobs.
Hope this helps!

OpenSSL: unable to verify the first certificate for Experian URL

I am trying to verify an SSL connection to Experian in Ubuntu 10.10 with OpenSSL client.
openssl s_client -CApath /etc/ssl/certs/ -connect dm1.experian.com:443
The problem is that the connection closes with a Verify return code: 21 (unable to verify the first certificate).
I've checked the certificate list, and the Certificate used to sign Experian (VeriSign Class 3 Secure Server CA - G3) is included in the list.
/etc/ssl/certs/ca-certificates.crt
Yet I don't know why it is not able to verify the first certificate.
The entire response could be seen here:
https://gist.github.com/1248790
The first error message is telling you more about the problem:
verify error:num=20:unable to get local issuer certificate
The issuing certificate authority of the end entity server certificate is
VeriSign Class 3 Secure Server CA - G3
Look closely in your CA file - you will not find this certificate since it is an intermediary CA - what you found was a similar-named G3 Public Primary CA of VeriSign.
But why does the other connection succeed, but this one doesn't? The problem is a misconfiguration of the servers (see for yourself using the -debug option). The "good" server sends the entire certificate chain during the handshake, therefore providing you with the necessary intermediate certificates.
But the server that is failing sends you only the end entity certificate, and OpenSSL is not capable of downloading the missing intermediate certificate "on the fly" (which would be possible by interpreting the Authority Information Access extension). Therefore your attempt fails using s_client but it would succeed nevertheless if you browse to the same URL using e.g. FireFox (which does support the "certificate discovery" feature).
Your options to solve the problem are either fixing this on the server side by making the server send the entire chain, too, or by passing the missing intermediate certificate to OpenSSL as a client-side parameter.
Adding additional information to emboss's answer.
To put it simply, there is an incorrect cert in your certificate chain.
For example, your certificate authority will have most likely given you 3 files.
your_domain_name.crt
DigiCertCA.crt # (Or whatever the name of your certificate authority is)
TrustedRoot.crt
You most likely combined all of these files into one bundle.
-----BEGIN CERTIFICATE-----
(Your Primary SSL certificate: your_domain_name.crt)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Your Intermediate certificate: DigiCertCA.crt)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Your Root certificate: TrustedRoot.crt)
-----END CERTIFICATE-----
If you create the bundle, but use an old, or an incorrect version of your Intermediate Cert (DigiCertCA.crt in my example), you will get the exact symptoms you are describing.
SSL connections appear to work from browser
SSL connections fail from other clients
Curl fails with error: "curl: (60) SSL certificate : unable to get local issuer certificate"
openssl s_client -connect gives error "verify error:num=20:unable to get local issuer certificate"
Redownload all certs from your certificate authority and make a fresh bundle.
I came across the same issue installing my signed certificate on an Amazon Elastic Load Balancer instance.
All seemed find via a browser (Chrome) but accessing the site via my java client produced the exception javax.net.ssl.SSLPeerUnverifiedException
What I had not done was provide a "certificate chain" file when installing my certificate on my ELB instance (see https://serverfault.com/questions/419432/install-ssl-on-amazon-elastic-load-balancer-with-godaddy-wildcard-certificate)
We were only sent our signed public key from the signing authority so I had to create my own certificate chain file. Using my browser's certificate viewer panel I exported each certificate in the signing chain. (The order of the certificate chain in important, see https://forums.aws.amazon.com/message.jspa?messageID=222086)
Here is what you can do:-
Exim SSL certificates
By default, the /etc/exim.conf will use the cert/key files:
/etc/exim.cert
/etc/exim.key
so if you're wondering where to set your files, that's where.
They're controlled by the exim.conf's options:
tls_certificate = /etc/exim.cert
tls_privatekey = /etc/exim.key
Intermediate Certificates
If you have a CA Root certificate (ca bundle, chain, etc.) you'll add the contents of your CA into the exim.cert, after your actual certificate.
Probably a good idea to make sure you have a copy of everything elsewhere in case you make an error.
Dovecot and ProFtpd should also read it correctly, so dovecot no longer needs the ssl_ca option.
So for both cases, there is no need to make any changes to either the exim.conf or dovecot.conf(/etc/dovecot/conf/ssl.conf)
If you are using MacOS use:
sudo cp /usr/local/etc/openssl/cert.pem /etc/ssl/certs
after this Trust anchor not found error disappears
For those using zerossl.com certificates, drag and drop all certificates (as is) to their respective folders.
Cut and pasting text into existing files, may cause utf8 issues - depending upon OS, format and character spacings.