As a system administrator, understanding OpenSSL is critical for managing secure connections to your web servers and applications. OpenSSL is an open-source toolkit that provides developers with various cryptographic functions to secure communications over networks.

One of the most useful OpenSSL commands is the s_client, which allows you to manually test and debug SSL/TLS connections. In this comprehensive guide, we will walk you through the practical examples of using the OpenSSL s_client to test, troubleshoot, and validate SSL certificates and connections.

Getting Started with OpenSSL s_client

The OpenSSL s_client tool enables you to connect to any TLS/SSL server to query information about the certificate and test the encrypted connection.

To use the s_client, the basic syntax is:

openssl s_client [options] [host:port]

Some examples of running the openssl s_client:

openssl s_client -connect www.example.com:443

This will connect to example.com over port 443 (HTTPS) and print details about the certificate and encryption in use.

openssl s_client -connect smtp.example.com:465 -starttls smtp

Here we connect to the smtp server on port 465 and then upgrade to an encrypted connection using SMTP STARTTLS.

In the following sections, we will explore various practical examples of querying SSL servers using openssl s_client.

1. Testing Basic SSL Connectivity

To check that your server accepts SSL connections, you can use s_client with the -connect option:

openssl s_client -connect www.mydomain.com:443
  • The -connect option specifies the host and port to connect to
  • Port 443 is typically used for HTTPS

This will attempt an SSL/TLS handshake with the server and print output similar to:

CONNECTED(00000003)
depth=2 OU = Domain Control Validated, OU = PositiveSSL Wildcard, CN = *.mydomain.com
verify return:1
depth=1 C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA
verify return:1
depth=0 CN = *.mydomain.com
verify return:1
---
Certificate chain
 0 s:CN = *.mydomain.com
   i:C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA
-----BEGIN CERTIFICATE-----
<cert contents here>
-----END CERTIFICATE-----
 1 s:C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA
   i:C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
-----BEGIN CERTIFICATE----- 
<cert contents here>
-----END CERTIFICATE-----
---
Server certificate
subject=CN = *.mydomain.com

issuer=C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA

---
Acceptable client certificate CA names
/C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Domain Validation Secure Server CA
/C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
---
SSL handshake has read 4419 bytes and written 489 bytes
Verification: OK
---
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: 0 (ok)
---

Key things to check in the output:

  • CONNECTED – this shows a TCP connection was established
  • Certificate chain – contains the server cert + intermediate issuing CA certificates
  • Verification: OK – the certificate chain is trusted
  • SSL handshake bytes – data exchanged in handshake
  • Verify return code: 0 – the handshake was successful

This allows you to confirm connectivity, view certificate details, and ensure encryption is in use between a client and your server.

2. Getting Certificate Details

To get all the X509 certificate details served by a host, use the -showcerts option:

openssl s_client -connect www.mydomain.com:443 -showcerts

This prints the full certificate chain sent by the server and various details about each certificate:

CONNECTED(00000003)
---
Certificate chain
 0 s:CN = *.mydomain.com
   i:C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA
-----BEGIN CERTIFICATE-----
MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQsFADCB
kDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
<truncated>
a1+G7otRhsXRwPXYytnRILn3AeiWXDzjR1ht/aAy8ZPj
-----END CERTIFICATE-----
 1 s:C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA
   i:C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
-----BEGIN CERTIFICATE-----
MIIEZTCCA02gAwIBAgIQQAF1BIMUpMghjISpDBbN3zANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
<truncated>
t8BdUXCRM08fC6UNOoSX6B8uBIhNSbHEb4hIOWboAjQ9KZhZYCvA8N6vTAR54xg=
-----END CERTIFICATE-----
---
Server certificate
subject=CN = *.mydomain.com

issuer=C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA

---
Acceptable client certificate CA names
/C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Domain Validation Secure Server CA  
/C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
---
SSL handshake has read 4419 bytes and written 489 bytes
Verification: OK
...

Key details this exposes:

  • Issuer – The CA that issued the certificate
  • Validity period – Date range the certificate is valid for
  • Subject – Domains/hostnames the cert is issued for
  • Public key – RSA / ECDSA public key in the certificate
  • Signature algorithm – Algorithm used to sign the certificate

This helps you inspect the certificate validity, usage terms, and cryptographic details relevant for debugging SSL issues.

3. Checking Certificate Validity

To specifically test that a certificate is properly signed by a trusted CA, use the -verify_return_error option:

openssl s_client -verify_return_error -connect www.mydomain.com:443

This performs the SSL handshake, focusing only on validating the certificate trust chain:

CONNECTED(00000003)
depth=2 OU = Domain Control Validated, OU = PositiveSSL Wildcard, CN = *.mydomain.com
verify return:1
depth=1 C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA  
verify return:1
depth=0 CN = *.mydomain.com
verify return:1
---
Certificate chain
 0 s:CN = *.mydomain.com
   i:C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA
-----BEGIN CERTIFICATE-----
<cert contents>
-----END CERTIFICATE-----
---
Server certificate
subject=CN = *.mydomain.com

issuer=C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 1619 bytes and written 375 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---

What this tests:

  • Verification: OK – certificate is issued by a trusted CA
  • Verify return code: 0 – no verification error occurred

Using this, you can easily confirm if a server is presenting trusted and valid certificates before investigating other connection issues.

4. Checking Certificate Chains

Improperly ordered certificate chains is a common SSL misconfiguration issue.

You can print all certificates in the chain sent by the server using -showcerts:

openssl s_client -showcerts -connect www.mydomain.com:443

The output will include the end-entity certificate first, followed by additional intermediate CA certificates:

---
Certificate chain
 0 s:CN = example.com
   i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Extended Validation Server CA
 1 s:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Extended Validation Server CA
   i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
---
Server certificate
subject=CN=example.com

issuer=C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Extended Validation Server CA
...

Here you can see a properly ordered chain – the intermediate CA matches the issuer of the end-entity certificate.

If these were flipped, it would lead to SSL errors:

Certificate chain
 0 s:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Extended Validation Server CA
 1 s:CN = example.com 
   i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Extended Validation Server CA  

So check for issues in chain ordering whenever you see SSL errors connecting to a site.

5. Testing Protocol Upgrades with STARTTLS

Many application protocols support upgrading plaintext connections to encrypted connections using STARTTLS.

To test STARTTLS with openssl s_client, use the -starttls option.

For example, to connect to an SMTP server:

openssl s_client -connect smtp.myhost.com:25 -starttls smtp

This will:

  1. Connect to the plaintext SMTP port 25
  2. Then negotiate an upgrade to an SSL/TLS encrypted connection after STARTTLS

You can replace smtp with other protocols like pop3, imap, ftp or xmpp depending on the server.

The output will confirm an encrypted connection:

STARTTLS
---
SSL handshake has read 1952 bytes and written 325 bytes
...
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
...

Using this you can test client implementations that need to support STARTTLS capability.

6. Specifying SSL Versions

If you need to explicitly test specific SSL/TLS versions, OpenSSL allows you to force the use of SSLv2, SSLv3, TLSv1, TLSv1.1 or TLSv1.2:

openssl s_client -ssl2 -connect www.myhost.com:443

Or to choose the most recent TLS 1.2:

openssl s_client -tls1_2 -connect www.myhost.com:443  

You can also blacklist protocols using no_ssl2, etc.

Testing with different SSL versions helps check for compatibility issues and determine what protocols your servers accept.

7. Checking Supported Cipher Suites

To see what cipher suites are supported by your SSL server, use the openssl ciphers command:

openssl ciphers -v ‘SSLv3‘

This lists all supported ciphers for the SSLv3 protocol on your OpenSSL client library:

      0xC0,0x11 - ECDHE-RSA-DES-CBC3-SHA
      0xC0,0x07 - ECDHE-RSA-RC4-SHA
      0x00,0x39 - DHE-RSA-AES256-SHA
      0x00,0x38 - DHE-RSA-CAMELLIA256-SHA 
      0x00,0x35 - DHE-RSA-AES128-SHA
      0x00,0x32 - DHE-RSA-SEED-SHA
...

To check what the actual server supports, connect using s_client and look for the New cipher output:

openssl s_client -connect www.myhost.com:443 

New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256

This shows the negotiated ECDHE-RSA-AES128-GCM-SHA256 suite.

Comparing supported cipher suites can identify mismatches if you‘re seeing handshake failures between clients and servers.

8. Testing Certificate Names

To validate that your server is presenting certificates with expected domain names, use:

openssl s_client -servername www.myhost.com -connect myhost.com:443
  • -connect connects to myhost.com
  • -servername specifies the hostname we expect

By default this verifies that the Common Name or a Subject Alternative Name matches www.myhost.com.

If the certificate is missing this hostname, you‘ll see a verification error:

verify error:num=20:unable to get local issuer certificate
verify return:0

So this test confirms you have certificates with the required hostnames.

Conclusion

openssl s_client provides a powerful tool for debugging SSL connectivity issues and testing encrypted client-server connections. It gives you insight into certificate validity, protocol support, and encryption details relevant for hardening application security.

Regularly utilizing these testing techniques will improve your ability to monitor certificates across your environment and catch SSL misconfigurations early. This in turn raises the bar for the overall level of protection you provide to your servers, services and data flows.


Image credits: FreeCodeCamp

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *