1. Library
  2. Computer Networks
  3. Tools and Commands
  4. Http Testing

Updated 8 hours ago

When an HTTPS connection fails, most tools just say "connection failed." They can't show you why. The encryption is a black box.

openssl s_client opens that box. It establishes an SSL/TLS connection to any server, performs the handshake, shows you every certificate in the chain, tells you what cipher was negotiated—and then hands you the keyboard. You're not observing a connection. You're making one. You become the client, speaking directly to the server, seeing exactly what it sends back.

Basic Usage

Connect to an HTTPS server:

openssl s_client -connect example.com:443

This establishes an SSL/TLS connection to port 443 and displays everything about the negotiation: certificate chain, TLS version, cipher suite, verification status.

What the Output Tells You

A successful connection shows:

CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
verify return:1
depth=0 C = US, ST = California, L = Los Angeles, O = Example, CN = example.com
verify return:1
---
Certificate chain
 0 s:C = US, ST = California, L = Los Angeles, O = Example, CN = example.com
   i:C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
 1 s:C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
   i:C = US, O = DigiCert Inc, CN = DigiCert Global Root CA
---
SSL handshake has read 3847 bytes and written 444 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384

The depth lines show certificate chain validation—depth 0 is the server's certificate, higher numbers are the chain leading to the root CA. verify return:1 means each certificate passed validation.

Speaking Protocols by Hand

Once connected, you can type protocol commands directly. For HTTPS:

openssl s_client -connect example.com:443

Then type:

GET / HTTP/1.1
Host: example.com

(Press Enter twice after the Host line.)

You'll see the raw HTTP response—headers and body—proving the encrypted connection works end-to-end.

Inspecting Certificates

Check expiration dates:

openssl s_client -connect example.com:443 </dev/null 2>/dev/null | openssl x509 -noout -dates
notBefore=Dec 15 00:00:00 2023 GMT
notAfter=Dec 14 23:59:59 2024 GMT

View full certificate details:

openssl s_client -connect example.com:443 </dev/null 2>/dev/null | openssl x509 -noout -text

Shows subject, issuer, validity period, public key, Subject Alternative Names (SANs), extensions, and signature algorithm.

Extract certificate to a file:

openssl s_client -connect example.com:443 </dev/null 2>/dev/null | openssl x509 -outform PEM > cert.pem

Check Subject Alternative Names:

openssl s_client -connect example.com:443 </dev/null 2>/dev/null | openssl x509 -noout -text | grep -A1 "Subject Alternative Name"

Shows all domains covered by the certificate.

Essential Options

-servername (SNI)

Server Name Indication tells the server which certificate to present—critical when multiple sites share an IP:

openssl s_client -servername example.com -connect 93.184.216.34:443

Without this, you might get the wrong certificate or a handshake failure.

-showcerts

Display every certificate in the chain, not just the server's:

openssl s_client -showcerts -connect example.com:443

Essential for debugging "unable to get local issuer certificate" errors.

-starttls

For protocols that upgrade to TLS mid-connection:

# SMTP
openssl s_client -starttls smtp -connect mail.example.com:587

# IMAP
openssl s_client -starttls imap -connect mail.example.com:143

# POP3
openssl s_client -starttls pop3 -connect mail.example.com:110

-tls1_2, -tls1_3

Force a specific TLS version:

# Verify TLS 1.3 support
openssl s_client -tls1_3 -connect example.com:443

# Verify TLS 1.0 is disabled (should fail on secure servers)
openssl s_client -tls1 -connect example.com:443

-cipher

Test if a server supports a specific cipher:

openssl s_client -cipher 'ECDHE-RSA-AES256-GCM-SHA384' -connect example.com:443

Connection succeeds if supported, fails if not.

-CAfile

Use a custom CA certificate for validation:

openssl s_client -CAfile custom-ca.crt -connect internal.example.com:443

-cert and -key

For mutual TLS (client certificate authentication):

openssl s_client -cert client.crt -key client.key -connect example.com:443

-brief and -quiet

# Minimal output
openssl s_client -brief -connect example.com:443

# Suppress handshake info, show only protocol interaction
openssl s_client -quiet -connect example.com:443

Testing Different Protocols

# HTTPS
openssl s_client -connect example.com:443

# SMTPS (implicit TLS)
openssl s_client -connect mail.example.com:465

# SMTP with STARTTLS
openssl s_client -starttls smtp -connect mail.example.com:587

# IMAPS
openssl s_client -connect mail.example.com:993

# POP3S
openssl s_client -connect mail.example.com:995

# LDAPS
openssl s_client -connect ldap.example.com:636

Debugging Common Failures

"unable to get local issuer certificate"

The certificate chain doesn't reach a trusted root. Either the server isn't sending intermediate certificates, or you need to specify a CA file:

openssl s_client -showcerts -connect example.com:443

Check if intermediates are present. If not, the server is misconfigured.

"Hostname mismatch"

The certificate's CN or SANs don't include the hostname you're connecting to. Use -servername to specify the correct hostname for SNI.

"SSL handshake failure"

TLS negotiation failed—usually a cipher or version mismatch. Try forcing a specific version:

openssl s_client -tls1_2 -connect example.com:443

"wrong version number"

You connected with SSL to a plaintext port, or vice versa.

"Cipher is (NONE)"

No mutually supported cipher. The server and client have no cipher suites in common.

Testing Before DNS Changes

Validate a certificate on a new server before cutting over:

openssl s_client -servername example.com -connect 203.0.113.50:443

Connects to the IP directly while presenting the correct hostname for SNI and certificate validation.

Scripting Examples

Alert on expiring certificates:

#!/bin/bash
EXPIRY=$(openssl s_client -connect example.com:443 </dev/null 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))

if [ $DAYS_LEFT -lt 30 ]; then
  echo "WARNING: Certificate expires in $DAYS_LEFT days"
fi

Test TLS version support:

#!/bin/bash
for version in tls1 tls1_1 tls1_2 tls1_3; do
  echo -n "$version: "
  if openssl s_client -$version -connect example.com:443 </dev/null 2>/dev/null | grep -q "Cipher is"; then
    echo "supported"
  else
    echo "not supported"
  fi
done

Security Auditing

Test for weak ciphers:

# 3DES is weak—should fail on secure servers
openssl s_client -cipher 'DES-CBC3-SHA' -connect example.com:443

Check for Certificate Transparency:

openssl s_client -connect example.com:443 </dev/null 2>/dev/null | openssl x509 -noout -text | grep -A5 "CT Precertificate SCTs"

Verify HSTS header:

Connect with openssl s_client, send an HTTP request, and look for:

Strict-Transport-Security: max-age=31536000

Frequently Asked Questions About OpenSSL s_client

Was this page helpful?

😔
🤨
😃