79

In the latest update to the JDK in April 2021 (11.0.11+9-0ubuntu2~18.04) support for TLSv1 and TLSv1.1 was dropped, presumably because since March 2021 those versions are no longer supported. This is evident by the diff in the java.security file:

Before:

jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
    EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
    include jdk.disabled.namedCurves

After:

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

which is also discussed in this SO post: SSLHandShakeException No Appropriate Protocol . In that thread there are also more answers popping up the last few days since the updated JDK version.

After this update of the JDK, we received the error

java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.

with c3p0.

After switching to hikari we got a more meaningful error:

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)

We're running on MySQL 5.7.33-0ubuntu0.18.04.1. Now in my understanding as described here, MySQL 5.7 supports TLSv1.2. Also when running SHOW VARIABLES LIKE 'tls_version'; we get TLSv1,TLSv1.1,TLSv1.2 which suggest that TLSv1.2 is supported.

So then the question is, why don't the JDK and MySQL just agree on using TLSv1.2 and what can we do about it, to make them communicate with TLSv1.2?

Note: I don't think changing the java.security file as suggested in the other thread is a good long term solution to this problem!

bersling
  • 17,851
  • 9
  • 60
  • 74
  • 1
    And what is the question now? How to make Java accept TLS 1.0 again or how to make MySQL use TLS 1.2? It's not really clear to me. – sticky bit Apr 30 '21 at 11:18
  • thanks for the hint, i rephrased the question to make it more clear. I think the goal should be to use TLSv1.2 as the way forward. – bersling Apr 30 '21 at 11:25
  • 7
    Try adding 'enabledTLSProtocols=TLSv1.2' to MySQL connection string. This will enforce TLSV1.2 protocol for java's mysql connection and you wouldn't have to make any changes to java.security file. – skelwa May 04 '21 at 08:05
  • Since Connector/J 8.0.28 enabledTLSProtocols has been renamed to tlsVersions. See https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-using-ssl.html – Yair Kukielka Feb 04 '22 at 10:52

7 Answers7

124

As @skelwa already commented you will need to add the enabledTLSProtocols=TLSv1.2 configuration property in the connection string to resolve your issue.

A complete connection string for Connector/J could look like this:

jdbc:mysql://<host>:<port>/<dbname>?enabledTLSProtocols=TLSv1.2

For r2dbc you will need to use tlsVersion=TLSv1.2 instead.

For Connector/J v8.0.28 enabledTLSProtocols was renamed to tlsVersions (see note). However, the original name remains as an alias.


The question that remains is:

Why don't the JDK and MySQL just agree on using TLSv1.2?

Although both parties do actually support TLSv1.2, the problem you were experiencing is introduced by the default behavior of Connector/J. For compatibility reasons Connector/J does not enable TLSv1.2 and higher by default. Therefore, one has to enable it explicitly.

See the following note:

For Connector/J 8.0.18 and earlier when connecting to MySQL Community Server 5.6 and 5.7 using the JDBC API: Due to compatibility issues with MySQL Server compiled with yaSSL, Connector/J does not enable connections with TLSv1.2 and higher by default. When connecting to servers that restrict connections to use those higher TLS versions, enable them explicitly by setting the Connector/J connection property enabledTLSProtocols (e.g., set enabledTLSProtocols=TLSv1,TLSv1.1,TLSv1.2).


WARNING: please be aware that solutions suggesting editing jdk.tls.disabledAlgorithms inside of jre/lib/security pose a security risk to your application and changing anything there might have severe implications! There are reasons why those protocols were disabled and one should not simply remove everything or even just parts from that list.


Note: if you want to get more low level insights from the JDK to debug your problem you can enable ssl debug logs by passing the following configuration to the java comand:

-Djavax.net.debug=ssl,handshake or even -Djavax.net.debug=all

In your case you will see something like:

...(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)
    ...
Kristianmitk
  • 4,528
  • 5
  • 26
  • 46
  • thank you for the recommendation. just wanted to add to also try using the *latest recommended mysql connector j* for the software you're using. We were testing with mysql connector 5.1.42, so I just tried to use 5.1.48 and enabling TLS v1.2 in the jdbc url and it worked! Also used java options `-Djdk.tls.client.protocols=TLSv1.2,TLSv1.3` and in tomcat server.xml `sslProtocol="TLS" sslEnabledProtocols="TLSv1.2,TLSv1.3"`. Make sure you also read the mysql notes here: https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-using-ssl.html – Savvas Radevic Mar 29 '22 at 08:12
  • Just a notice, this works even for IntelliJ that was not able to connect to several mysql... unless i added the "?enabledTLSProtocols=TLSv1.2" – Kendar Feb 14 '23 at 16:51
21

I just added useSSL=false and it worked for me.

jdbc:mysql://<host>:<port>/<dbname>?useSSL=false

I have JDK 8, MySQL 5.7 and mysql-connector-java lib with version 5.1.38

This is useful when you want to execute quickly in local environment only (not recommended for staging/test/prod)

Ankur Raiyani
  • 1,509
  • 5
  • 21
  • 49
  • 3
    In a DMZ it might be ok to have no encryption instead of weak encryption. In Production it usually is not ok. – Grim Sep 02 '21 at 07:34
  • 2
    Question title: "how should it be fixed? (ssl.SSLHandshakeException: No appropriate protocol)" Your answer: Disable SSL – Joshua Schlichting Sep 07 '21 at 14:49
  • 2
    This solved for me. I only used this option because I'm on local development environment. – Vinicius Oct 14 '21 at 21:42
  • 1
    What advantage does `useSSL=false` provide over `enabledTLSProtocols=TLSv1.2` (accepted answer)? I don't see a benefit, while it makes it insecure as a downside? – bersling Apr 14 '22 at 11:21
4

I came here because I had the same issue, but unfortunately,

jdbc:mysql://host:port/dbname?enabledTLSProtocols=TLSv1.2

didn't work for me because I'm using r2dbc. After a little bit of debugging I found out the name of the parameter must be tlsVersion instead, so you can use, for example:

spring.r2dbc.url=r2dbc:mysql://host:port/dname?tlsVersion=TLSv1.2
Marcus
  • 617
  • 3
  • 8
  • This is also how it works after Connector/J 8.0.28, enabledTLSProtocols has been renamed to tlsVersions. See https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-using-ssl.html – Yair Kukielka Feb 04 '22 at 10:50
4

I faced this issue due to the older version of mysql-connector-java-5.1.40-bin.jar & OpenJDK 1.8 version, After Upgrading to the 5.1.49 version solved my issue

Rahul Sawant
  • 1,223
  • 9
  • 12
1

This is not a StreamSets issue. This is a compatibility issue between Java and the MySQL JDBC driver

Choose the most appropriate solution from below for your situation Solution #1: Add "enabledTLSProtocols=TLSv1.2" to JDBC connection string Verify MySQL supports TLSv1.2

mysql> show variables like 'tls_version';
+---------------+---------------------+
| Variable_name | Value |
+---------------+---------------------+
| tls_version | TLSv1,TLSv1.1,TLSv1.2 |
+---------------+---------------------+
1 row in set (0.00 sec)

Update JDBC connection string

jdbc:mysql://[hostname]:[port]/[databaseName]?enabledTLSProtocols=TLSv1.2

Solution #2: Enable TLSv1 and TLSv1.1 File: $JAVA_HOME/jre/lib/security/java.security Old configuration: jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA,
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL New configuration: jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024,
EC keySize < 224, 3DES_EDE_CBC, anon, NULL

Solution #3: Upgrade the MySQL database The TLS version is automatically selected by the JDBC driver depending on the database version.

TLSv1 and TLSv1.1 will be used for versions below: 8.0, 5.7.28, 5.6.46

Additional Information A recent Java update, specifically Red Hat/CentOS, disables TLSv1 and TLSv1.1 by default for Java 8

The MySQL JDBC driver will attempt to use TLSv1 and/or TLSv1.1 if the MySQL database version is below one of the following: 8.0, 5.7.28, 5.6.46

Linus
  • 880
  • 13
  • 25
0

If possible, the better solution should be to upgrade to one of the following releases of Connector/J:

  • 8.0.19, released on 2020-01-13, the release notes for which say:

The allowable versions of TLS protocol used for connecting to the server, when no restrictions have been set using the connection properties enabledTLSProtocols, have been changed to:

  • TLSv1, TLSv1.1, TLSv1.2, and TLSv1.3 for MySQL Community Servers 8.0, 5.7.28 and later, and 5.6.46 and later, and for all commercial versions of MySQL Servers.
  • TLSv1 and TLSv1.1 for all other versions of MySQL Servers.

or

The allowable versions of TLS protocol used for connecting to the server, when no restrictions have been set using the connection properties enabledTLSProtocols, have been changed to:

  • TLSv1, TLSv1.1, and TLSv1.2 for MySQL Community Servers 8.0, 5.7.28 and later, and 5.6.46 and later, and for commercial versions of MySQL Server 5.6, 5.7, and 8.0.
  • TLSv1 and TLSv1.1 for all other versions of MySQL Servers.

If that's not possible, you could consider upgrading your MySQL servers to 8.0.x, which some older versions of Connector/J will use TLSv1.2 to where they won't enable it when connecting to 5.7.x.

If you can't upgrade either (yet), then changing enabledTLSProtocols would obviously be necessary.

-7

You can do the following steps:

  1. Open java.security file. (It is under jre/lib/security folder)
  2. Find the following line : jdk.tls.disabledAlgorithms
  3. Comment that complete line.

After this try running and it should work.

Or if you want only specific algorithm remove it from disabled list.

You can send it in config and comment that in java.security file

jdbc:mysql://<host>:<port>/<dbname>?enabledTLSProtocols=TLSv1.2
Vayuj Rajan
  • 85
  • 1
  • 2
  • 9
    Commenting out "jdk.tls.disabledAlgorithms" is catastrophically bad advice... It's a bit like saying: the fastest way to get to work in the morning is to leave your car doors unlocked and the keys in the ignition. Selectively removing items is only slightly less bad... – paulsm4 Jul 01 '21 at 18:51
  • @paulsm4 that is true and not encouraged outside the local dev environment. – Vayuj Rajan Jul 05 '21 at 19:37
  • 2
    Remember: things you do in a dev environment often have a nasty habit of inadvertently leaking out to your upstream environments. Best advice: "Just Say No" ;) – paulsm4 Jul 05 '21 at 19:58