エラーメッセージ
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 で無効化されています。サーバーには何も送信されていません。
発生する理由
アプリケーションが古いプロトコルを強制している
よくある何年も前にレガシーなサーバー向けに書かれた SSLContext.getInstance("TLSv1")、setEnabledProtocols(new String[]{"TLSv1"})、https.protocols=TLSv1 などの指定です。
JDK のアップデートで、アプリケーションが使っていたものが無効化された
よくある2021 年に Java 8、11 およびそれ以降のバージョン向けに提供されたセキュリティアップデートで、TLS 1.0 と 1.1 はデフォルトで無効化されました。これらでしか動作しなかったアプリケーションは、アップグレード後に動かなくなります。
明示的に指定した暗号スイートのリストに、無効化されたスイートしか含まれていない
ときどきTLS_RSA_* や 3DES のスイートをいくつか列挙しただけの設定では、それらが無効化されると使えるものが何も残りません。
修正方法
- 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.
「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.
最終手段: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