⏱ Time to read: 4 minutes
TL;DR
java -Djavax.net.debug=ssl:handshake:verbose -jar your-application.jar
- Enable SSL logging with
-Djavax.net.debug=ssl:handshake:verbose
- Java 11+ logs include TLS 1.3-specific details.
- Logs help troubleshoot certificate issues, protocol mismatches, and cipher suite failures.
SSL/TLS handshakes are vital for secure communication in Java applications. Logging and analysing handshake details helps with debugging and enhancing security.
In this article, we’ll cover the most common errors during SSL/TLS handshake and how to troubleshoot them using logs.
Common SSL Issues That Logging Can Help Pinpoint
- Certificate Expiry or Trust Problems: Identify when certificates have expired or are not trusted by the client.
- Protocol Mismatches: Detect issues when the client and server support different SSL/TLS protocol versions.
- Cipher Suite Negotiation Failures: When the server chooses a cipher suite that the client does not support.
- Hostname Verification Errors: When the hostname in the certificate does not match the requested domain.
- Unsupported Algorithms: When the cipher or key exchange algorithm is not supported by one of the parties.
- Certificate Chain Validation Issues: When the chained certificates is invalid or incomplete.
- TLS Version Downgrades: Identify when connections fall back to an older, less secure TLS version.
We’ll look at examples for each common SSL handshake below, and hopefully it will give you enough context for your own investigation.
Setting Up SSL Handshake Logging
To log SSL handshake details, configure the JVM for verbose SSL debugging. Here’s how:
1. Enabling SSL Debug Logging
The command to enable SSL debug logging varies slightly with different Java versions:
- Java 7 or older: Use this command for detailed SSL debugging:
java -Djavax.net.debug=ssl -jar your-application.jar
- Java 8 and Above: The command remains the same, but logs may include TLS 1.3-specific entries:
java -Djavax.net.debug=ssl:handshake:verbose -jar your-application.jar
Java 11+ supports TLS 1.3 by default, so you’ll see additional protocol and handshake messages.
Additional Methods to Enable SSL Logging
Besides JVM options, you can enable SSL logging in other ways:
- Programmatic Property Setting:
System.setProperty("javax.net.debug", "ssl:handshake:verbose");
This approach is useful for toggling SSL logging dynamically in specific environments.
- Logging Framework Integration: Capture and redirect SSL debug outputs to application logs with frameworks like Logback or Log4j by configuring output streams to log files or monitoring services.
Reading and Understanding Log Output
Once SSL debug logging is enabled, your logs will show detailed handshake information. Here’s a sample log snippet:
*** ClientHello, TLSv1.3
RandomCookie: [bytes...]
Session ID: [session id]
Cipher Suites: [TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384]
...
*** ServerHello, TLSv1.3
RandomCookie: [bytes...]
Cipher Suite: TLS_AES_128_GCM_SHA256
...
*** Certificate chain
chain [0]: CN=example.com, OU=IT, O=Example Corp, L=City, ST=State, C=US
...
***
These logs detail key phases of the handshake. The ClientHello
section shows the client’s initial request and proposed cipher suites, while the ServerHello
indicates the chosen suite.
Examples of Log Outputs and Troubleshooting Tips
Understanding log outputs and interpreting them is essential for effective troubleshooting. Here are common examples and their analysis:
Example Log Outputs and Their Analysis
- Certificate Expiry or Trust Issues:
*** Certificate chain
chain [0]: CN=example.com, OU=IT, O=Example Corp, L=City, ST=State, C=US
verification failed: java.security.cert.CertificateExpiredException: NotAfter: Mon Apr 15 12:00:00 UTC 2024
***
Analysis: This indicates an expired server certificate. Renew the certificate or check if the trust store has current certificates.
- Protocol Mismatch:
%% No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
%% SSLHandshakeException: Received fatal alert: protocol_version
Analysis: The client and server do not agree on the SSL/TLS protocol version. Ensure both sides support a common version, like TLS 1.2 or TLS 1.3.
- Cipher Suite Negotiation Failure:
*** ClientHello, TLSv1.2
Cipher Suites: [TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA]
...
*** ServerHello, TLSv1.2
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA
...
%% Invalid or unsupported cipher suite.
Analysis: The server chose a cipher suite unsupported or disabled on the client side. Review the enabled cipher suites in your JVM.
- Hostname Verification Issues:
%% hostname in certificate didn’t match: <example.com> != <other-example.com>
%% javax.net.ssl.SSLPeerUnverifiedException: Hostname verification failed
Analysis: The SSL handshake failed due to a hostname mismatch. Ensure the hostname matches the certificate or implement a custom verifier if needed.
Troubleshooting Tips
- Analyze Log Context: Look at surrounding entries for related SSL/TLS information, such as key exchange details.
- Certificate Path Validation: Use tools like
keytool
or OpenSSL to inspect certificates for proper chaining and validation. - Review JVM Security Policies: Verify that your Java security policy allows the desired algorithms and protocols.
Conclusion
Logging SSL handshake details in Java helps diagnose connection issues and ensures secure, seamless communication. Enabling JVM-level debugging or integrating programmatic listeners can enhance visibility into SSL/TLS handshakes and aid in proactive troubleshooting.