Investigating SSL Handshake Issues(javax.net.ssl.SSLException: Received fatal alert: internal_error) During Migration to Spring Boot 3.x and Java 17

Investigating SSL Handshake Issues(javax.net.ssl.SSLException: Received fatal alert: internal_error) During Migration to Spring Boot 3.x and Java 17
Photo by Mi Min / Unsplash

Recently, our team embarked on the task of migrating applications to Spring Boot 3.x and Java 17. However, during this transition, we encountered an unusual SSL handshake error affecting a subset of our applications. The issue exhibited a sporadic nature, with approximately a 20% reproduction rate, and intriguingly, a retry attempt consistently resolved it. Eager to delve deeper into this anomaly, we opted to enable comprehensive network logging by leveraging Java VM arguments, specifically -Djavax.net.debug=all. This enabled us to gather detailed logs from the client-side.

"Alert": {
  "level"      : "fatal",
  "description": "internal_error"
}
)
javax.net.ssl|ERROR|92|http-nio-9000-exec-3|2024-04-15 15:33:55.009 UTC|TransportContext.java:363|Fatal (INTERNAL_ERROR): Received fatal alert: internal_error (
"throwable" : {
  javax.net.ssl.SSLException: Received fatal alert: internal_error
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:133)

Upon analysis, we uncovered a corresponding stack trace originating from the server-side, indicating an inability to interpret the SSL message sent by the client.

javax.net.ssl|ERROR|13|https-jsse-nio-9000-exec-10|2024-04-15 10:33:55.004 CDT|TransportContext.java:363|Fatal (INTERNAL_ERROR): problem unwrapping net record (
"throwable" : {
  javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
    at java.base/sun.security.ssl.SSLEngineInputRecord.bytesInCompletePacket(SSLEngineInputRecord.java:145)
    at java.base/sun.security.ssl.SSLEngineInputRecord.bytesInCompletePacket(SSLEngineInputRecord.java:64)
    at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:612)
    at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:506)
    at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:482)
    at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:679)
    at org.apache.tomcat.util.net.SecureNioChannel.handshakeUnwrap(SecureNioChannel.java:481)
    at org.apache.tomcat.util.net.SecureNioChannel.handshake(SecureNioChannel.java:213)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1715)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:833)}

Notably, the issue consistently occurred when the client attempted to resume a session, resulting in an immediate fatal error. Further investigation revealed that the sessions attempting to resume were negotiated with TLSv1.3.

Try resuming session (
Session(1713195048209|TLS_AES_256_GCM_SHA384)
)
javax.net.ssl|INFO|92|http-nio-9000-exec-3|2024-04-15 15:33:54.954 UTC|AlpnExtension.java:182|No available application protocols
javax.net.ssl|DEBUG|92|http-nio-9000-exec-3|2024-04-15 15:33:54.954 UTC|SSLExtensions.java:272|Ignore, context unavailable extension: application_layer_protocol_negotiation
javax.net.ssl|ALL|92|http-nio-9000-exec-3|2024-04-15 15:33:54.954 UTC|SignatureScheme.java:412|Ignore disabled signature scheme: dsa_sha256
javax.net.ssl|ALL|92|http-nio-9000-exec-3|2024-04-15 15:33:54.954 UTC|SignatureScheme.java:412|Ignore disabled signature scheme: dsa_sha224
javax.net.ssl|ALL|92|http-nio-9000-exec-3|2024-04-15 15:33:54.954 UTC|SignatureScheme.java:412|Ignore disabled signature scheme: dsa_sha1
javax.net.ssl|ALL|92|http-nio-9000-exec-3|2024-04-15 15:33:54.954 UTC|SignatureScheme.java:412|Ignore disabled signature scheme: rsa_md5
javax.net.ssl|DEBUG|92|http-nio-9000-exec-3|2024-04-15 15:33:54.954 UTC|SSLExtensions.java:272|Ignore, context unavailable extension: cookie
javax.net.ssl|DEBUG|92|http-nio-9000-exec-3|2024-04-15 15:33:54.955 UTC|SSLExtensions.java:272|Ignore, context unavailable extension: renegotiation_info
javax.net.ssl|DEBUG|92|http-nio-9000-exec-3|2024-04-15 15:33:54.955 UTC|PreSharedKeyExtension.java:707|Found resumable session. Preparing PSK message.
javax.net.ssl|DEBUG|92|http-nio-9000-exec-3|2024-04-15 15:33:54.990 UTC|ClientHello.java:641|Produced ClientHello handshake message (
"ClientHello": {
  "client version"      : "TLSv1.2",
  "random"              : "11BEE3F305C4048B9BA2BB2E4F8D1E124E9C75CA038F5F64805658218628B90A",
  "session id"          : "",

The session trying to resuming was negotiated with TLSv1.3:

Negotiated protocol version: TLSv1.3
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLExtensions.java:175|Ignore unsupported extension: server_name
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLExtensions.java:175|Ignore unsupported extension: max_fragment_length
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLExtensions.java:175|Ignore unsupported extension: status_request
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLExtensions.java:175|Ignore unsupported extension: ec_point_formats
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLExtensions.java:175|Ignore unsupported extension: application_layer_protocol_negotiation
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLExtensions.java:175|Ignore unsupported extension: status_request_v2
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLExtensions.java:175|Ignore unsupported extension: extended_master_secret
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLExtensions.java:175|Ignore unsupported extension: session_ticket
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLExtensions.java:204|Consumed extension: supported_versions
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLExtensions.java:204|Consumed extension: key_share
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLExtensions.java:175|Ignore unsupported extension: renegotiation_info
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|PreSharedKeyExtension.java:924|Handling pre_shared_key absence.
javax.net.ssl|ALL|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLSessionImpl.java:219|Session initialized:  Session(1713195048209|TLS_AES_256_GCM_SHA384)
javax.net.ssl|DEBUG|D2|http-nio-9000-exec-7|2024-04-15 15:30:48.209 UTC|SSLExtensions.java:219|Ignore unavailable extension: server_name

Interestingly, we encountered a similar pattern of issues during a previous upgrade to Java 11 and Spring Boot 2.6.x. At that time, we addressed the issue by implementing a retry mechanism for SSLExceptions, particularly for API calls to SOAP endpoints. However, this time around, our focus lies in identifying the root cause of the issue. Extensive research, both internal and external, led us to discover similar issues reported by others, notably documented as JDK-8277307.

Problem with SSL handshake after upgrade spring boot and java 17
My spring boot application could not work with old SSL certificate after upgrading to spring boot 2.6 and Java 17.After debuging, seems there was problem with TLS version or ciphers suite. I don’t...

https://bugs.openjdk.org/browse/JDK-8277307

Java 11 HTTPS connection fails with SSL HandshakeException while using Jsoup
I am trying to crawl a webpage (this one) using Jsoup library. While performing simple GET operation, i am getting the following exception: javax.net.ssl|DEBUG|01|main|2018-12-24 15:41:06.431 EET|

Fortunately, our findings provided potential solutions, suggesting an upgrade to Java 17.0.10 or alternatively applying a workaround by configuring the JVM argument -Djdk.tls.client.enableSessionTicketExtension=false on the client side. Armed with this information, we are eager to implement Java 17.0.10 and assess its effectiveness in resolving the SSL handshake issue.

In conclusion, our journey toward migrating to Spring Boot 3.x and Java 17 has presented us with unforeseen challenges. Yet, each obstacle serves as an opportunity for growth and learning. By diligently investigating and applying solutions, we aim not only to resolve immediate issues but also to fortify our systems for the future. Through collaboration and perseverance, we are confident in our ability to navigate these complexities and emerge stronger than before. We eagerly anticipate the outcome of implementing Java 17.0.10 and remain committed to addressing any challenges that may arise along the way.

Subscribe to Post, Code and Quiet Time.

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe