En la última actualización de JDK en abril de 2021 ( 11.0.11+9-0ubuntu2~18.04
), se eliminó la compatibilidad con TLSv1
y TLSv1.1
, presumiblemente porque desde marzo de 2021 esas versiones ya no son compatibles. Esto es evidente por la diferencia en el archivo java.security
:
Antes:
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \ EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ include jdk.disabled.namedCurves
Después:
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \ DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ include jdk.disabled.namedCurves
que también se analiza en esta publicación SO: SSLHandShakeException No Appropriate Protocol . En ese hilo también hay más respuestas apareciendo en los últimos días desde la versión actualizada de JDK.
Después de esta actualización del JDK, recibimos el error
java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
con c3p0
.
Después de cambiar a hikari
, obtuvimos un error más significativo:
ERROR [2021-04-29 16:21:16,426] com.zaxxer.hikari.pool.HikariPool: HikariPool-1 - Exception during pool initialization. ! javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
Estamos ejecutando MySQL 5.7.33-0ubuntu0.18.04.1
. Ahora, según tengo entendido, como se describe aquí , MySQL 5.7 es compatible con TLSv1.2. También cuando se ejecuta SHOW VARIABLES LIKE 'tls_version';
obtenemos TLSv1,TLSv1.1,TLSv1.2
que sugieren que se admite TLSv1.2
.
Entonces, la pregunta es, ¿por qué JDK y MySQL simplemente no acuerdan usar TLSv1.2
y qué podemos hacer al respecto para que se comuniquen con TLSv1.2
?
Nota: ¡No creo que cambiar el archivo java.security
como se sugiere en el otro hilo sea una buena solución a largo plazo para este problema!
Como @skelwa ya comentó, deberá agregar la propiedad de configuración enabledTLSProtocols=TLSv1.2
en la cadena de conexión para resolver su problema.
Una cadena de conexión completa para Connector/J podría verse así:
jdbc:mysql://<host>:<port>/<dbname>?enabledTLSProtocols=TLSv1.2
Para r2dbc necesitará usar tlsVersion=TLSv1.2
en su lugar.
Para Connector/J v8.0.28 enabledTLSProtocols
se cambió el nombre de enableTLSProtocols a tlsVersions
(ver nota ). Sin embargo, el nombre original permanece como un alias.
La pregunta que queda es:
¿Por qué JDK y MySQL simplemente no están de acuerdo en usar TLSv1.2
?
Aunque ambas partes realmente admiten TLSv1.2, el problema que estaba experimentando lo presenta el comportamiento predeterminado de Connector/J. Por motivos de compatibilidad, Connector/J no habilita TLSv1.2 y superior de forma predeterminada. Por lo tanto, uno tiene que habilitarlo explícitamente.
Ver la siguiente nota :
Para Connector/J 8.0.18 y versiones anteriores cuando se conecta a MySQL Community Server 5.6 y 5.7 mediante la API de JDBC: debido a problemas de compatibilidad con MySQL Server compilado con yaSSL, Connector/J no habilita las conexiones con TLSv1.2 y versiones posteriores de manera predeterminada. Al conectarse a servidores que restringen las conexiones para usar esas versiones superiores de TLS, habilítelos explícitamente configurando la propiedad de conexión Connector/J enableTLSProtocols (por ejemplo, establezca enableTLSProtocols=TLSv1,TLSv1.1,TLSv1.2).
ADVERTENCIA: tenga en cuenta que las soluciones que sugieren editar jdk.tls.disabledAlgorithms
dentro de jre/lib/security
representan un riesgo de seguridad para su aplicación y cambiar cualquier cosa allí podría tener graves implicaciones. Hay razones por las que esos protocolos se deshabilitaron y uno no debe simplemente eliminar todo o incluso solo partes de esa lista.
Nota: si desea obtener más información de bajo nivel del JDK para depurar su problema, puede habilitar los registros de depuración de ssl pasando la siguiente configuración al comando java:
-Djavax.net.debug=ssl,handshake
o incluso -Djavax.net.debug=all
En tu caso verás algo como:
...(HANDSHAKE_FAILURE): Couldn't kickstart handshaking ( "throwable" : { javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) at java.base/sun.security.ssl.HandshakeContext.<init>(HandshakeContext.java:170) at java.base/sun.security.ssl.ClientHandshakeContext.<init>(ClientHandshakeContext.java:98) ...
Acabo de agregar useSSL=false y funcionó para mí.
jdbc:mysql://<host>:<port>/<dbname>?useSSL=false
Tengo JDK 8, MySQL 5.7 y mysql-connector-java lib con la versión 5.1.38
Esto es útil cuando desea ejecutar rápidamente solo en un entorno local (no en preparación/prueba/producción)
Puedes hacer los siguientes pasos:
jdk.tls.disabledAlgorithms
Después de esto, intente ejecutar y debería funcionar.
O si solo desea un algoritmo específico, elimínelo de la lista de deshabilitados.
Puede enviarlo en la configuración y comentarlo en el archivo java.security
jdbc:mysql://<host>:<port>/<dbname>?enabledTLSProtocols=TLSv1.2
Vine aquí porque tenía el mismo problema, pero desafortunadamente,
jdbc:mysql://host:puerto/nombrebd?enabledTLSProtocols=TLSv1.2
no funcionó para mí porque estoy usando r2dbc. Después de un poco de depuración, descubrí que el nombre del parámetro debe ser tlsVersion
, por lo que puede usar, por ejemplo:
spring.r2dbc.url=r2dbc:mysql://host:port/dname?tlsVersion=TLSv1.2