How to debug SSL handshake using cURL?

I would like to troubleshoot per directory authentication with client certificate. I would specially like to find out which acceptable client certificates does server send.

How do I debug SSL handshake, preferably with cURL?


I have used this command to troubleshoot client certificate negotiation:

openssl s_client -connect www.test.com:443 -prexit

The output will probably contain "Acceptable client certificate CA names" and a list of CA certificates from the server, or possibly "No client certificate CA names sent", if the server doesn't always require client certificates.


curl -iv https://your.domain.io

That will give you cert and header output if you do not wish to use openssl command.


curl probably does have some options for showing more information but for things like this I always use openssl s_client

With the -debug option this gives lots of useful information

Maybe I should add that this also works with non HTTP connections. So if you are doing "https", try the curl commands suggested below. If you aren't or want a second option openssl s_client might be good


  1. For TLS handshake troubleshooting please use openssl s_client instead of curl.
  2. -msg does the trick!
  3. -debug helps to see what actually travels over the socket.
  4. -status OCSP stapling should be standard nowadays.
openssl s_client -connect example.com:443 -tls1_2 -status -msg -debug -CAfile <path to trusted root ca pem> -key <path to client private key pem> -cert <path to client cert pem> 

Other useful switches -tlsextdebug -prexit -state

https://www.openssl.org/docs/man1.0.2/man1/s_client.html


curl has a --trace (and --trace-ascii) option, which prints basically everything, including all SSL/TSL handshaking. Since --trace supersedes other verbosity options, all you need is

curl --trace /path/to/trace.log https://example.com

You can then read up on ietf to match the messages from the log to the respective messages from the standard - e.g. TLS v1.2, TLS v1.3, curl even prints the corresponding message number from the standard like:

== Info: TLSv1.3 (OUT), TLS handshake, Client hello (1):

Where the (1) is the message number.

--trace-ascii works just as --trace but does not print the binary data.