与 SSL 的 mysql jdbc 连接在 tls 握手级别失败

Posted

技术标签:

【中文标题】与 SSL 的 mysql jdbc 连接在 tls 握手级别失败【英文标题】:mysql jdbc connection with SSL fails at tls handshake level 【发布时间】:2019-08-03 09:57:05 【问题描述】:

我们的 mysql 服务器配置为仅接受与 ssl 密码 DHE-RSA-AES256-GCM-SHA384 的连接。

我正在使用 java mysql-connector-java (8.0.15) 和 java 8 (openjdk 版本 "1.8.0_191" OpenJDK 运行时环境(build 1.8.0_191-8u191-b12-2ubuntu0.16.04.1-b12)

当我使用以下程序列出可用密码时,我得到 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 密码可用。

下面是列出可用密码的程序 https://confluence.atlassian.com/stashkb/files/679609085/679772359/1/1414093373406/Ciphers.java

但是当我在 ssl 上启用调试模式时,我得到 忽略不受支持的密码套件:TLS_DHE_RSA_WITH_AES_256_GCM_SHA384。

并带有以下消息

即将握手状态:server_hello[2]

*** 客户端你好,TLSv1.1 RandomCookie: GMT: 1535642319 字节 = 168, 0, 213, 212, 68, 19, 189, 131, 12, 147, 76, 108, 65, 77, 56, 170, 35, 147, 119, 196, 102, 161、241、133、49、97、153、200 会话 ID: 密码套件:[TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,TLS_DHE_DSS_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 压缩方式:0

这里当服务器使用 TLSv1.2 时,客户端开始通过 TLSv1.1 进行通信

我还注意到 ExportControlled.java(包 com.mysql.cj.protocol;)将 SSLContext 创建为(第 563 行)

try
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kms, tms.toArray(new TrustManager[tms.size()]), null);
        return sslContext;

    

请帮助我了解为什么忽略可用密码以及我应该如何连接到服务器

【问题讨论】:

【参考方案1】:

很简单,我只需要在 jdbc url 中添加 enabledTLSProtocols 参数即可

例如:-

jdbc:mysql://<hostname>:3115/<schema>?enabledTLSProtocols=TLSv1.2

【讨论】:

对,在Connector/J中默认不启用TLSv1.2,如文档中所述:dev.mysql.com/doc/connector-j/8.0/en/…这里还有一些关于TLS支持的说明:dev.mysql.com/doc/connector-j/8.0/en/…【参考方案2】:

我得到了这个工作,我必须在 SSL 模式下使用 mysql-connector-java-8.0.26.jar 在连接属性中设置和启用 TLS 协议版本。 props.setProperty("enabledTLSProtocols", "TLSv1.2")

Properties props = new Properties();
props.setProperty("user", USER_SSL);
props.setProperty("password", PASS_SSL);
props.setProperty("useSSL", "true");
props.setProperty("requireSSL", "true");
props.setProperty("verifyServerCertificate", "true");
props.setProperty("sslMode", "VERIFY_CA");
props.setProperty("javax.net.debug", "all");
props.setProperty("enabledTLSProtocols", "TLSv1.2");
props.setProperty("zeroDateTimeBehavior", "convertToNull");

// Setting the truststore
props.setProperty("trustCertificateKeyStoreUrl", TRUST_STORE_URL);
props.setProperty("trustCertificateKeyStorePassword", TRUST_STORE_PASSWORD);

// Setting the keystore
props.setProperty("clientCertificateKeyStoreUrl", KEYSTORE_URL);
props.setProperty("clientCertificateKeyStorePassword", KEYSTORE_PASSWORD);
try 
conn = DriverManager.getConnection(DB_URL, props);
 catch (Exception ex) 

Logger.debug(ex);

【讨论】:

以上是关于与 SSL 的 mysql jdbc 连接在 tls 握手级别失败的主要内容,如果未能解决你的问题,请参考以下文章

JDBC SSL连接MySQL

尝试通过 JDBC 与 Postgres 建立 SSL 连接时出现 PSQLException“无法打开 SSL 根证书文件”

jdbc连接mysql时发出警告:WARN: Establishing SSL connection without server's identity verification is not

我与数据库的 JDBC 连接是不是使用 SSL?

JDBC SSL连接SQL Server

在 context.xml 中指定用于 jdbc 的 SSL