1

I've suddenly been getting these errors when making HTTP requests:

Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1002)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:290)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:259)
at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:125)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:319)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
at com.mashape.unirest.http.HttpClientHelper.request(HttpClientHelper.java:138)
... 24 more
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:505)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)
... 41 more

It didn't always do this, it was working fine for awhile. I then used different libraries and even a different IntelliJ project for testing, still the same issues. Things I've tried:

  • Changing the endpoint I'm using
  • Setting the TLS version to TLSv1.2 (as I found when making a browser request)

I can load the endpoint fine with a browser and Postman. My code (using the Unirest library):

System.setProperty("https.protocols", "TLSv1.2");
System.out.println(Unirest.get("https://bittrex.com/api/v1.1/public/getmarketsummary?market=btc-ltc").asString().getBody());

I'm at a loss as to what could be causing this issue, and it's extremely frustrating. Any help would be appreciated.

EDIT: Updating to JDK10 fixed the issue. See the chosen answer and it's comment thread for more info.

Nicholas Harris
  • 103
  • 4
  • 15

1 Answers1

1

First, turn on SSL debug: -Djavax.net.debug=all

Redirect your code's stdout to a file and check it for errors around handshaking.

If you examine the url you use with nmap or openssl:

nmap --script ssl-enum-ciphers -p <port> <host>

or

openssl s_client -connect <host>:<port>

(host: bittrex.com, port: 443)

you can see that is uses TLSv1.2 and ECDHE-ECDSA-AES128-GCM-SHA256 cypher:

New, TLSv1/SSLv3, Cipher is ECDHE-ECDSA-AES128-GCM-SHA256
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-ECDSA-AES128-GCM-SHA256

Depending on your JDK version, you may need to install JCE extension and/or specify this cypher.

To be sure, you should print out the current supported cyphers using this little java code. If ECDHE-ECDSA-AES128-GCM-SHA256 not listed, this is your problem.

m4gic
  • 1,461
  • 12
  • 19
  • Yeah, I don't have that cypher listed. I'll check the logs with the debugging on, in the meantime what would I do to add that cypher (if that's the correct term)? – Nicholas Harris Aug 29 '18 at 22:18
  • I think yes, you have already specified the correct TLS version, and this two thing* is required to a successfully handshake (* in case of earlier JDK versions, the JCE extension too) – m4gic Aug 29 '18 at 22:22
  • How would I go about installing/getting the correct cypher? – Nicholas Harris Aug 29 '18 at 22:25
  • I have successfully connected using [SSLPoke](https://gist.github.com/4ndrej/4547029) and Oracle JDK 1.8.0_151 (64bit) without any modification of the current JDK settings and without any SSL related JVM argument (except the SSL debug). What JDK version do you use? – m4gic Aug 29 '18 at 22:29
  • According to [the documentation from Oracle](http://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html) no GCM ciphers are available in Java 1.7 but they only got added to Java .8. Which explains the message about unsupported cipher. [Source](https://stackoverflow.com/questions/32576646/unsupported-ciphersuite-tls-ecdhe-ecdsa-with-aes-128-gcm-sha256) – m4gic Aug 29 '18 at 22:33
  • I should be using JDK8, I don't think I even have 7 installed. – Nicholas Harris Aug 29 '18 at 22:35
  • Yeah, I'm definitely using JDK8. I'll try 9 and see if that makes a difference. Judging from the logs, it appears that I only have cyphers for TLS 1.0 and 1.1. – Nicholas Harris Aug 29 '18 at 22:37
  • However in case of JDK7, there is a [workaround](https://stackoverflow.com/questions/49672296/is-it-possible-to-do-use-gcm-with-bc-on-jdk-1-7). – m4gic Aug 29 '18 at 22:37
  • Try out SSLPoke too, maybe not JDK related your issue, maybe for Unirest there is another way to specify the TLS version... – m4gic Aug 29 '18 at 22:40
  • Well, upgrading to JDK 10 worked. Must be an issue with my version of it, I believe it's quite old. In any case, thanks a ton - was really starting to get frustrated with this. – Nicholas Harris Aug 29 '18 at 22:48
  • 1
    Some more info: [openssl - java cypher suite mapping](http://testssl.sh/openssl-rfc.mapping.html) [Java8 JCE (default enabled cyphers)](https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html) - in this way one can figure out that ECDHE-ECDSA-AES128-GCM-SHA256 in java TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 and it is enabled by default in Java8, there is no need to install JCE. – m4gic Aug 29 '18 at 22:52