https connection using CURL from command line

CurlSslCommand LineHttpsCertificate

Curl Problem Overview


I am new to Curl and Cacerts world and facing a problem while connecting to a server. Basically, I need to test connectivity over https from one machine to another machine. I have a URL to which I need to connect from Machine A (a linux machine) I tried this on command prompt

cmd> curl https://[my domain or IP address]

and got the following:

curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

On going through some articles over internet I did this:

openssl s_client -connect <domain name or Ip address>:443

and got some response including the server certificate (inside -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----).

What should I do next from here. I think, I will have to just copy paste the text inside BEGIN CERTIFICATE & END CERTIFICATE and save it in a file. But, What type of file it should be? .pem, .crt ?.. What should I be do after that?

I tried this - copied the text inside BEGIN CERTIFICATE & END CERTIFICATE and saved it in a .crt file - named it as my-ca.crt (also tried the same thing by naming it as my-ca.pem file) and then did this:

cmd>curl --cacert my-ca.crt https://[my domain or IP address]

But got the same error.

Curl Solutions


Solution 1 - Curl

I had the same problem - I was fetching a page from my own site, which was served over HTTPS, but curl was giving the same "SSL certificate problem" message. I worked around it by adding a -k flag to the call to allow insecure connections.

curl -k https://whatever.com/script.php

Edit: I discovered the root of the problem. I was using an SSL certificate (from StartSSL, but I don't think that matters much) and hadn't set up the intermediate certificate properly. If you're having the same problem as user1270392 above, it's probably a good idea to test your SSL cert and fix any issues with it before resorting to the curl -k fix.

Solution 2 - Curl

Basic certificate info

That's my everyday script:

curl --insecure -vvI https://www.example.com 2>&1 | awk 'BEGIN { cert=0 } /^\* SSL connection/ { cert=1 } /^\*/ { if (cert) print }'

Output:

* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=California; L=Los Angeles; O=Verizon Digital Media Services, Inc.; CN=www.example.org
*  start date: Dec 10 00:00:00 2021 GMT
*  expire date: Dec  9 23:59:59 2022 GMT
*  issuer: C=US; O=DigiCert Inc; CN=DigiCert TLS RSA SHA256 2020 CA1
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x5588e1f5ae30)
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
* Connection #0 to host www.example.com left intact

Full certificate info

openssl s_client -connect www.example.com:443 </dev/null 2>/dev/null | openssl x509 -inform pem -text

Solution 3 - Curl

You need to provide the entire certificate chain to curl, since curl no longer ships with any CA certs. Since the cacert option can only use one file, you need to concat the full chain info into 1 file

Copy the certificate chain (from your browser, for example) into DER encoded binary x.509(.cer). Do this for each cert.

Convert the certs into PEM, and concat them into 1 file.

openssl x509 -inform DES -in file1.cer -out file1.pem -text
openssl x509 -inform DES -in file2.cer -out file2.pem -text
openssl x509 -inform DES -in file3.cer -out file3.pem -text

cat *.pem > certRepo

curl --cacert certRepo -u user:passwd -X GET -H 'Content-Type: application/json' "https//somesecureserver.com/rest/field"

I wrote a blog on how to do this here: http://javamemento.blogspot.no/2015/10/using-curl-with-ssl-cert-chain.html

Solution 4 - Curl

use --cacert to specify a .crt file. ca-root-nss.crt for example.

Solution 5 - Curl

I actually had this kind of problem and I solve it by these steps:

  1. Get the bundle of root CA certificates from here: https://curl.haxx.se/ca/cacert.pem and save it on local

  2. Find the php.ini file

  3. Set the curl.cainfo to be the path of the certificates. So it will something like:

Solution 6 - Curl

Here you could find the CA certs with instructions to download and convert Mozilla CA certs. Once you get ca-bundle.crt or cacert.pem you just use:

curl.exe --cacert cacert.pem https://www.google.com

or

curl.exe --cacert ca-bundle.crt https://www.google.com

Solution 7 - Curl

having dignosed the problem I was able to use the existing system default CA file, on debian6 this is:

/etc/ssl/certs/ca-certificates.crt

as root this can be done like:

echo curl.cainfo=/etc/ssl/certs/ca-certificates.crt >> /etc/php5/mods-available/curl.ini

then re-start the web-server.

Solution 8 - Curl

you could use this

curl_setopt($curl->curl, CURLOPT_SSL_VERIFYPEER, false);

Solution 9 - Curl

You need the certificates chain and not a single certificate. It is easy to get it using Firefox:

  1. Open the url in Firefox.
  2. Click on the security icon on the address box left to the url.
  3. Click on connection not secure, more information. Under the security tab, select view certificate, scroll toward the end. Next to download, select the PEM(chain) to download the chain of certificates.

Now you have the chain of certificates as a file that you can use in the curl request after the --cacert flag:
curl --cacert downloaded.pem -X POST https://the-url-to-access

Solution 10 - Curl

For me, I just wanted to test a website that had an automatic http->https redirect. I think I had some certs installed already, so this alone works for me on Ubuntu 16.04 running curl 7.47.0 (x86_64-pc-linux-gnu) libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3

curl --proto-default https <target>

Solution 11 - Curl

With modern versions of curl, you can simply override which ip-address to connect to, using --resolve or --connect-to (curl newer than version 7.49). This works even with SSL/SNI. All details are in the man page.

For example, to override DNS and connect to www.example.com with ssl using a particular ip address: (This will also override ipv6)

curl --resolve www.example.com:443:192.168.42.2 https://www.example.com/

Another example, to connect to a particular backend server named backend1 on port 8080

curl --connect-to www.example.com:80:backend1.example.com:8080 http://www.example.com/

Remember to add the host header if the server needs that to answer correctly:

-H 'Host:www.example.com' 

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1270392View Question on Stackoverflow
Solution 1 - CurlDave ChildView Answer on Stackoverflow
Solution 2 - CurlAntonio CostaView Answer on Stackoverflow
Solution 3 - CurlSomaiah KumberaView Answer on Stackoverflow
Solution 4 - CurlanoView Answer on Stackoverflow
Solution 5 - CurlgeckobView Answer on Stackoverflow
Solution 6 - CurllmiguelmhView Answer on Stackoverflow
Solution 7 - CurlJasenView Answer on Stackoverflow
Solution 8 - CurlAhmed AliView Answer on Stackoverflow
Solution 9 - CurlTal HahamView Answer on Stackoverflow
Solution 10 - CurlSamCyanideView Answer on Stackoverflow
Solution 11 - CurlingvarhaView Answer on Stackoverflow