Last updated:
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).
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
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" } ]
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 ...
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) ...
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