本文へスキップ
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 のログでは、同じ状況が「SSL peer shut down incorrectly」を原因とする「Remote host closed connection during handshake」として表示されることがよくあります。

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

このエラーの意味

JVM が TLS ハンドシェイクの途中にあるときに、相手側(またはその間にある何か)が TLS アラートを送信せずに TCP 接続を閉じました。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 はデフォルトでは OS やブラウザーのプロキシ設定を使いません。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.

関連するエラー

署名エラーデータベースをすべて見る