SSL peer shut down incorrectly in Java
JavaSslJava Problem Overview
I need to make a request through a HTTPS protocol. I wrote the following code:
import java.net.HttpURLConnection;
import java.net.URL;
import org.junit.Test;
public class XMLHandlerTest {
private static final String URL = "https://ancine.band.com.br/xml/pgrt1_dta_20150303.xml";
@Test
public void testRetrieveSchedule() {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(URL).openConnection();
connection.setRequestMethod("HEAD");
int responseCode = connection.getResponseCode();
System.out.println(responseCode);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I got this exception stacktrace with a java.io.EOFException:
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:953)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1301)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
at br.com.onebr.onesocial.arte1.service.core.scheduler.Arte1XMLHandlerTest.testRetrieveSchedule(Arte1XMLHandlerTest.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:482)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:934)
... 32 more
I got successful response from https://google.com but this error from URL above (https://ancine.band.com.br/xml/pgrt1_dta_20150303.xml).
Using PHP, .NET and NodeJS that URL works fine.
Anyone has any idea why this happening?
Java Solutions
Solution 1 - Java
That is a problem of security protocol. I am using TLSv1 but the host accept only TLSv1.1 and TLSv1.2 then I changed the protocol in Java with the instruction below:
System.setProperty("https.protocols", "TLSv1.1")
;
Solution 2 - Java
You can set protocol versions in system property as :
overcome ssl handshake error
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
Solution 3 - Java
Apart from the accepted answer, other problems can cause the exception too. For me it was that the certificate was not trusted (i.e., self-signed cert and not in the trust store).
If the certificate file does not exists, or could not be loaded (e.g., typo in path) can---in certain circumstances---cause the same exception.
Solution 4 - Java
This error is generic of the security libraries and might happen in other cases. In case other people have this same error when sending emails with javax.mail to a smtp server. Then the code to force other protocol is setting a property like this:
prop.put("mail.smtp.ssl.protocols", "TLSv1.2");
//And just in case probably you need to set these too
prop.put("mail.smtp.starttls.enable", true);
prop.put("mail.smtp.ssl.trust", {YOURSERVERNAME});
Solution 5 - Java
please close the android studio and remove the file
.gradle
and
.idea
file form your project .Hope so it is helpful
Location:Go to Android studio projects->your project ->see both file remove (.gradle
& .idea
)
Solution 6 - Java
Below code worked for me You have to add below configuration in surefire plugin
<configuration> <argLine>-Dhttps.protocols=TLSv1.1</argLine> </configuration>
Solution 7 - Java
As @Zigri2612 suggested, what worked for me was to add TLS https.protocols
, but i had to do it with white spaces instead of comma separated values:
System.setProperty("https.protocols", "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3");
Solution 8 - Java
I was facing same issue, for me adding certificate to trust store solved this issue.
Solution 9 - Java
I had a similar issue that was resolved by unchecking the option in java advanced security for "Use SSL 2.0 compatible ClientHello format.
Solution 10 - Java
The accepted answer didn't work in my situation, not sure why. I switched from JRE1.7 to JRE1.8 and that resolved the issue automatically. JRE1.8 uses TLS1.2 by default
Solution 11 - Java
I experienced this exception using a SSL/TLS server Socket library on java 8. Updating the jdk to 14 (and also the VM to 14) solved the issue.
Solution 12 - Java
I was having the same issue, as everyone else I suppose.. adding the System.setProperties(....) didn't fix it for me.
So my email client is in a separate project uploaded to an artifactory. I'm importing this project into other projects as a gradle dependency. My problem was that I was using implementation
in my build.gradle for javax.mail
, which was causing issues downstream.
I changed this line from implementation
to api
and my downstream project started working and connecting again.
Solution 13 - Java
I had mutual SSL enabled on my Spring Boot app and my Jenkins pipeline was re-building the dockers, bringing the compose up and then running integration tests which failed every time with this error. I was able to test the running dockers without this SSL error every time in a standalone test on the same Jenkins machine. It turned out that server was not completely up when the tests started executing. Putting a sleep of few seconds in my bash script to allow Spring boot application to be up and running completely resolved the issue.
Solution 14 - Java
In my case i was making a request to a system that is using SSLV3. So i have added the following jvm option. And problem got resolved.
-Dhttps.protocols="TLSv1,TLSv1.1,TLSv1.2"
Solution 15 - Java
Sometimes it can be caused due to network issue. Don't know the reason but after switching to other network, the application got build and installed successfully.
Solution 16 - Java
For me, setting -Dhttps.protocols="TLSv1,TLSv1.1,TLSv1.2"
(or -Dhttps.protocols="TLSv1.2"
for that matter) didn't work.
Since I was running the problematic code in a Docker container in an AWS K8S cluster, I found a similar solution in the [AWS Documentation][1]
After setting this system property -Djdk.tls.client.protocols=TLSv1.2
, the error was gone.
[UPDATE] After deploying this to production, I noticed the behaviour is intermittent: sometimes I emails were getting sent, sometimes they didn't. Whilst researching some more, I found that my client was using TLS 1.0 which the server didn't support (it only supported TLS 1.2) The verbose error messages I was getting is this:
javax.net.ssl|SEVERE|10|grpc-default-executor-0|2021-10-22 19:38:48.017 GMT|Logger.java:765|Fatal (HANDSHAKE_FAILURE): Couldn't kickstart handshaking
Finally, after multiple trials, I solved it using the answer from here: https://stackoverflow.com/questions/47166425/how-to-force-javamailsenderimpl-to-use-tls1-2 [1]: https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/security-java-tls.html
Solution 17 - Java
I've encountered the same error message but the reason and solution are quite interesting:
my problem resolved by upgrade the openjdk from 8u40 to 8u191 or higher version 8u312,
the root cause is a kind of interoperability issue that seems the client and server are using different padding method or cipher parameter(e.g EC curve) for DH key exchange,
so if you run out of solutions, probably you may try upgrade your jdk(don't just upgrade to a major version, try to upgrade to a higher minor version first, please note my problem resolved by higher minor version for openjdk8uXXX but still failed with openjdk9)
you may refer to the whole troubleshooting process at(handshake section): https://lyhistory.github.io/docs/software/network/http_ssl_tls_setup.html
Solution 18 - Java
Check your internet connection, then resync your project.