Last updated: 23 March 2021

In our article about checking the health of SSL certificates we used Qualys’ online SSL Labs checker. If you prefer the command line and know how to parse JSON then you’ll be delighted to know that you can perform the same check using the ssllabs-scan utility.

The utility is particularly useful if you want to automate testing and/or check multiple websites. It has some other neat options, such as checking SSL certificates for websites that aren’t publicly available. To give you an idea of how to use the utility I’ll check the catalyst2.com certificate.

As containers are all the rage I’ll run ssllabs-scan in a Podman container. You don’t have to use a container, and you can of course use Docker instead of Podman (simply replace podman with docker in the commands that follow).

Download the Docker image

The first step is to download (pull) the Docker image. It’s a very small image (just over 5MB):

$ podman pull jumanjiman/ssllabs-scan:latest
✔ docker.io/jumanjiman/ssllabs-scan:latest
Trying to pull docker.io/jumanjiman/ssllabs-scan:latest...
Getting image source signatures
Copying blob 2b3390b5d16d done  
Copying blob 6836ab1d7e3b done  
Copying blob 6e53f611f3e5 done  
Copying config 2a46bf22e3 done  
Writing manifest to image destination
Storing signatures
2a46bf22e388c2e6cfecc877c3a1039249f93d3f961a9fcb2d89c488f8e10709

$ podman images
REPOSITORY                                     TAG     IMAGE ID      CREATED       SIZE
registry.fedoraproject.org/f33/fedora-toolbox  33      af1f279fed20  2 months ago  351 MB
docker.io/jumanjiman/ssllabs-scan              latest  2a46bf22e388  9 months ago  5.68 MB

Scan options

Next, I run the container to check the catalyst2.com certificate. By default, you get a few status messages followed by the IP address, the certificate rating and a huge blob of JSON. If you just want to know the headlines then you can add the --quiet and --grade options. The former option disables status messages and the latter returns just the hostname, IP address and rating:

$ podman run --rm -it jumanjiman/ssllabs-scan:latest --quiet --grade catalyst2.com
HostName:"catalyst2.com"
"84.18.210.139":"A"

If you want all the information then you can use the --quiet option and redirect the output to a JSON file:

$ podman run --rm -it jumanjiman/ssllabs-scan:latest --quiet https://catalyst2.com > catalyst2.com.json

You can now parse the JSON file. For instance, you can use the jq utility to get specific bits of data:

$ jq '.[].endpoints[].grade' catalyst2.com.json
"A"

$ jq '.[].endpoints[].ipAddress' catalyst2.com.json
"84.18.210.139"

$ jq '.[].host' test.json
"https://catalyst2.com"

$ jq '.[].endpoints[].details.protocols' catalyst2.com.json
[
  {
    "id": 771,
    "name": "TLS",
    "version": "1.2"
  },
  {
    "id": 772,
    "name": "TLS",
    "version": "1.3"
  }
]

Other command line tools

Depending on what information you need the ssllabs-scan utility might be overkill. For instance, if you just want to check if a website can be accessed via HTTPS then you can use curl instead:

$ curl -IL https://example.net
curl: (60) SSL certificate problem: self signed certificate
...

openssl s_client

You can also use openssl to get more information about a certificate:

$ openssl s_client -connect example.net:443
CONNECTED(00000003)
depth=0 CN = example.net, O = Examples Rock, L = Exampleville, C = GB, ST = Exampleshire
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = example.net, O = Examples Rock, L = Exampleville, C = GB, ST = Exampleshire
verify return:1
---
Certificate chain
 0 s:CN = example.net, O = Examples Rock, L = Exampleville, C = GB, ST = Exampleshire
   i:CN = example.net, O = Examples Rock, L = Exampleville, C = GB, ST = Exampleshire
---
...
SSL handshake has read 1617 bytes and written 385 bytes
Verification error: self signed certificate
...
Verify return code: 18 (self signed certificate)
...

Clearly, a self-signed certificate can’t be trusted. example.net in Exampleville isn’t a recognised certificate authority! Here’s an example of a certificate that does validate:

$ openssl s_client -connect catalyst2.com:443
CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = RapidSSL RSA CA 2018
verify return:1
depth=0 CN = www.catalyst2.com
verify return:1
---
Certificate chain
 0 s:CN = www.catalyst2.com
   i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = RapidSSL RSA CA 2018
 1 s:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = RapidSSL RSA CA 2018
   i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
---
...
SSL handshake has read 3298 bytes and written 387 bytes
Verification: OK
...
Verify return code: 0 (ok)
...

Checking TLS support

You can also use openssl s_client to check what TLS versions a server supports. For instance, you can check if SSL3 is disabled:

$ openssl s_client -connect catalyst2.com:443 -ssl3
CONNECTED(00000003)
140485809567552:error:141E70BF:SSL routines:tls_construct_client_hello:no protocols available:ssl/statem/statem_clnt.c:1112:
---
no peer certificate available
---
No client certificate CA names sent
---
...

In case you’re wondering, SSL3 is a security nightmare that should be disabled. It’s not secure, so not having support for the protocol is a good thing. In the same way you can check if a server supports TLS 1.2 (which it should):

$ openssl s_client -connect catalyst2.com:443 -tls1_2
CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = RapidSSL RSA CA 2018
verify return:1
depth=0 CN = www.catalyst2.com
verify return:1
---
Certificate chain
 0 s:CN = www.catalyst2.com
   i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = RapidSSL RSA CA 2018
 1 s:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = RapidSSL RSA CA 2018
   i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
---
...

Unfortunately, you can’t simply list all TLS versions supported by a server. To check all TLS versions you need to run multiple commands:

$ openssl s_client -connect catalyst2.com:443 -ssl3
$ openssl s_client -connect catalyst2.com:443 -tls1
$ openssl s_client -connect catalyst2.com:443 -tls1_1
$ openssl s_client -connect catalyst2.com:443 -tls1_2
$ openssl s_client -connect catalyst2.com:443 -tls1_3