`openssl s_client`: Getting Server Certificate Information

Okay, here is a detailed article on using openssl s_client to retrieve and inspect server certificate information, aiming for approximately 5000 words.


Deep Dive into openssl s_client: Mastering Server Certificate Inspection

In the modern digital landscape, secure communication is paramount. Transport Layer Security (TLS), the successor to Secure Sockets Layer (SSL), is the cryptographic protocol that underpins secure data exchange over networks, most notably the internet (HTTPS). At the heart of TLS lies the X.509 certificate, a digital document that binds a public key to an identity (like a domain name) and is signed by a trusted Certificate Authority (CA). Verifying and understanding the details of a server’s certificate is crucial for ensuring authenticity, confidentiality, and integrity.

While web browsers handle TLS handshakes and certificate validation automatically, system administrators, developers, and security professionals often need a more granular, command-line approach to inspect certificates, troubleshoot connection issues, or verify security configurations. This is where the openssl toolkit, specifically the s_client command, becomes an indispensable tool.

openssl s_client is a versatile utility that acts as a generic SSL/TLS client. It can connect to a remote server, perform a TLS handshake, display detailed information about the connection, the session parameters, and, most importantly for our focus, the server’s certificate(s). This article provides an in-depth exploration of using openssl s_client specifically for retrieving and analyzing server certificate information.

Table of Contents

  1. Introduction to TLS Certificates and the Need for Inspection
    • What is an X.509 Certificate?
    • Why Inspect Server Certificates?
  2. Introducing openssl s_client
    • Purpose and Functionality
    • Prerequisites (Installing OpenSSL)
  3. Basic Connection and Initial Output
    • The Simplest Command: openssl s_client -connect host:port
    • Understanding the Default Output
  4. Essential Options for Certificate Retrieval
    • -connect <host>:<port>: Specifying the Target
    • -servername <name>: The Crucial Role of Server Name Indication (SNI)
    • -showcerts: Retrieving the Entire Certificate Chain
  5. Extracting the Server Certificate (PEM Format)
    • Manual Copy-Paste
    • Programmatic Extraction (using sed or awk)
  6. The Powerhouse: Piping to openssl x509 for Detailed Analysis
    • Basic Parsing: openssl x509 -text -noout
    • Understanding the -noout Option
  7. Dissecting Certificate Fields with openssl x509
    • Core Identity Information:
      • Subject (-subject)
      • Issuer (-issuer)
    • Validity Period:
      • Not Before / Not After (-dates, -startdate, -enddate)
      • Checking Expiry (-checkend <seconds>)
    • Serial Number (-serial)
    • Fingerprints/Thumbprints (-fingerprint [md5|sha1|sha256])
    • Public Key Information (-pubkey)
    • Signature Algorithm
    • X.509 Version
  8. Exploring X.509v3 Extensions
    • Introduction to Extensions
    • Key Usage (-purpose indirectly, detailed in -text)
    • Extended Key Usage (EKU) (-purpose indirectly, detailed in -text)
    • Subject Alternative Names (SANs) – Critical
    • Basic Constraints (Is it a CA?)
    • Authority Key Identifier (AKI)
    • Subject Key Identifier (SKI)
    • Certificate Policies (CP)
    • Authority Information Access (AIA) – OCSP and CA Issuers
    • CRL Distribution Points (CDP)
    • Certificate Transparency (Embedded SCTs)
  9. Working with the Certificate Chain
    • Using -showcerts with openssl x509
    • Understanding Chain Order and Trust Anchors
    • Specifying Trust Stores: -CAfile and -CApath
  10. Verification Process and Debugging
    • How s_client Performs Verification
    • Forcing Verification: -verify <depth>, -verify_return_error
    • Hostname Verification: -verify_hostname <name>
    • Common Verification Errors and Their Meanings
  11. Controlling Protocol Versions and Cipher Suites
    • Specifying TLS/SSL Versions (-tls1_3, -tls1_2, -no_tls1_3, etc.)
    • Specifying Cipher Suites (-cipher, -ciphersuites)
    • Relevance to Certificate Validation (e.g., Signature Algorithms)
  12. Handling Non-HTTPS Protocols (STARTTLS)
    • Using -starttls <protocol>
    • Examples: SMTP, POP3, IMAP, FTP
  13. Advanced Techniques and Scripting
    • Extracting Specific Fields Programmatically (e.g., SANs, Expiry Date)
    • Automated Certificate Monitoring Scripts
    • Combining s_client with other tools (grep, awk, jq)
  14. Common Pitfalls and Troubleshooting
    • Forgetting -servername (SNI Issues)
    • Firewall Restrictions
    • Missing Intermediate Certificates
    • Incorrect Trust Store Configuration
    • Protocol/Cipher Mismatches
  15. Alternatives to openssl s_client
    • Web Browsers (Developer Tools)
    • curl -v
    • nmap (NSE Scripts)
    • Online SSL Checkers
    • Other Language Libraries (Python ssl, Go crypto/tls)
  16. Conclusion

1. Introduction to TLS Certificates and the Need for Inspection

What is an X.509 Certificate?

At its core, an X.509 certificate is a standardized digital identity document. Think of it like a digital passport for a server (or sometimes a client, user, or device). It contains crucial information:

  • Subject: Who or what the certificate identifies (e.g., www.example.com).
  • Public Key: The public part of a cryptographic key pair belonging to the subject. The corresponding private key is kept secret by the subject.
  • Issuer: The entity (usually a Certificate Authority like Let’s Encrypt, DigiCert, GlobalSign) that verified the subject’s identity and signed the certificate.
  • Validity Period: The dates between which the certificate is considered valid.
  • Serial Number: A unique identifier assigned by the issuer.
  • Signature: A digital signature created by the issuer using their private key. This signature proves the certificate’s authenticity and integrity – it confirms that the issuer vouches for the information and that the certificate hasn’t been tampered with.
  • Extensions: Additional fields providing more context, usage constraints, or pointers (like Subject Alternative Names, Key Usage, etc.).

These certificates form the basis of trust in the TLS ecosystem. When your browser connects to https://www.example.com, the server presents its certificate. Your browser checks:

  1. Is the certificate’s signature valid and generated by a trusted CA?
  2. Is the certificate within its validity period?
  3. Does the name in the certificate (Subject or SAN) match the domain you’re connecting to?
  4. Has the certificate been revoked? (Often checked via OCSP or CRLs).

Why Inspect Server Certificates?

While browsers automate this, manual inspection using tools like openssl s_client is vital for various reasons:

  • Troubleshooting Connection Errors: Diagnosing why a TLS connection fails (e.g., expired certificate, name mismatch, untrusted issuer, weak cipher).
  • Security Auditing: Verifying that servers are using strong cryptographic parameters, correct key usage, and valid certificates from approved CAs.
  • Deployment Verification: Ensuring a newly deployed or renewed certificate is correctly installed and served, including any necessary intermediate certificates.
  • Understanding Certificate Chains: Visualizing the chain of trust from the end-entity certificate up to the root CA.
  • Checking Specific Details: Extracting information not easily visible in a browser, like specific extensions (Certificate Policies, AIA/CDP URLs), signature algorithms, or public key details.
  • Automation and Monitoring: Scripting checks for certificate expiry, configuration compliance, or changes.
  • Learning and Education: Gaining a deeper understanding of TLS handshakes and certificate structure.

2. Introducing openssl s_client

Purpose and Functionality

openssl s_client is part of the OpenSSL suite, a robust, commercial-grade, and full-featured toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols. It also serves as a general-purpose cryptography library.

The s_client command implements a generic SSL/TLS client which connects to a remote host using SSL/TLS. It’s primarily designed for testing and debugging TLS servers. It allows you to:

  • Establish a connection to a specified host and port.
  • Negotiate a TLS session (specify protocols, ciphers).
  • Display session parameters (protocol version, cipher suite, session ID).
  • Show the server’s certificate(s).
  • Perform basic certificate verification.
  • Send data to the server and receive data from it after the handshake (acting like a simple telnet over TLS).

Its ability to dump the raw certificate information and handshake details makes it invaluable for certificate inspection.

Prerequisites (Installing OpenSSL)

OpenSSL is pre-installed on most Linux distributions and macOS. You can verify its installation and version by opening a terminal and running:

bash
openssl version

If it’s not installed, you can typically install it using your system’s package manager:

  • Debian/Ubuntu: sudo apt update && sudo apt install openssl
  • Fedora/CentOS/RHEL: sudo dnf install openssl or sudo yum install openssl
  • macOS (using Homebrew): brew install openssl (Note: macOS has a built-in LibreSSL, but the Homebrew version is often preferred for newer features. You might need to adjust your PATH or use the full path /usr/local/opt/openssl/bin/openssl.)
  • Windows: You can download pre-compiled binaries from various sources (e.g., Shining Light Productions) or use environments like Cygwin, MinGW, or the Windows Subsystem for Linux (WSL).

Ensure you have a reasonably recent version of OpenSSL (1.1.1 or later is recommended for modern TLS features like TLS 1.3).

3. Basic Connection and Initial Output

The Simplest Command: openssl s_client -connect host:port

The most basic usage involves specifying the target server and port using the -connect option. The default port for HTTPS is 443.

bash
openssl s_client -connect www.example.com:443

When you run this command, s_client performs the following actions:

  1. Resolves the hostname (www.example.com) to an IP address.
  2. Establishes a TCP connection to that IP address on the specified port (443).
  3. Initiates a TLS handshake (ClientHello).
  4. Receives the server’s response (ServerHello, Certificate, ServerKeyExchange, ServerHelloDone, etc.).
  5. Performs basic validation (based on its default trust store).
  6. Completes the handshake.
  7. Prints a wealth of information to the standard output.
  8. Waits for input from you (stdin) to send to the server, and prints any data received from the server (stdout). You typically press Ctrl+C or Ctrl+D (or type Q then Enter on some systems after -quiet) to close the connection.

Understanding the Default Output

The output can be verbose, but key sections related to the certificate include:

“`
CONNECTED(00000…)
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let’s Encrypt, CN = R3
verify return:1
depth=0 CN = www.example.com
verify return:1


Certificate chain
0 s:/CN=www.example.com <– End-entity certificate subject
i:/C=US/O=Let’s Encrypt/CN=R3 <– End-entity certificate issuer
a:PKEY: id-ecPublicKey, 256 (bit); sigalg: RSA-SHA256
v:NotBefore: May 15 10:00:00 2024 GMT; NotAfter: Aug 13 10:00:00 2024 GMT
1 s:/C=US/O=Let’s Encrypt/CN=R3 <– Intermediate certificate subject
i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1 <– Intermediate issuer
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Sep 4 00:00:00 2020 GMT; NotAfter: Sep 15 16:00:00 2025 GMT


Server certificate
—–BEGIN CERTIFICATE—–
MIIF… (lots of Base64 encoded data) …A==
—–END CERTIFICATE—–
subject=CN = www.example.com

issuer=C = US, O = Let’s Encrypt, CN = R3


No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: ECDSA
Server Temp Key: X25519, 253 bits


SSL handshake has read 2900 bytes and written 420 bytes
Verification: OK <– Verification result based on default trust store


New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)


(Connection remains open, waiting for input…)
“`

Key parts of this output:

  • CONNECTED: Indicates a successful TCP connection.
  • depth=... verify return:1: Shows the certificate chain verification process. depth=0 is the server’s certificate, depth=1 is the intermediate, and so on. verify return:1 means verification succeeded at that level.
  • Certificate chain: A summary of the Subject (s:), Issuer (i:), Public Key (a:), and Validity (v:) for each certificate in the chain presented by the server.
  • Server certificate: The actual server certificate (depth 0) in PEM (Privacy-Enhanced Mail) format. This is the Base64 encoded representation of the DER (Distinguished Encoding Rules) formatted certificate, enclosed by -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines.
  • subject= / issuer=: A repetition of the subject and issuer of the end-entity certificate.
  • Verification: OK / Verify return code: 0 (ok): The overall result of the certificate verification against OpenSSL’s default trust store. If it failed, you’d see an error message and a non-zero code here (e.g., Verify return code: 21 (unable to verify the first certificate)).
  • Session Parameters: Information about the negotiated TLS version (TLSv1.3), cipher suite (TLS_AES_256_GCM_SHA384), temporary key exchange parameters, etc.

This basic command already gives us the server’s main certificate in PEM format and a summary of the chain.

4. Essential Options for Certificate Retrieval

While the basic command is useful, several options are often necessary for accurate and complete certificate retrieval.

-connect <host>:<port>: Specifying the Target

This is fundamental. Always specify both the hostname/IP address and the port number. Common ports:
* 443: HTTPS (default)
* 993: IMAPS (IMAP over SSL/TLS)
* 995: POP3S (POP3 over SSL/TLS)
* 465: SMTPS (SMTP over SSL/TLS – historically used, often STARTTLS on 587 is preferred now)
* 636: LDAPS (LDAP over SSL/TLS)
* 3389: RDP (sometimes with TLS)

Example: openssl s_client -connect mail.example.com:993

-servername <name>: The Crucial Role of Server Name Indication (SNI)

This is one of the most critical options in modern web environments. Many web servers host multiple websites (virtual hosts) on a single IP address. During the TLS handshake, the server needs to know which website’s certificate the client is requesting before the encrypted HTTP request is sent.

Server Name Indication (SNI) is a TLS extension where the client includes the requested hostname in the initial ClientHello message. This allows the server to select and present the correct certificate.

Without -servername, openssl s_client does not send the SNI extension. If the server relies on SNI (which most do), it might:

  1. Return a default certificate (often for the server’s main hostname or a generic one).
  2. Return no certificate and abort the handshake.
  3. Return an incorrect certificate.

Always use -servername matching the hostname you put in -connect when dealing with HTTPS or any SNI-aware protocol:

“`bash

CORRECT: Uses SNI

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

INCORRECT/RISKY: Connects to the IP but requests cert for www.example.com

(Assumes 192.0.2.1 is the IP for www.example.com)

openssl s_client -connect 192.0.2.1:443 -servername www.example.com

INCORRECT/RISKY: Connects to www.example.com but sends no SNI

openssl s_client -connect www.example.com:443
“`

Failure to use -servername is a very common reason for getting unexpected certificate results or verification failures.

-showcerts: Retrieving the Entire Certificate Chain

By default, openssl s_client only prints the end-entity (server) certificate in the main PEM block output. However, servers usually send a chain of certificates:

  1. End-entity certificate: Identifies the server itself.
  2. Intermediate certificate(s): Issued by the CA that signed the end-entity cert, and possibly signed by another intermediate or a root CA.
  3. (Optional) Root certificate: Sometimes servers send the root, though clients usually rely on their local trust store for roots.

The client needs the intermediate certificates to build a valid chain of trust from the end-entity certificate up to a root certificate present in its trust store.

The -showcerts option tells s_client to print all certificates sent by the server during the handshake, each in its own PEM block.

bash
openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts

The output will now contain multiple -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- blocks, typically starting with the end-entity certificate and followed by the intermediate(s) in order.

“`
CONNECTED(00000…)
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let’s Encrypt, CN = R3
verify return:1
depth=0 CN = www.example.com
verify return:1


Certificate chain
0 s:/CN=www.example.com
i:/C=US/O=Let’s Encrypt/CN=R3
a:PKEY: id-ecPublicKey, 256 (bit); sigalg: RSA-SHA256
v:NotBefore: May 15 10:00:00 2024 GMT; NotAfter: Aug 13 10:00:00 2024 GMT
1 s:/C=US/O=Let’s Encrypt/CN=R3
i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Sep 4 00:00:00 2020 GMT; NotAfter: Sep 15 16:00:00 2025 GMT


Server certificate
—–BEGIN CERTIFICATE—–
MIIF… (End-entity cert PEM data) …A==
—–END CERTIFICATE—–
subject=CN = www.example.com
issuer=C = US, O = Let’s Encrypt, CN = R3


—–BEGIN CERTIFICATE—–
MIIE… (Intermediate cert PEM data) …G==
—–END CERTIFICATE—– <– Added by -showcerts


No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: ECDSA
Server Temp Key: X25519, 253 bits


SSL handshake has read 2900 bytes and written 420 bytes
Verification: OK


New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)


DONE <– Connection closes automatically often with -showcerts
“`

Notice the second -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- block. This is crucial for analyzing the full chain provided by the server. Note also that using -showcerts often causes s_client to close the connection immediately after the handshake (DONE) instead of waiting for input.

5. Extracting the Server Certificate (PEM Format)

We often need the certificate data itself, separate from the rest of the s_client output, perhaps to save it to a file or pass it to another tool.

Manual Copy-Paste

The simplest method is to manually copy the text starting from -----BEGIN CERTIFICATE----- up to and including -----END CERTIFICATE----- from the terminal output and paste it into a text file (e.g., server.pem). If using -showcerts, you can copy each certificate block.

Programmatic Extraction (using sed or awk)

For scripting or automation, command-line tools like sed or awk are invaluable.

To extract only the first (end-entity) certificate:

Using sed:

“`bash
openssl s_client -connect www.example.com:443 -servername www.example.com \
</dev/null | \
sed -n ‘/—–BEGIN CERTIFICATE—–/,/—–END CERTIFICATE—–/p; /—–END CERTIFICATE—–/q’ \

server.pem
“`

  • </dev/null: Prevents s_client from waiting for stdin input, making it exit cleanly after the handshake. You might also use echo "Q" on some systems.
  • sed -n '...': -n suppresses default printing.
  • /-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p: Prints lines between (and including) the BEGIN and END markers.
  • /-----END CERTIFICATE-----/q: Quits sed immediately after printing the first complete certificate block.
  • > server.pem: Redirects the output to a file.

Using awk:

“`bash
openssl s_client -connect www.example.com:443 -servername www.example.com \
</dev/null | \
awk ‘/—–BEGIN CERTIFICATE—–/ {flag=1} flag; /—–END CERTIFICATE—–/ {exit}’ \

server.pem
“`

  • Sets flag=1 when BEGIN marker is found.
  • Prints the line if flag is set (flag evaluates to true).
  • Exits awk when END marker is found.

To extract all certificates (when using -showcerts):

Using sed:

“`bash
openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts \
</dev/null | \
sed -n ‘/—–BEGIN CERTIFICATE—–/,/—–END CERTIFICATE—–/p’ \

chain.pem
“`

  • This simply prints all occurrences of blocks between the markers.

Using awk:

“`bash
openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts \
</dev/null | \
awk ‘/—–BEGIN CERTIFICATE—–/ {flag=1} flag; /—–END CERTIFICATE—–/ {flag=0}’ \

chain.pem
“`

  • Sets flag=1 on BEGIN marker, prints if flag is 1, sets flag=0 on END marker. This correctly handles multiple blocks.

Now that we can reliably extract the PEM-encoded certificate(s), we can move on to detailed parsing.

6. The Powerhouse: Piping to openssl x509 for Detailed Analysis

While s_client shows some certificate details, its primary job is establishing the connection. For in-depth certificate analysis, we use another OpenSSL command: openssl x509. This command is designed specifically for parsing and displaying X.509 certificate information.

We can directly pipe the PEM output from s_client (extracted as shown above, or even the raw s_client output if we’re careful) into openssl x509.

Basic Parsing: openssl x509 -text -noout

The most common way to view all details of a certificate in a human-readable format is using the -text option.

“`bash

Extract the first cert and pipe it to openssl x509

openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null | \
sed -n ‘/—–BEGIN CERTIFICATE—–/,/—–END CERTIFICATE—–/p; /—–END CERTIFICATE—–/q’ | \
openssl x509 -text -noout
“`

Alternatively, if you just want to quickly inspect the first certificate without saving it, you can often pipe directly, relying on openssl x509 to find the first PEM block (though using extraction is more robust):

“`bash

Less robust, but often works for quick inspection of the first cert

openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null | \
openssl x509 -text -noout
“`

The output of openssl x509 -text -noout is extensive and includes:

  • Certificate Data (Version, Serial Number, Signature Algorithm, Issuer, Validity, Subject, Public Key Info)
  • X.509v3 Extensions (Basic Constraints, Key Usage, EKU, SANs, AIA, CDP, etc.)
  • Signature

Example Snippet:
“`
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
04:09:51:69:be:91:17:a4:f7:86:47:58:47:42:86:66:12:1d
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = US, O = Let’s Encrypt, CN = R3
Validity
Not Before: May 15 10:00:00 2024 GMT
Not After : Aug 13 10:00:00 2024 GMT
Subject: CN = www.example.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:…
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36
X509v3 Authority Key Identifier:
keyid:1A:B7:4B:99:7F:46:16:A9:5A:8F:B9:28:2A:20:9B:01:71:F7:44:0A

        Authority Information Access:
            OCSP - URI:http://r3.o.lencr.org
            CA Issuers - URI:http://r3.i.lencr.org/

        X509v3 Subject Alternative Name:
            DNS:example.com, DNS:www.example.com
        X509v3 Certificate Policies:
            Policy: 2.23.140.1.2.1
            Policy: 1.3.6.1.4.1.44947.1.1.1
              CPS: http://cps.letsencrypt.org
        ct_precert_scts: ... (Certificate Transparency info)
Signature Algorithm: sha256WithRSAEncryption
     30:82:... (Signature value)

“`

Understanding the -noout Option

By default, openssl x509 reads a certificate (e.g., from stdin or a file specified with -in) and prints the PEM-encoded version to stdout. The -noout option prevents this default printing, ensuring that only the information requested by other options (like -text, -subject, -dates, etc.) is displayed. It’s almost always used when you want specific details rather than the certificate itself.

7. Dissecting Certificate Fields with openssl x509

Instead of dumping everything with -text, openssl x509 allows extracting specific fields. This is extremely useful for scripting and focused checks. Remember to always use -noout with these options.

(Pipe the certificate PEM data into each command as shown before, e.g., ... | openssl x509 -noout -<option>)

Core Identity Information

  • Subject (-subject): Displays the Subject Distinguished Name (DN).
    bash
    openssl x509 -noout -subject
    # Output: subject=CN = www.example.com

    The DN contains components like CN (Common Name), O (Organization), OU (Organizational Unit), L (Locality), ST (State/Province), C (Country). Note: While CN was historically used for hostname matching, the Subject Alternative Name (SAN) extension is the standard now.

  • Issuer (-issuer): Displays the Issuer Distinguished Name.
    bash
    openssl x509 -noout -issuer
    # Output: issuer=C = US, O = Let's Encrypt, CN = R3

  • Subject Hash (-subject_hash, -subject_hash_old): Prints a hashed version of the subject name, used by OpenSSL for quickly finding certificates in a directory (-CApath). -subject_hash uses the newer hash algorithm, -subject_hash_old uses the older MD5-based one.
    bash
    openssl x509 -noout -subject_hash
    # Output: e5c3a700

  • Issuer Hash (-issuer_hash, -issuer_hash_old): Prints a hashed version of the issuer name.
    bash
    openssl x509 -noout -issuer_hash
    # Output: b760f1a7

Validity Period

  • Dates (-dates): Shows both the “Not Before” and “Not After” dates.
    bash
    openssl x509 -noout -dates
    # Output:
    # notBefore=May 15 10:00:00 2024 GMT
    # notAfter=Aug 13 10:00:00 2024 GMT

  • Start Date (-startdate): Shows only the “Not Before” date.
    bash
    openssl x509 -noout -startdate
    # Output: notBefore=May 15 10:00:00 2024 GMT

  • End Date (-enddate): Shows only the “Not After” date. Crucial for expiry checks.
    bash
    openssl x509 -noout -enddate
    # Output: notAfter=Aug 13 10:00:00 2024 GMT

  • Checking Expiry (-checkend <seconds>): Checks if the certificate will expire within the specified number of seconds from now. It returns 0 (success in shell terms) if it will not expire, and 1 (failure) if it will expire. It also prints a message.
    “`bash
    # Check if expires within 30 days (30 * 24 * 60 * 60 = 2592000 seconds)
    openssl x509 -noout -checkend 2592000
    # Output (if not expiring soon): Certificate will not expire
    # Output (if expiring soon): Certificate will expire

    Example usage in a script:

    if openssl x509 -noout -checkend 2592000 < server.pem; then
    echo “Certificate is valid for at least 30 days.”
    else
    echo “WARNING: Certificate expires within 30 days!”
    fi
    “`
    Note the slightly counter-intuitive exit codes (0 means not expiring).

Serial Number

  • Serial Number (-serial): Displays the certificate’s serial number, typically as a hexadecimal string. Unique per issuing CA.
    bash
    openssl x509 -noout -serial
    # Output: serial=04095169BE9117A4F786475847428666121D

Fingerprints/Thumbprints

  • Fingerprint (-fingerprint [md5|sha1|sha256]): Calculates and displays a hash (fingerprint) of the entire DER-encoded certificate. Useful for uniquely identifying a certificate. SHA-256 is recommended; MD5 and SHA-1 are weak and should only be used for legacy compatibility. If no algorithm is specified, SHA-1 is often the default (depending on OpenSSL version).
    “`bash
    openssl x509 -noout -fingerprint sha256
    # Output: SHA256 Fingerprint=A1:B2:…:Y9:Z0

    openssl x509 -noout -fingerprint sha1

    Output: SHA1 Fingerprint=C3:D4:…:W7:X8

    openssl x509 -noout -fingerprint md5

    Output: MD5 Fingerprint=E5:F6:…:U5:V6

    “`

Public Key Information

  • Public Key (-pubkey): Displays the public key embedded within the certificate in PEM format.
    bash
    openssl x509 -noout -pubkey
    # Output:
    # -----BEGIN PUBLIC KEY-----
    # MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVs...
    # -----END PUBLIC KEY-----

    This can be piped further, e.g., to openssl pkey -pubin -text -noout for more details about the key itself (like key size, parameters).

    “`bash
    openssl x509 -noout -pubkey | openssl pkey -pubin -text -noout

    Output (example for EC key):

    EC Public-Key: (256 bit)

    pub:

    04:…

    ASN1 OID: prime256v1

    NIST CURVE: P-256

    Output (example for RSA key):

    RSA Public-Key: (2048 bit)

    Modulus:

    00:b?…

    Exponent: 65537 (0x10001)

    “`

Signature Algorithm

While -text shows this, there isn’t a direct dedicated flag just for the signature algorithm of the certificate itself (the one used by the issuer to sign this certificate). However, you can often grep it from the -text output. The algorithm used for the subject’s public key is shown by piping -pubkey to openssl pkey -pubin -text -noout.

X.509 Version

Displayed in the -text output (e.g., Version: 3 (0x2)). Version 3 is standard and allows for extensions.

8. Exploring X.509v3 Extensions

X.509v3 extensions are the most interesting part of modern certificates, providing critical metadata and constraints. The openssl x509 -text command displays these clearly. While there aren’t direct flags for every extension, -purpose provides some insight, and -text gives the full details.

Introduction to Extensions

Extensions add flexibility and specificity to certificates. They can be marked as critical or non-critical. If a client doesn’t understand a critical extension, it must reject the certificate. If it doesn’t understand a non-critical extension, it can safely ignore it.

Key Usage (-purpose indirectly, detailed in -text)

The Key Usage extension defines the cryptographic operations the certificate’s public key is intended for. It’s a bitmask. Common uses:

  • Digital Signature: Verifying signatures (but not for certificates or CRLs).
  • Non Repudiation / Content Commitment: Similar to Digital Signature but potentially with higher assurance (less common now).
  • Key Encipherment: Encrypting symmetric keys (e.g., during RSA key exchange in older TLS versions).
  • Data Encipherment: Encrypting data directly (rarely used for TLS).
  • Key Agreement: Used with key agreement protocols like Diffie-Hellman (e.g., ECDH). Essential for modern TLS forward secrecy.
  • Certificate Sign: Signing other certificates (only for CA certificates).
  • CRL Sign: Signing Certificate Revocation Lists.
  • Encipher Only: Only when Key Agreement is also set.
  • Decipher Only: Only when Key Agreement is also set.

openssl x509 -text displays the enabled usages:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment

The -purpose option checks if the certificate’s extensions are consistent with a specific intended use, but it doesn’t just list the Key Usage bits.

Extended Key Usage (EKU) (-purpose indirectly, detailed in -text)

EKU refines the intended application of the certificate, often identified by Object Identifiers (OIDs). Common EKUs:

  • TLS Web Server Authentication (id-kp-serverAuth): The certificate can be used to authenticate a TLS server. Essential for HTTPS.
  • TLS Web Client Authentication (id-kp-clientAuth): The certificate can be used to authenticate a TLS client (mutual TLS).
  • Code Signing (id-kp-codeSigning): For signing executable code.
  • Email Protection (id-kp-emailProtection): For securing email (S/MIME).
  • Time Stamping (id-kp-timeStamping): For trusted timestamping.
  • OCSP Signing (id-kp-OCSPSigning): For signing OCSP responses.

openssl x509 -text displays these:
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication

The openssl x509 -purpose <purpose> option specifically checks if the required Key Usage and EKU bits/OIDs are present for a given purpose (e.g., -purpose sslserver, -purpose sslclient, -purpose email).

“`bash
openssl x509 -noout -purpose sslserver < server.pem

Output (if OK): Certificate purposes: … SSL server : Yes …

Output (if not): Certificate purposes: … SSL server : No

“`

Subject Alternative Names (SANs) – Critical

This is the standard way to specify the identities (domain names, IP addresses, etc.) that the certificate covers. Browsers and clients must check the SAN extension for matching; the Subject Common Name (CN) is considered legacy and often ignored if SAN is present.

A certificate can have multiple SAN entries of different types:

  • DNS: Domain names (e.g., www.example.com, example.com, *.example.net)
  • IP Address: IPv4 or IPv6 addresses (e.g., 192.0.2.1, 2001:db8::1)
  • email: Email addresses
  • URI: Uniform Resource Identifiers
  • DirName: Distinguished Names
  • otherName: Custom types

openssl x509 -text shows all SANs:
X509v3 Subject Alternative Name:
DNS:www.example.com, DNS:example.com, DNS:mail.example.com

There isn’t a direct flag like -sants, but you can extract them from the -text output using tools like grep and awk or sed:

“`bash

Extract DNS SANs

openssl x509 -noout -text < server.pem | \
awk ‘/X509v3 Subject Alternative Name:/ {getline; gsub(/ /,””); print}’ | \
sed ‘s/DNS://g’ | tr ‘,’ ‘\n’

Output:

www.example.com

example.com

mail.example.com

“`

Basic Constraints (Is it a CA?)

Indicates whether the certificate subject can act as a Certificate Authority and sign other certificates.

  • CA:TRUE: This is a CA certificate.
  • CA:FALSE: This is an end-entity certificate (cannot sign other certs).

It can also include a pathlen constraint, limiting the depth of the CA hierarchy below it if CA:TRUE.

openssl x509 -text shows this:
X509v3 Basic Constraints: critical
CA:FALSE

Or for a CA cert:
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0 # A CA that can only issue end-entity certs

Authority Key Identifier (AKI)

Helps identify the specific key used by the issuer (CA) to sign this certificate. It usually contains the Key Identifier (hash) of the issuer’s public key, and sometimes the issuer’s serial number and DN. This helps in chain building, especially if a CA has multiple signing keys.

openssl x509 -text:
X509v3 Authority Key Identifier:
keyid:1A:B7:4B:99:7F:46:16:A9:5A:8F:B9:28:2A:20:9B:01:71:F7:44:0A

Subject Key Identifier (SKI)

Provides a unique identifier (usually a hash) for the subject’s public key contained within this certificate. The AKI of a certificate being issued should match the SKI of the issuing certificate.

openssl x509 -text:
X509v3 Subject Key Identifier:
A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36

Certificate Policies (CP)

References policy documents that describe the practices and procedures used by the CA in issuing and managing the certificate. Identified by OIDs. Sometimes includes pointers (CPS URIs) to human-readable policy statements.

openssl x509 -text:
X509v3 Certificate Policies:
Policy: 2.23.140.1.2.1 # OID for Let's Encrypt DV certs
Policy: 1.3.6.1.4.1.44947.1.1.1 # Let's Encrypt specific OID
CPS: http://cps.letsencrypt.org

Authority Information Access (AIA) – OCSP and CA Issuers

Provides information about how to access services related to the certificate’s issuer. Crucial for modern certificate validation. Contains two primary types of pointers:

  • OCSP URI: The URL of the Online Certificate Status Protocol responder for checking the revocation status of this certificate.
  • CA Issuers URI: The URL where the issuer’s certificate can be downloaded. This helps clients build the certificate chain if they don’t have the intermediate certificate locally.

openssl x509 -text:
Authority Information Access:
OCSP - URI:http://r3.o.lencr.org
CA Issuers - URI:http://r3.i.lencr.org/

Clients use the OCSP URI to check if the certificate has been revoked before its expiry date. They use the CA Issuers URI to fetch the intermediate certificate needed to link the server cert to a trusted root.

CRL Distribution Points (CDP)

Provides URLs where Certificate Revocation Lists (CRLs) can be downloaded. CRLs are lists of serial numbers of certificates that have been revoked by the issuer. While OCSP is often preferred for its real-time nature, CRLs are still used.

openssl x509 -text:
“`
X509v3 CRL Distribution Points:

        Full Name:
          URI:http://r3.crl.lencr.org

“`

Certificate Transparency (Embedded SCTs)

To combat CA mis-issuance, Certificate Transparency (CT) requires publicly logging issued certificates. Servers prove inclusion in these logs by providing Signed Certificate Timestamps (SCTs) to clients during the TLS handshake. SCTs can be embedded in the certificate itself (as an X.509 extension), delivered via a TLS extension, or provided in an OCSP response.

openssl x509 -text will display embedded SCTs if present:
SCT List:
SCT #1:
Version : v1 (0x0)
Log ID : ...
Timestamp : May 15 10:00:00 2024 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:...
SCT #2:
...

9. Working with the Certificate Chain

Understanding the full chain is often necessary, especially when troubleshooting “incomplete chain” or “untrusted issuer” errors.

Using -showcerts with openssl x509

When you use openssl s_client -showcerts, the output contains multiple PEM blocks. Piping this directly to openssl x509 -text -noout will only process the first certificate.

To analyze all certificates in the chain, you can:

  1. Save the chain to a file:
    bash
    openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts </dev/null > chain.pem

  2. View the file: It will contain multiple cert blocks.

  3. Process each certificate individually: You would need to split the chain.pem file or use a script to iterate through it. A simpler way for quick inspection is often to use a text editor or less chain.pem.

  4. Use crl2pkcs7 (less common for inspection): A trick sometimes used is to convert the PEM sequence into a PKCS#7 container and print the certs from there, which might apply openssl x509 to each, but it’s clunky for manual analysis:
    bash
    # This might print details for all certs, depending on OpenSSL version/flags
    openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts </dev/null | \
    openssl crl2pkcs7 -nocrl | openssl pkcs7 -print_certs -text -noout

    Often, just saving to chain.pem and inspecting manually or with focused openssl x509 commands on extracted individual certs is more practical.

Understanding Chain Order and Trust Anchors

  • Order: The server should send the chain in the correct order: end-entity first, followed by the intermediate that signed it, then the next intermediate, up towards (but not necessarily including) the root CA. s_client -showcerts prints them in the order received.
  • Trust Anchors: The client validates the chain by checking signatures step-by-step:
    • Verify the end-entity certificate’s signature using the intermediate’s public key.
    • Verify the intermediate’s signature using the next certificate’s public key.
    • Repeat until it reaches a certificate that is present in the client’s trust store (a collection of trusted root CA certificates). This is the “trust anchor”.
  • Common Issue: If the server fails to send the necessary intermediate certificate(s), the client cannot link the end-entity certificate to a trusted root, resulting in a verification error (e.g., “unable to get local issuer certificate”). -showcerts helps diagnose if the intermediate is missing from what the server sent.

Specifying Trust Stores: -CAfile and -CApath

By default, openssl s_client uses the OpenSSL default trust store, usually located at /etc/ssl/certs/ca-certificates.crt or in /etc/ssl/certs/. You can override this:

  • -CAfile <filename>: Specify a file containing one or more trusted CA certificates in PEM format, concatenated together.
  • -CApath <directory>: Specify a directory containing trusted CA certificates in PEM format. The directory must be prepared using the openssl rehash or c_rehash utility, which creates symbolic links named by the subject hash (e.g., b760f1a7.0).

This is useful for:
* Testing against a custom or private CA.
* Debugging verification issues by providing a specific set of roots/intermediates.
* Simulating a client with a different trust store.

“`bash

Verify using a specific CA bundle file

openssl s_client -connect internal.example.com:443 -servername internal.example.com -CAfile /path/to/custom_ca_bundle.pem

Verify using a directory of CAs

openssl rehash /path/to/custom_ca_dir/ # Prepare the directory first
openssl s_client -connect internal.example.com:443 -servername internal.example.com -CApath /path/to/custom_ca_dir/
“`

10. Verification Process and Debugging

s_client performs verification automatically using its configured trust store. The results are shown in the Verify return code: and the per-depth verify return: lines.

How s_client Performs Verification

It attempts to build a chain from the server’s certificate up to a trusted CA using the certificates sent by the server (-showcerts) and the certificates in its trust store (-CAfile, -CApath, or default). It checks:
* Signatures at each step.
* Validity periods (not expired, already valid).
* Basic Constraints (intermediate certs must have CA:TRUE).
* Key Usage (e.g., the issuing cert must have Certificate Sign key usage).
* Name constraints (if applicable).
* Hostname match (see below).
* Revocation status (basic check, not full OCSP/CRL by default).

Forcing Verification: -verify <depth>, -verify_return_error

  • -verify <depth>: Explicitly turns on verification up to a specified chain depth. Not usually needed as verification is on by default, but can set the maximum chain length to check.
  • -verify_return_error: Causes s_client to exit immediately with a non-zero exit code if verification fails. Useful in scripts. Without this, s_client prints the error but might continue the connection.

bash
if openssl s_client -connect untrusted.example.com:443 -servername untrusted.example.com -verify_return_error </dev/null &>/dev/null; then
echo "Verification successful."
else
echo "Verification FAILED."
fi

(&>/dev/null suppresses normal output and errors from showing on the console).

Hostname Verification: -verify_hostname <name>

Standard certificate validation includes checking if one of the SAN DNS names or the CN matches the hostname the client intended to connect to. s_client does not perform this check by default.

  • -verify_hostname <name>: Enables hostname verification against the specified <name>. This should usually match the -servername value. Requires OpenSSL 1.0.2 or later.

“`bash

Perform full verification including hostname check

openssl s_client -connect www.example.com:443 \
-servername www.example.com \
-verify_hostname www.example.com \
</dev/null
“`
If the hostname doesn’t match any SAN or the CN, you’ll get a verification error.

Common Verification Errors and Their Meanings

The Verify return code: gives a number (and s_client often prints a text description). Common codes seen in the output or via openssl verify:

  • 0: ok: Verification successful.
  • 2: unable to get issuer certificate: Could not find the certificate that issued the current one. Often means the server didn’t send the necessary intermediate, or the intermediate isn’t trusted.
  • 10: certificate has expired: The Not After date is in the past.
  • 9: certificate is not yet valid: The Not Before date is in the future.
  • 18: self signed certificate: The certificate’s issuer matches its subject, and it’s not in the trust store.
  • 19: self signed certificate in certificate chain: An intermediate or root certificate in the chain is self-signed but not trusted.
  • 20: unable to get local issuer certificate: Similar to code 2, specifically means the chain could be built, but the final issuer (root or intermediate acting as root) is not in the local trust store.
  • 21: unable to verify the first certificate: A catch-all for various issues with the end-entity certificate or finding its issuer. Often points to missing intermediates or untrusted roots.
  • 27: certificate revoked: The certificate appears on a CRL. Requires CRL checking to be configured and working.
  • 50: key usage violation / 63: invalid purpose: The Key Usage or EKU extensions are inconsistent with how the certificate is being used (e.g., a cert without Certificate Sign trying to issue another cert).
  • 62: hostname mismatch: -verify_hostname failed. The name in the certificate (SAN/CN) does not match the requested hostname. (Requires OpenSSL 1.1.0+ for this specific code, older versions might show a generic error).

Use -showcerts, -CAfile/-CApath, and checking certificate details (openssl x509 -text) to debug these errors.

11. Controlling Protocol Versions and Cipher Suites

While our focus is certificates, the TLS protocol version and cipher suite negotiated can be relevant (e.g., certificate signature algorithms might require TLS 1.2+). s_client allows controlling these.

Specifying TLS/SSL Versions (-tls1_3, -tls1_2, -no_tls1_3, etc.)

  • -tls1_3, -tls1_2, -tls1_1, -tls1: Force use of only that specific protocol version.
  • -no_ssl3, -no_tls1, -no_tls1_1, -no_tls1_2, -no_tls1_3: Disable specific protocol versions. Useful for testing server support or forcing newer protocols.

“`bash

Test connection using only TLS 1.2

openssl s_client -connect www.example.com:443 -servername www.example.com -tls1_2

Test connection disabling TLS 1.0 and 1.1

openssl s_client -connect www.example.com:443 -servername www.example.com -no_tls1 -no_tls1_1
“`

Specifying Cipher Suites (-cipher, -ciphersuites)

  • -cipher <cipher_list>: Specifies the list of cipher suites for TLS 1.2 and below (OpenSSL format, colon-separated, e.g., ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256).
  • -ciphersuites <cipher_list>: Specifies the list of cipher suites for TLS 1.3 (IANA format, colon-separated, e.g., TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256).

“`bash

Force a specific TLS 1.2 cipher suite

openssl s_client -connect www.example.com:443 -servername www.example.com -tls1_2 -cipher ECDHE-RSA-AES256-GCM-SHA384

Force a specific TLS 1.3 cipher suite

openssl s_client -connect www.example.com:443 -servername www.example.com -tls1_3 -ciphersuites TLS_AES_256_GCM_SHA384
“`
This can be used to check if a server supports specific required ciphers, or if a certificate (e.g., with an EC key) works correctly with specific EC-based ciphers.

12. Handling Non-HTTPS Protocols (STARTTLS)

Many protocols (SMTP, POP3, IMAP, FTP, LDAP) start as plain text on their standard ports and then upgrade to TLS using a STARTTLS (or similar) command. s_client supports this with the -starttls option.

Using -starttls <protocol>

The -starttls flag tells s_client to connect, perform the initial protocol-specific handshake (or just wait for the server greeting), send the STARTTLS command appropriate for the specified protocol, and then initiate the TLS negotiation.

Supported protocols typically include: smtp, pop3, imap, ftp, ldap, xmpp, psql.

Examples:

  • SMTP (usually port 587 or 25):
    bash
    openssl s_client -connect smtp.example.com:587 -servername smtp.example.com -starttls smtp

    After connecting, s_client will wait for the 220 greeting, send EHLO, wait for the capability list including STARTTLS, send STARTTLS, wait for 220 Ready to start TLS, and then perform the TLS handshake and show certificate info.

  • IMAP (usually port 143):
    bash
    openssl s_client -connect imap.example.com:143 -servername imap.example.com -starttls imap

  • POP3 (usually port 110):
    bash
    openssl s_client -connect pop3.example.com:110 -servername pop3.example.com -starttls pop3

Once the TLS handshake completes after STARTTLS, you can inspect the certificate information exactly as you would for HTTPS connections, including using -showcerts and piping to openssl x509. Remember to use -servername if the server uses SNI (common for mail servers hosting multiple domains).

13. Advanced Techniques and Scripting

The real power comes from combining s_client, openssl x509, and standard Unix tools (grep, awk, sed, date, etc.) for automation.

Extracting Specific Fields Programmatically

  • Get Expiry Date:
    “`bash
    EXPIRY_DATE=$(openssl s_client -connect www.example.com:443 -servername www.example.com /dev/null | \
    openssl x509 -noout -enddate | cut -d= -f2)
    echo “Expires on: $EXPIRY_DATE”

    Convert to epoch seconds for comparison (requires GNU date or similar)

    EXPIRY_EPOCH=$(date -d “$EXPIRY_DATE” +%s)
    NOW_EPOCH=$(date +%s)
    DAYS_LEFT=$(( (EXPIRY_EPOCH – NOW_EPOCH) / 86400 ))
    echo “Days left: $DAYS_LEFT”
    “`

  • Get All DNS SANs: (Using the previous awk/sed example)
    bash
    SANS=$(openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null 2>/dev/null | \
    openssl x509 -noout -text | \
    awk '/X509v3 Subject Alternative Name:/ {getline; gsub(/ /,""); print}' | \
    sed 's/DNS://g' | tr ',' '\n')
    echo "SANs:"
    echo "$SANS"

  • Get Issuer CN:
    bash
    ISSUER_CN=$(openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null 2>/dev/null | \
    openssl x509 -noout -issuer | sed -n 's/.*CN = \([^,]*\).*/\1/p')
    echo "Issuer CN: $ISSUER_CN"

Automated Certificate Monitoring Scripts

You can build shell scripts to periodically check certificates on multiple servers:

“`bash

!/bin/bash

SERVERS=( “www.example.com:443” “api.example.com:443” “mail.example.com:587:smtp” )
WARN_DAYS=30
ALERT_THRESHOLD=$(( WARN_DAYS * 86400 )) # Seconds

for server_info in “${SERVERS[@]}”; do
IFS=’:’ read -r host port protocol <<< “$server_info”
servername=$host # Assume servername matches host for simplicity

echo “Checking: $host:$port…”

starttls_opt=””
if [[ -n “$protocol” ]]; then
starttls_opt=”-starttls $protocol”
fi

# Use timeout to prevent hanging
cert_pem=$(timeout 10 openssl s_client -connect “$host:$port” -servername “$servername” $starttls_opt /dev/null | \
sed -n ‘/—–BEGIN CERTIFICATE—–/,/—–END CERTIFICATE—–/p; /—–END CERTIFICATE—–/q’)

if [[ -z “$cert_pem” ]]; then
echo ” ERROR: Could not retrieve certificate for $host:$port”
continue
fi

# Check expiry
if ! echo “$cert_pem” | openssl x509 -noout -checkend $ALERT_THRESHOLD > /dev/null 2>&1; then
enddate=$(echo “$cert_pem” | openssl x509 -noout -enddate | cut -d= -f2)
echo ” WARNING: Certificate for $host:$port expires soon! ($enddate)”
else
echo ” Expiry OK.”
fi

# Add other checks here (e.g., issuer, SANs)

done

echo “Check complete.”
“`
(This is a basic example; robust monitoring involves more error handling, retries, better output, etc.)

Combining s_client with other tools

  • jq: If dealing with APIs that return certificate info in JSON.
  • grep/awk/sed: Essential for parsing text output.
  • date: For date comparisons and formatting.
  • timeout: To prevent s_client from hanging indefinitely.

14. Common Pitfalls and Troubleshooting

  • Forgetting -servername: The most common mistake. Always use it for SNI-enabled servers. Result: Wrong certificate or handshake failure.
  • Firewall Restrictions: Ensure the port (e.g., 443) is open between your client machine and the server. Result: Connection timed out or refused.
  • Missing Intermediate Certificates: Server isn’t configured to send the full chain. Result: Verification error (unable to get local issuer certificate). Use -showcerts to check what the server sends.
  • Incorrect Trust Store Configuration: Using -CAfile or -CApath incorrectly, or the default store missing the required root CA. Result: Verification error (self signed, unable to get local issuer).
  • Protocol/Cipher Mismatches: Client and server cannot agree on a TLS version or cipher suite. Result: Handshake failure. Use -tls* / -no_tls* / -cipher* options to debug.
  • Expired/Not Yet Valid Certificate: Simple validity check failure. Result: Verification error. Check with openssl x509 -dates.
  • Hostname Mismatch: Certificate SAN/CN doesn’t match the -servername or -verify_hostname value. Result: Verification error (if hostname check enabled). Check SANs in -text output.
  • Input Buffering: Sometimes pipes (|) can cause issues if commands expect immediate input/output. Using temporary files or tools like expect might be needed for complex interactions (though usually not just for certificate retrieval). Using </dev/null often helps avoid stdin issues.

15. Alternatives to openssl s_client

While s_client is powerful, other tools can also provide certificate information:

  • Web Browsers (Developer Tools): Modern browsers have built-in tools (often under Security or Network tabs in Developer Tools) that display the certificate chain, validity, issuer, subject, SANs, and verification status visually. Easy for quick checks on websites.
  • curl -v: The curl command with the verbose flag (-v) shows TLS handshake details, including the server certificate chain information (Subject, Issuer, Validity, SANs) during the connection setup. Less detailed than openssl x509 -text but convenient.
    bash
    curl -v https://www.example.com > /dev/null
  • nmap (NSE Scripts): The network scanner nmap has Nmap Scripting Engine (NSE) scripts like ssl-cert and ssl-enum-ciphers that can retrieve certificate details and test protocols/ciphers.
    bash
    nmap --script ssl-cert -p 443 www.example.com
  • Online SSL Checkers: Websites like SSL Labs’ SSL Test provide exhaustive analysis of a server’s TLS configuration, including certificate details, chain issues, protocol support, cipher suites, vulnerabilities, etc. Very comprehensive but requires the server to be publicly accessible.
  • Other Language Libraries: Programming languages have libraries for TLS connections (Python ssl, Go crypto/tls, Java javax.net.ssl) that allow programmatic access to certificate details after establishing a connection.

Why openssl s_client? Its main advantages are its ubiquity on Unix-like systems, fine-grained control over connection parameters (protocols, ciphers, SNI), direct access to the raw PEM certificates, and seamless integration with openssl x509 for deep analysis via standard command-line pipes. It’s the sysadmin’s and security professional’s go-to tool for direct TLS interaction and certificate inspection.

16. Conclusion

openssl s_client is an essential command-line utility for anyone needing to interact directly with TLS servers and inspect their certificates. By understanding its core options like -connect, -servername, and -showcerts, you can reliably retrieve the certificate(s) presented during a TLS handshake.

The true analytical power, however, comes from piping the PEM output of s_client into openssl x509. Using options like -text, -noout, -subject, -issuer, -dates, -serial, -fingerprint, -purpose, and leveraging standard text processing tools, you can dissect every detail of a certificate – from basic identity and validity information to complex X.509v3 extensions like Key Usage, EKU, SANs, AIA, and CDP.

Mastering openssl s_client and openssl x509 empowers you to effectively troubleshoot TLS connection problems, verify security configurations, audit certificate deployments, monitor expiry dates, and gain a much deeper understanding of the certificates that underpin trust on the internet. It’s a fundamental skill for navigating the complexities of TLS/SSL in today’s interconnected world.

Leave a Comment

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

Scroll to Top