Mensaje de error
No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
También se muestra como
- javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
El texto es el mismo desde las actualizaciones de JDK 8 hasta JDK 25. Cuando una JVM actúa como servidor, la misma situación aparece como «No appropriate protocol» si todos sus propios protocolos están desactivados.
Java (JSSE) — the client itself has no enabled protocol/cipher combination left
Qué significa
La JVM ni siquiera pudo construir un ClientHello: tras quitar todos los protocolos y conjuntos de cifrado de jdk.tls.disabledAlgorithms, no queda nada de lo que pidió la aplicación. Normalmente, el código o la configuración se empeñan en usar TLS 1.0, TLS 1.1 o SSLv3, todos desactivados en los JDK actuales. No se envió nada al servidor.
Por qué ocurre
La aplicación fuerza un protocolo antiguo
frecuenteSSLContext.getInstance("TLSv1"), setEnabledProtocols(new String[]{"TLSv1"}) o https.protocols=TLSv1, escritos hace años para un servidor heredado.
Una actualización del JDK desactivó lo que usaba la aplicación
frecuenteTLS 1.0 y 1.1 se desactivaron por defecto en las actualizaciones de seguridad de 2021 de Java 8, 11 y posteriores; las aplicaciones que solo funcionaban con ellos dejan de funcionar al actualizar.
Una lista explícita de conjuntos de cifrado solo contiene conjuntos desactivados
ocasionalLas configuraciones que enumeran unos pocos conjuntos TLS_RSA_* o 3DES no dejan nada utilizable una vez que estos se desactivan.
Cómo solucionarlo
- 1.
Encontrar dónde se pide el protocolo antiguo
Busca nombres de protocolo explícitos en el código y en las opciones de la JVM; -XshowSettings:security:tls muestra lo que el JDK tiene activado.
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.
Pedir «TLS» y dejar que JSSE negocie
SSLContext.getInstance("TLS") activa TLS 1.3 y 1.2 en los JDK actuales.
java // Let JSSE negotiate the best version (TLS 1.3 / 1.2) SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, null, null); - 3.
Último recurso: una sobrescritura acotada para un único endpoint heredado
Si un dispositivo no se puede actualizar, un archivo de propiedades de seguridad aparte puede quitar TLSv1/TLSv1.1 de jdk.tls.disabledAlgorithms para la JVM que se comunica con él. Parte del valor actual completo del JDK, cambia solo las entradas de protocolo y aísla esa 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