跳到主要内容
ecdsa.com
Java (JSSE)Java

错误信息

javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake

也可能输出为

  • Remote host terminated the handshake

JDK 21 和 25 打印的是“Remote host terminated the handshake”。在 Java 8 的日志中,同样的情况通常显示为“Remote host closed connection during handshake”,其原因(cause)为“SSL peer shut down incorrectly”。

Java (JSSE) — the TCP connection closed during the handshake without a TLS alert

含义

在 JVM 进行 TLS 握手的过程中,对端(或中间的某个设备)关闭了 TCP 连接,且没有发送 TLS 告警。Java 无从得知原因,只能看到连接结束了。通常是防火墙、代理或负载均衡器丢弃了握手,或者服务器静默地拒绝了 ClientHello。

原因

修复方法

  1. 1.

    跟踪握手过程,并与 openssl 对比

    javax.net.debug 会显示握手进行到了哪一步;如果在同一台主机上运行的 openssl s_client 也被断开,原因就在网络或服务器,而不在 JVM。

    bash
    java -Djavax.net.debug=ssl:handshake -jar app.jar 2>&1 | grep -E 'ClientHello|server_name|EOF|terminated'
    # Same handshake without Java: is it the network or the JVM?
    openssl s_client -connect api.example.com:443 -servername api.example.com -brief </dev/null
  2. 2.

    使用所在网络的代理

    Java 默认不使用操作系统或浏览器的代理设置;设置 https.proxyHost/https.proxyPort(或 -Djava.net.useSystemProxies=true),并用 http.nonProxyHosts 排除内部主机。

    bash
    # Corporate networks: route HTTPS through the proxy the browser uses
    java -Dhttps.proxyHost=proxy.example.net -Dhttps.proxyPort=3128 \
         -Dhttp.nonProxyHosts="localhost|*.internal.example.com" -jar app.jar
  3. 3.

    发送 SNI

    在 URL 中使用主机名,并保持 SNI 扩展处于启用状态。

    text
    Connect with the host name (not an IP address) so JSSE sends SNI, and do not set
    -Djsse.enableSNIExtension=false: front ends that need SNI close such connections.

相关错误

浏览完整的签名错误库