The openssl s_client command is a diagnostic tool that establishes a raw SSL/TLS connection to a remote server, letting you inspect the certificate, cipher suite, and protocol details of the handshake. You use it by providing a hostname and port (e.g., openssl s_client -connect example.com:443), and it returns the server’s certificate chain, negotiated protocol, and cipher information. This article explains how the command works, how to read its output, and how to troubleshoot common connection issues.
What is OpenSSL s_client?
OpenSSL is a widely used open-source library that implements the SSL and TLS protocols. The s_client subcommand is a test client that mimics a browser or other client software, but with the ability to show you exactly what happens during the secure handshake. It is not a full-featured client like curl or a web browser; it is a debugging tool that gives you raw visibility into the TLS negotiation.
Typical uses include:
- Checking whether a server is reachable on a given port and speaks TLS.
- Viewing the server’s certificate chain, including expiry dates and issuer.
- Verifying which TLS versions and cipher suites are supported.
- Testing SNI (Server Name Indication) behavior for virtual hosts.
- Debugging handshake failures, such as mismatched ciphers or expired certificates.
Basic Syntax and Options
The most common invocation is:
openssl s_client -connect host:port
For example, to connect to example.com on port 443 (HTTPS):
openssl s_client -connect example.com:443
This opens a connection and prints the certificate and handshake details, then waits for you to type data (which is sent over the encrypted channel). To exit, type Q or press Ctrl+C.
Useful options include:
-servername name– sets the SNI extension, which is required for servers that host multiple certificates on the same IP.-showcerts– displays the full certificate chain, not just the server certificate.-tls1_2or-tls1_3– forces a specific TLS version.-cipher 'SUITE'– restricts the cipher suites offered.-quiet– suppresses most output, showing only the certificate and handshake messages.-brief– outputs a condensed summary of the connection parameters.
Reading the Output
When you run s_client, the output contains several sections. The first is the certificate chain, printed in PEM format. Each certificate block shows the subject and issuer, validity dates, and the public key. The line Verify return code: 0 (ok) indicates that the certificate chain validates against the system trust store. If verification fails, you’ll see a non-zero return code and a description, such as self-signed certificate or certificate has expired.
Next, the handshake details appear, including:
Protocol– the negotiated TLS version (e.g., TLSv1.3).Cipher– the selected cipher suite (e.g., TLS_AES_256_GCM_SHA384).Session-ID– a session identifier for resumption.Master-Key– a secret used to derive session keys (not normally shown unless you request it).
After the handshake, the connection is open and you can send data. For example, to see an HTTP response, you can pipe an HTTP request:
echo -e 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' | openssl s_client -connect example.com:443 -quiet
This sends a simple GET request and prints the HTTP response headers and body.
Common Use Cases and Examples
Checking certificate expiry: Use -showcerts and look at the notAfter date. For a quick check, you can pipe the output to openssl x509 -noout -dates:
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
Testing SNI: If a server hosts multiple sites, you must send the correct hostname via SNI:
openssl s_client -connect 192.0.2.1:443 -servername www.example.com
Forcing a TLS version: To see if a server supports TLS 1.2 only:
openssl s_client -connect example.com:443 -tls1_2
If the handshake fails, the server likely does not support that version.
Common Problems and Troubleshooting
Handshake failure / no cipher overlap: This happens when the client and server cannot agree on a cipher suite or protocol version. Check the server’s supported ciphers with a tool like nmap --script ssl-enum-ciphers or try different TLS versions.
Certificate verification failed: If you see Verify return code: 20 (unable to get local issuer certificate), the server’s certificate chain is incomplete, or the root CA is not in your trust store. You can specify a custom CA bundle with -CAfile or -CApath.
Connection refused or timeout: The server may not be listening on that port, or a firewall is blocking you. Check with telnet host port or nc -vz host port.
Unexpected EOF: The server closed the connection during the handshake. This often indicates a protocol mismatch or that the server requires SNI.
Security Considerations
Using s_client does not verify the server’s identity by default. The output shows the certificate, but it does not check that the hostname matches the certificate or that the chain is trusted. To perform a full verification, use -verify_return_error and -verify_hostname hostname. For example:
openssl s_client -connect example.com:443 -verify_hostname example.com -verify_return_error
This will fail if the certificate is invalid for the hostname. However, for debugging, you often intentionally ignore verification errors to inspect the certificate itself.
Alternatives to s_client
While s_client is powerful, other tools may be more convenient for specific tasks:
curl -vI https://example.com– shows TLS details and HTTP headers, with automatic verification.openssl s_server– the counterpart for testing servers.gnutls-cli– a similar client from the GnuTLS library.nmap --script ssl-cert– scans a server’s TLS configuration without a full handshake.
Frequently Asked Questions
How do I see the full certificate chain?
Add the -showcerts option. The output will include all certificates in the chain, from the server certificate up to the root. Without it, only the server certificate is shown.
Why does s_client hang after connecting?
After the handshake, s_client waits for you to send data. If you don’t type anything, it appears to hang. Press Ctrl+C to exit, or pipe input like echo | openssl s_client ... to send an empty line and close.
How do I check if a server supports TLS 1.3?
Run openssl s_client -connect host:443 -tls1_3. If the handshake succeeds and the output shows Protocol: TLSv1.3, it supports it. If it fails, it likely doesn’t.
What does ‘Verify return code: 19’ mean?
Return code 19 means the certificate chain is self-signed or the root certificate is not in the trust store. It’s a common error when testing internal servers with self-signed certificates.
Can I use s_client to test SMTP, IMAP, or other TLS services?
Yes. For SMTP on port 465 (implicit TLS), use openssl s_client -connect smtp.example.com:465. For STARTTLS on port 587, use -starttls smtp. Similar options exist for imap, pop3, and ftp.