本文へスキップ
ecdsa.com
Java (JSSE)Java

エラーメッセージ

No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

別の表記

  • javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

文言は JDK 8 のアップデートから JDK 25 まで同じです。JVM がサーバー側の場合、自身のプロトコルがすべて無効化されていると、同じ状況が「No appropriate protocol」として現れます。

Java (JSSE) — the client itself has no enabled protocol/cipher combination left

このエラーの意味

JVM は ClientHello を組み立てることすらできませんでした。jdk.tls.disabledAlgorithms に列挙されたプロトコルと暗号スイートをすべて除外すると、アプリケーションが要求したものが何も残らないためです。典型的なのは、コードや設定が TLS 1.0、TLS 1.1、SSLv3 のいずれかを使うよう固定している場合で、これらはすべて現在の JDK で無効化されています。サーバーには何も送信されていません。

発生する理由

修正方法

  1. 1.

    古いプロトコルを要求している箇所を見つける

    コードと JVM オプションから、明示的に指定されたプロトコル名を探してください。-XshowSettings:security:tls を使うと、JDK で有効になっているものを確認できます。

    bash
    grep -rnE 'SSLContext.getInstance\("(TLSv1|TLSv1\.1|SSL)"\)|setEnabledProtocols|https\.protocols' src/
    java -XshowSettings:security:tls -version 2>&1 | sed -n '/Enabled Protocols/,/Enabled Cipher/p'
  2. 2.

    「TLS」を要求し、ネゴシエーションは JSSE に任せる

    現在の JDK では、SSLContext.getInstance("TLS") で TLS 1.3 と 1.2 が有効になります。

    java
    // Let JSSE negotiate the best version (TLS 1.3 / 1.2)
    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(null, null, null);
  3. 3.

    最終手段:1 つのレガシーなエンドポイントに限定した上書き

    機器をアップグレードできない場合は、別のセキュリティプロパティファイルを使って、その機器と通信する JVM に限り jdk.tls.disabledAlgorithms から TLSv1/TLSv1.1 を除外できます。JDK の現在の値全体を出発点にし、プロトコルの項目だけを変更したうえで、その JVM を隔離してください。

    bash
    # Last resort for ONE legacy endpoint: take this JDK's own value and drop only TLSv1/TLSv1.1
    v=$(sed -n '/^jdk.tls.disabledAlgorithms=/,/[^\\]$/p' "$JAVA_HOME/conf/security/java.security" | sed 's/\\$//' | tr -d '\n')
    printf '%s\n' "$v" | sed -E 's/ TLSv1(\.1)?,//g' > legacy-tls.security
    java -Djava.security.properties=legacy-tls.security -jar legacy-client.jar

関連するエラー

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