【问题标题】:Java "Remote host closed connection during handshake" using Bittrex HTTP API使用 Bittrex HTTP API 的 Java“握手期间远程主机关闭连接”
【发布时间】:2019-02-04 15:43:26
【问题描述】:

我在发出 HTTP 请求时突然遇到这些错误:

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

它并不总是这样做,它在一段时间内运行良好。然后我使用不同的库甚至不同的 IntelliJ 项目进行测试,仍然是同样的问题。我尝试过的事情:

  • 更改我正在使用的端点
  • 将 TLS 版本设置为 TLSv1.2(我在发出浏览器请求时发现)

我可以使用浏览器和 Postman 加载端点。我的代码(使用 Unirest 库):

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

我不知道是什么导致了这个问题,这非常令人沮丧。任何帮助将不胜感激。

编辑:更新到 JDK10 解决了这个问题。有关更多信息,请参阅所选答案及其评论主题。

【问题讨论】:

    标签: java unirest


    【解决方案1】:

    首先,开启SSL debug: -Djavax.net.debug=all

    将代码的标准输出重定向到一个文件并检查它是否存在握手错误。

    如果您检查使用 nmap 或 openssl 的 url:

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

    openssl s_client -connect <host>:<port>
    

    (主机:bittrex.com,端口:443)

    您可以看到它使用 TLSv1.2 和 ECDHE-ECDSA-AES128-GCM-SHA256 密码:

    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
    

    根据您的 JDK 版本,您可能需要安装 JCE 扩展和/或 specify 这个密码。

    当然,您应该使用this little java 代码打印出当前支持的密码。如果 ECDHE-ECDSA-AES128-GCM-SHA256 未列出,这是您的问题。

    【讨论】:

    • 是的,我没有列出那个密码。我将在调试的情况下检查日志,同时我会如何添加该密码(如果这是正确的术语)?
    • 我想是的,你已经指定了正确的 TLS 版本,并且这两个东西*是成功握手所必需的(*对于早期的 JDK 版本,JCE 扩展也是)
    • 我将如何安装/获取正确的密码?
    • 我已使用SSLPoke 和 Oracle JDK 1.8.0_151(64 位)成功连接,无需对当前 JDK 设置进行任何修改,也无需任何与 SSL 相关的 JVM 参数(SSL 调试除外)。你用的是什么JDK版本?
    • 更多信息:openssl - java cypher suite mapping Java8 JCE (default enabled cyphers) - 通过这种方式可以找出 java TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 中的 ECDHE-ECDSA-AES128-GCM-SHA256 并且它在 Java8 中默认启用,有无需安装 JCE。
    猜你喜欢
    • 2017-03-03
    • 2012-08-12
    • 2018-09-27
    • 1970-01-01
    • 2019-07-19
    • 2018-07-29
    • 2017-06-25
    相关资源
    最近更新 更多