使用 Java 建立到 MySQL Amazon RDS (SSL/TLS) 的安全连接 [英] Using Java to establish a secure connection to MySQL Amazon RDS (SSL/TLS)

查看:105
本文介绍了使用 Java 建立到 MySQL Amazon RDS (SSL/TLS) 的安全连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 JDK 1.8 和 MySQL Connector/J 版本 5.1.23 安全地连接到 Amazon RDS,但我对 MySQL Connector/J 文档.

说明说在当前目录中创建一个信任库并导入服务器的 CA 证书.当我运行以下命令时,我被要求输入密码,但我不知道该输入什么:

keytool -import -alias mysqlServerCACert -file file_location.pem -keystore truststore

来自亚马逊的说明另一方面指出证书是由证书颁发机构签署的.SSL 证书包括数据库实例终端节点作为通用名称 (CN).公钥也存储在 http://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem.

虽然我了解 SSL/TSL 和私钥/公钥的概念,但我对如何实现这一点感到困惑?

当我运行 SHOW VARIABLES LIKE 'have_ssl'; 命令时,我收到是"作为值.当我连接到数据库并运行 SHOW SESSION STATUS LIKE 'Ssl_version'; 时,我没有收到任何值.

如何建立从 Java 到 MySQL 数据库的安全连接?

更新:我使用的是 ubuntu,我使用 keytool 在 JRE 目录 /usr/lib/jvm/java/jre/ 中生成了一个 truststore.jks 文件.我还执行了以下命令:GRANT USAGE ON db_name.* To 'username'@'address' REQUIRE SSL;

下面的代码是我连接到数据库的方式:

import com.mysql.jdbc.Connection;公共类 mainClass{公共静态无效主(字符串 [] args){System.setProperty("javax.net.ssl.trustStore", "/usr/lib/jvm/java/jre/truststore.jks");System.setProperty("javax.net.ssl.trustStorePassword", "truststore_password");最终字符串 url = "jdbc:mysql://mysql_rds_enpoint:port/db_name?verifyServerCertificate=true&useSSL=true&requireSSL=true";最终字符串用户名 = "用户名";最终字符串密码 = "密码";连接 mysqlConnection = null;mysqlConnection = (Connection) mysqlMethods.connectToMysql(url, username, password);}}

上面的代码产生一个Communications link failure 消息和从服务器成功接收的最后一个数据包是 24 毫秒前.最后一个成功发送到服务器的数据包是 24 毫秒前.当 ?verifyServerCertificate=true&useSSL=true&requireSSL=true 从 uri 中删除并且 REQUIRE SSL 从用户权限中删除时,我能够成功连接.>

更新 2:当我运行以下代码时,我已经将代码带回了基础:

import java.sql.DriverManager;导入 java.sql.SQLException;类测试类{公共静态无效主(字符串 [] args){System.setProperty("javax.net.ssl.trustStore", "/usr/lib/jvm/java/jre/truststore.jks");System.setProperty("javax.net.ssl.trustStorePassword", "truststore_password");最终字符串 url = "jdbc:mysql://mysql_rds_enpoint:port/db_name?verifyServerCertificate=true&useSSL=true&requireSSL=true";最终字符串用户名 = "用户名";最终字符串密码 = "密码";尝试 {Object connection = DriverManager.getConnection(url, username, password);} catch (SQLException e) {e.printStackTrace();}}}

我收到以下错误消息:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:通信链接失败从服务器成功接收的最后一个数据包是 206 毫秒前.最后一个成功发送到服务器的数据包是在 203 毫秒前.在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)在 java.lang.reflect.Constructor.newInstance(Constructor.java:422)在 com.mysql.jdbc.Util.handleNewInstance(Util.java:389)在 com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1038)在 com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:110)在 com.mysql.jdbc.MysqlIO.negotiateSSLConnection(MysqlIO.java:4760)在 com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1629)在 com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1206)在 com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2239)在 com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2270)在 com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2069)在 com.mysql.jdbc.ConnectionImpl.(ConnectionImpl.java:794)在 com.mysql.jdbc.JDBC4Connection.(JDBC4Connection.java:44)在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)在 java.lang.reflect.Constructor.newInstance(Constructor.java:422)在 com.mysql.jdbc.Util.handleNewInstance(Util.java:389)在 com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:399)在 com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:325)在 java.sql.DriverManager.getConnection(DriverManager.java:664)在 java.sql.DriverManager.getConnection(DriverManager.java:247)在 apples.main(mainClass.java:18)引起:javax.net.ssl.SSLException:java.lang.RuntimeException:意外错误:java.security.InvalidAlgorithmParameterException:trustAnchors 参数必须非空在 sun.security.ssl.Alerts.getSSLException(Alerts.java:208)在 sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)在 sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1906)在 sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1889)在 sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1410)在 sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)在 com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:95)……还有 18 个引起:java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty在 sun.security.validator.PKIXValidator.(PKIXValidator.java:90)在 sun.security.validator.Validator.getInstance(Validator.java:179)在 sun.security.ssl.X509TrustManagerImpl.getValidator(X509TrustManagerImpl.java:312)在 sun.security.ssl.X509TrustManagerImpl.checkTrustedInit(X509TrustManagerImpl.java:171)在 sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:184)在 sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)在 sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1488)在 sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)在 sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)在 sun.security.ssl.Handshaker.process_record(Handshaker.java:914)在 sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)在 sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)在 sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)……还有 20 个引起:java.security.InvalidAlgorithmParameterException:trustAnchors 参数必须非空在 java.security.cert.PKIXParameters.setTrustAnchors(PKIXParameters.java:200)在 java.security.cert.PKIXParameters.(PKIXParameters.java:120)在 java.security.cert.PKIXBuilderParameters.(PKIXBuilderParameters.java:104)在 sun.security.validator.PKIXValidator.(PKIXValidator.java:88)... 32 更多

我还使用 Workbench 和 .pem 文件确认用户可以使用 SSL 登录.

更新 3: 将 javax.net.debug 设置为 ssl 后的调试信息:

keyStore 是:keyStore 类型是:jks密钥库提供程序是:初始化密钥库SunX509 类型的初始化密钥管理器trustStore 是:/usr/lib/jvm/java/jre/truststore.jkstrustStore 类型是:jkstrustStore 提供者是:初始化信任库添加为受信任的证书:主题:CN=aws.amazon.com/rds/,OU=RDS,O=Amazon.com,L=西雅图,ST=华盛顿,C=美国发行人:CN=aws.amazon.com/rds/,OU=RDS,O=Amazon.com,L=西雅图,ST=华盛顿,C=US算法:RSA;序列号:0xe775b657e21a8128有效期从 2010 年 4 月 06 日星期二 08:44:31 AEST 到 2015 年 4 月 5 日星期日 08:44:31 AEST触发 SecureRandom 的播种完成播种 SecureRandom忽略不可用的密码套件:TLS_DHE_DSS_WITH_AES_256_GCM_SHA384忽略不可用的密码套件:TLS_RSA_WITH_AES_256_CBC_SHA忽略不可用的密码套件:TLS_DHE_RSA_WITH_AES_256_GCM_SHA384忽略不可用的密码套件:TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA忽略不可用的密码套件:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384忽略不可用的密码套件:TLS_RSA_WITH_AES_256_CBC_SHA256忽略不可用的密码套件:TLS_DHE_DSS_WITH_AES_256_CBC_SHA忽略不可用的密码套件:TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384忽略不可用的密码套件:TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384忽略不可用的密码套件:TLS_RSA_WITH_AES_256_GCM_SHA384忽略不可用的密码套件:TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384忽略不可用的密码套件:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384忽略不可用的密码套件:TLS_ECDH_RSA_WITH_AES_256_CBC_SHA忽略不可用的密码套件:TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384忽略不可用的密码套件:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384忽略不可用的密码套件:TLS_DHE_RSA_WITH_AES_256_CBC_SHA256忽略不可用的密码套件:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA忽略不可用的密码套件:TLS_DHE_DSS_WITH_AES_256_CBC_SHA256忽略不可用的密码套件:TLS_DHE_RSA_WITH_AES_256_CBC_SHA忽略不可用的密码套件:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA忽略不可用的密码套件:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384允许不安全的重新协商:false允许旧的 hello 消息:true是否初始握手:真是否安全重新协商:false忽略不支持的密码套件:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1忽略不支持的密码套件:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1忽略不支持的密码套件:TLSv1 的 TLS_RSA_WITH_AES_128_CBC_SHA256忽略不支持的密码套件:TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1忽略不支持的密码套件:TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 for TLSv1忽略不支持的密码套件:TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1忽略不支持的密码套件:TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 for TLSv1忽略不支持的密码套件:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256忽略不支持的密码套件:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256忽略不支持的密码套件:TLS_RSA_WITH_AES_128_CBC_SHA256忽略不支持的密码套件:TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256忽略不支持的密码套件:TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256忽略不支持的密码套件:TLS_DHE_RSA_WITH_AES_128_CBC_SHA256忽略不支持的密码套件:TLS_DHE_DSS_WITH_AES_128_CBC_SHA256忽略不支持的密码套件:TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256忽略不支持的密码套件:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256忽略不支持的密码套件:TLS_RSA_WITH_AES_128_GCM_SHA256忽略不支持的密码套件:TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256忽略不支持的密码套件:TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256忽略不支持的密码套件:TLS_DHE_RSA_WITH_AES_128_GCM_SHA256忽略不支持的密码套件:TLS_DHE_DSS_WITH_AES_128_GCM_SHA256%% 没有缓存的客户端会话*** 客户你好,TLSv1RandomCookie: GMT: 1425012760 字节 = { 250, 182, 202, 168, 139, 248, 125, 121, 251, 188, 182, 110, 1, 234, 29, 5,102557, 87, 80, 44, 141, 121, 154 }会话 ID:{}密码套件:[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_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,TLS_EMPTY_RENEGOTIATION_INFO_SCSV]压缩方法:{0}扩展elliptic_curves,曲线名称:{secp256r1,sect163k1,sect163r2,secp192r1,secp224r1,sect233k1,sect233r1,sect283k1,sect283r1,secp384r1,sect409k1,sect409r1,secp521r1,sect571k1,sect571r1,secp160k1,secp160r1,secp160r2,sect163r1,secp192k1,sect193r1,sect193r2, secp224k1, secp239k1, secp256k1}扩展 ec_point_formats,格式:[未压缩]扩展 server_name, server_name: [type=host_name (0), value=abcd.abcd123.ap-southeast-1.rds.amazonaws.com]***主要,写入:TLSv1 握手,长度 = 202主要,阅读:TLSv1 握手,长度 = 74*** 服务器你好,TLSv1RandomCookie: GMT: -1571637097 字节 = { 78, 228, 80, 30, 162, 233, 208, 59, 196, 166, 88, 129, 155, 99, 123, 252,512134, 235, 185, 112, 68, 79, 2, 79 }会话 ID:{104、7、155、31、238、102、222、218、193、219、108、206、57、235、53、253、1、200、64、46、3、6、9251, 142, 106, 233, 54, 27, 110, 79, 128}密码套件:TLS_RSA_WITH_AES_128_CBC_SHA压缩方式:0***警告:ServerHello 中没有重新协商指示扩展%% 初始化:[Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]** TLS_RSA_WITH_AES_128_CBC_SHA主要,阅读:TLSv1 握手,长度 = 1057*** 证书链链 [0] = [[版本:V3主题:C=US, ST=Washington, L=Seattle, O=Amazon.com, OU=RDS, CN=sifrmedium.cove4uttgoa2.ap-southeast-2.rds.amazonaws.com签名算法:SHA1withRSA,OID = 1.2.840.113549.1.1.5密钥:Sun RSA 公钥,1024 位模量:7182371456073335432842458631460148573771628715802835656528548198324749485547005738326606223242830258829871966755842342342342344059076665280539770508892924695580383343581127930380098999434723444448883595421930164673020286553920728427公共指数:65537有效期:[来自:Sun Jun 21 11:55:57 AEST 2015,至:2020 年 3 月 6 日星期五 09:03:24 AEDT]发行人:CN=Amazon RDS ap-southeast-2 CA,OU=Amazon RDS,O="Amazon Web Services, Inc.",L=西雅图,ST=华盛顿,C=US序列号:[810c7b2c 621bcf07 366cad3b ab405b]证书扩展:2[1]: ObjectId: 2.5.29.35 Criticality=false权限密钥标识符 [密钥标识符 [0000: 89 50 9D 8D 0A 1D 42 A7 D6 36 2E 99 27 44 61 FC .P..6..'Ia.0010: 23 FC D7 F0 #...][CN=Amazon RDS 根 CA,OU=Amazon RDS,O="Amazon Web Services, Inc.",L=西雅图,ST=华盛顿,C=美国]序列号:[46]][2]:ObjectId:2.5.29.14 Criticality=false主题键标识符 [密钥标识符 [0000: 0C 5C 64 D5 CE C4 27 13 34 01 A0 0D 64 8C B1 C9 .d...'.4...d<..0010:4D 6C 3D 16 M=.]]]算法:[SHA1withRSA]签名:0000: 16 53 AA 7A 55 49 84 87 5C EC 49 B9 BD 51 98 83 .S.zUI...I..Q..0010: BA 91 84 72 29 77 19 6C F7 CA 0A 36 09 AC 70 F4 ...r)w.l...6..p.0020: 8A 2C 90 FD 36 3D 3D CD E9 BA 2C 5C 95 C3 79 78 .,..6==...,..yx0030:CE FA 46 A0 3D 77 31 11 E3 5B 9C 84 AF 4D 60 51 ..F.=w1..[...M`Q0040: 80 52 04 1E 65 4D 6E 5B 92 E1 69 79 12 8E 56 0F .R..eMn[..iy..V.0050: 83 E4 F8 31 4E A7 65 4E C2 BB 97 A8 B4 67 79 F4 ...1N.eN ....gy.0060:CD 37 F7 00 A5 42 B9 E0 CB D9 CA 81 EC E3 A3 E3 .7...B........0070: FB 05 40 2F 9A 4B 5D AE 7C 30 F4 BA ED DC 74 AC ..@/.K]..0..t.0080: 89 30 AD 13 26 F7 88 09 66 01 E1 4B 3A 8C B1 3D ..&...f..K:..=0090: 28 6F 74 1D B0 00 25 FB 9B 1E 00 8D F1 1F 83 84 (其他...%.........00A0:CE D7 92 39 78 C4 70 26 8E 3C 05 1C 10 3C A3 E0 ...9x.p&.<...<..00B0:CC 30 F0 A0 68 B1 26 C4 23 AC C0 C6 8A 27 DB 3C .0..h.&.#..'.<00C0: 7F 38 DD EE 92 1B A3 A4 99 13 9F 80 62 66 C8 F0 .8..........bf..00D0: 46 25 38 C3 99 0A A2 A7 04 E5 FF 4D 31 2B E4 82 F%8........M1+..00E0:BE D9 D5 07 28 96 17 07 30 B9 EC BA 26 F3 7B C3 ....(...0...&...00F0:1A CF 13 73 58 96 F2 87 3F FD 86 09 35 FA A3 7B ...sX...?...5...]***%% 无效:[Session-1,TLS_RSA_WITH_AES_128_CBC_SHA]主要,发送 TLSv1 警报:致命,描述 = certificate_unknown主要,写入:TLSv1 警报,长度 = 2主要的,称为 closeSocket()主要,处理异常:javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效认证路径主要,称为 close()主要,称为 closeInternal(true)

解决方案

当您运行以下命令并被要求输入密码时,您应该输入changeit".这是密钥库的默认密码

keytool -import -alias mysqlServerCACert -file file_location.pem -keystore truststore

接下来,确保您使用的 mysql 用户配置为需要 SSL,如下所示

在测试中授予所有特权.* 'root'@'localhost' 需要 SSL;

接下来,确保您从 下载的 rds 包https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem 导入到尝试连接到 AWS RDS 的应用服务器的默认 java cacerts 上.>

最后,您需要将以下三个值为 'true' 的属性附加到您的 mysql url

?verifyServerCertificate=true&useSSL=true&requireSSL=true

例如:

final String url = "jdbc:mysql://mysql_rds_enpoint:port/db_name?verifyServerCertificate=true&useSSL=true&requireSSL=true";

希望这有帮助!

I am trying to securely connect to Amazon RDS using JDK 1.8 and MySQL Connector/J version 5.1.23 and I am confused about the instructions in MySQL Connector/J documentation.

The instructions say to create a truststore in the current directory and import the server's CA certificate. When I run the below command I am asked for a password and I do not know what to enter:

keytool -import -alias mysqlServerCACert -file file_location.pem -keystore truststore

The instructions from Amazon on the other hand point out that certificates are signed by a certificate authority. The SSL certificate includes the DB instance endpoint as the Common Name (CN). The public key is also stored at http://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem.

Whilst I understand the concept of SSL/TSL and private/public keys, I am confused how to implement this?

When I run SHOW VARIABLES LIKE 'have_ssl'; command I receive "yes" as a value. When I am connected to the database and run SHOW SESSION STATUS LIKE 'Ssl_version';, I receive no value back.

How do you establish a secure connection from Java to a MySQL database?

Update: I am using ubuntu and I used the keytool to generate a truststore.jks file in the JRE directory /usr/lib/jvm/java/jre/. I also executed the following command: GRANT USAGE ON db_name.* To 'username'@'address' REQUIRE SSL;

The below code is how I am connecting to the database:

import com.mysql.jdbc.Connection;

public class mainClass{

    public static void main(String[] args){

        System.setProperty("javax.net.ssl.trustStore", "/usr/lib/jvm/java/jre/truststore.jks");
        System.setProperty("javax.net.ssl.trustStorePassword", "truststore_password");

        final String url = "jdbc:mysql://mysql_rds_enpoint:port/db_name?verifyServerCertificate=true&useSSL=true&requireSSL=true";
        final String username = "username";
        final String password = "password";

        Connection mysqlConnection = null;
        mysqlConnection = (Connection) mysqlMethods.connectToMysql(url, username, password);
    }
}

The above code produces a Communications link failure message and The last packet successfully received from the server was 24 milliseconds ago. The last packet sent successfully to the server was 24 milliseconds ago. I am able to successfully connect when ?verifyServerCertificate=true&useSSL=true&requireSSL=true is removed from the uri and REQUIRE SSL is removed from the user permissions.

Update 2: I have taken the code back to basics and when I run the below code:

import java.sql.DriverManager;
import java.sql.SQLException;

class testClass{

    public static void main(String[] args){
        System.setProperty("javax.net.ssl.trustStore", "/usr/lib/jvm/java/jre/truststore.jks");
        System.setProperty("javax.net.ssl.trustStorePassword", "truststore_password");

        final String url = "jdbc:mysql://mysql_rds_enpoint:port/db_name?verifyServerCertificate=true&useSSL=true&requireSSL=true";
        final String username = "username";
        final String password = "password";

        try {
            Object connection = DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

I get the following error message:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 206 milliseconds ago.  The last packet sent successfully to the server was 203 milliseconds ago.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:389)
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1038)
    at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:110)
    at com.mysql.jdbc.MysqlIO.negotiateSSLConnection(MysqlIO.java:4760)
    at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1629)
    at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1206)
    at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2239)
    at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2270)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2069)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:794)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:44)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:389)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:399)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:325)
    at java.sql.DriverManager.getConnection(DriverManager.java:664)
    at java.sql.DriverManager.getConnection(DriverManager.java:247)
    at apples.main(mainClass.java:18)

Caused by: javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1906)
    at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1889)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1410)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
    at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:95)
    ... 18 more

Caused by: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
    at sun.security.validator.PKIXValidator.<init>(PKIXValidator.java:90)
    at sun.security.validator.Validator.getInstance(Validator.java:179)
    at sun.security.ssl.X509TrustManagerImpl.getValidator(X509TrustManagerImpl.java:312)
    at sun.security.ssl.X509TrustManagerImpl.checkTrustedInit(X509TrustManagerImpl.java:171)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:184)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1488)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
    ... 20 more

Caused by: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
    at java.security.cert.PKIXParameters.setTrustAnchors(PKIXParameters.java:200)
    at java.security.cert.PKIXParameters.<init>(PKIXParameters.java:120)
    at java.security.cert.PKIXBuilderParameters.<init>(PKIXBuilderParameters.java:104)
    at sun.security.validator.PKIXValidator.<init>(PKIXValidator.java:88)
    ... 32 more

I have also confirmed using Workbench and the .pem file that the user is able to login using SSL.

Update 3: Debug info after setting javax.net.debug to ssl:

keyStore is : 
keyStore type is : jks
keyStore provider is : 
init keystore
init keymanager of type SunX509
trustStore is: /usr/lib/jvm/java/jre/truststore.jks
trustStore type is : jks
trustStore provider is : 
init truststore
adding as trusted cert:
  Subject: CN=aws.amazon.com/rds/, OU=RDS, O=Amazon.com, L=Seattle, ST=Washington, C=US
  Issuer:  CN=aws.amazon.com/rds/, OU=RDS, O=Amazon.com, L=Seattle, ST=Washington, C=US
  Algorithm: RSA; Serial number: 0xe775b657e21a8128
  Valid from Tue Apr 06 08:44:31 AEST 2010 until Sun Apr 05 08:44:31 AEST 2015

trigger seeding of SecureRandom
done seeding SecureRandom
Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
%% No cached client session
*** ClientHello, TLSv1
RandomCookie:  GMT: 1425012760 bytes = { 250, 182, 202, 168, 139, 248, 125, 121, 251, 188, 182, 110, 1, 234, 29, 105, 158, 219, 212, 122, 105, 57, 87, 80, 44, 141, 121, 154 }
Session ID:  {}
Cipher Suites: [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_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension server_name, server_name: [type=host_name (0), value=abcd.abcd123.ap-southeast-1.rds.amazonaws.com]
***
main, WRITE: TLSv1 Handshake, length = 202
main, READ: TLSv1 Handshake, length = 74
*** ServerHello, TLSv1
RandomCookie:  GMT: -1571637097 bytes = { 78, 228, 80, 30, 162, 233, 208, 59, 196, 166, 88, 129, 155, 99, 123, 252, 123, 153, 129, 25, 144, 235, 185, 112, 68, 79, 2, 79 }
Session ID:  {104, 7, 155, 31, 238, 102, 222, 218, 193, 219, 108, 206, 57, 235, 53, 253, 1, 200, 64, 46, 92, 60, 63, 251, 142, 106, 233, 54, 27, 110, 79, 128}
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA
Compression Method: 0
***
Warning: No renegotiation indication extension in ServerHello
%% Initialized:  [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
** TLS_RSA_WITH_AES_128_CBC_SHA
main, READ: TLSv1 Handshake, length = 1057
*** Certificate chain
chain [0] = [
[
  Version: V3
  Subject: C=US, ST=Washington, L=Seattle, O=Amazon.com, OU=RDS, CN=sifrmedium.cove4uttgoa2.ap-southeast-2.rds.amazonaws.com
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun RSA public key, 1024 bits
  modulus: 7182371456073335432842458631460148573771628715802835656528548198324749485547005738326606223242830258829871966755842342342342344059076665280539770508892924695580383343581127930380098999434723444448883595421930164673020286553920728427
  public exponent: 65537
  Validity: [From: Sun Jun 21 11:55:57 AEST 2015,
               To: Fri Mar 06 09:03:24 AEDT 2020]
  Issuer: CN=Amazon RDS ap-southeast-2 CA, OU=Amazon RDS, O="Amazon Web Services, Inc.", L=Seattle, ST=Washington, C=US
  SerialNumber: [    810c7b2c 621bcf07 366cad3b ab405b]

Certificate Extensions: 2
[1]: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 89 50 9D 8D 0A 1D 42 A7   D6 36 2E 99 27 44 61 FC  .P.......6..'Ia.
0010: 23 FC D7 F0                                        #...
]
[CN=Amazon RDS Root CA, OU=Amazon RDS, O="Amazon Web Services, Inc.", L=Seattle, ST=Washington, C=US]
SerialNumber: [    46]
]

[2]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 0C 5C 64 D5 CE C4 27 13   34 01 A0 0D 64 8C B1 C9  .d...'.4...d<..
0010: 4D 6C 3D 16                                        M=.
]
]

]
  Algorithm: [SHA1withRSA]
  Signature:
0000: 16 53 AA 7A 55 49 84 87   5C EC 49 B9 BD 51 98 83  .S.zUI...I..Q..
0010: BA 91 84 72 29 77 19 6C   F7 CA 0A 36 09 AC 70 F4  ...r)w.l...6..p.
0020: 8A 2C 90 FD 36 3D 3D CD   E9 BA 2C 5C 95 C3 79 78  .,..6==...,..yx
0030: CE FA 46 A0 3D 77 31 11   E3 5B 9C 84 AF 4D 60 51  ..F.=w1..[...M`Q
0040: 80 52 04 1E 65 4D 6E 5B   92 E1 69 79 12 8E 56 0F  .R..eMn[..iy..V.
0050: 83 E4 F8 31 4E A7 65 4E   C2 BB 97 A8 B4 67 79 F4  ...1N.eN.....gy.
0060: CD 37 F7 00 A5 42 B9 E0   CB D9 CA 81 EC E3 A3 E3  .7...B..........
0070: FB 05 40 2F 9A 4B 5D AE   7C 30 F4 BA ED DC 74 AC  ..@/.K]..0....t.
0080: 89 30 AD 13 26 F7 88 09   66 01 E1 4B 3A 8C B1 3D  .0..&...f..K:..=
0090: 28 6F 74 1D B0 00 25 FB   9B 1E 00 8D F1 1F 83 84  (ot...%.........
00A0: CE D7 92 39 78 C4 70 26   8E 3C 05 1C 10 3C A3 E0  ...9x.p&.<...<..
00B0: CC 30 F0 A0 68 B1 26 C4   23 AC C0 C6 8A 27 DB 3C  .0..h.&.#....'.<
00C0: 7F 38 DD EE 92 1B A3 A4   99 13 9F 80 62 66 C8 F0  .8..........bf..
00D0: 46 25 38 C3 99 0A A2 A7   04 E5 FF 4D 31 2B E4 82  F%8........M1+..
00E0: BE D9 D5 07 28 96 17 07   30 B9 EC BA 26 F3 7B C3  ....(...0...&...
00F0: 1A CF 13 73 58 96 F2 87   3F FD 86 09 35 FA A3 7B  ...sX...?...5...

]
***
%% Invalidated:  [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
main, SEND TLSv1 ALERT:  fatal, description = certificate_unknown
main, WRITE: TLSv1 Alert, length = 2
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
main, called close()
main, called closeInternal(true)

解决方案

When you run the below command and are asked for the password you should type "changeit". That is the default password for the keystore

keytool -import -alias mysqlServerCACert -file file_location.pem -keystore truststore

Next, make sure the mysql user you are using is configured to require SSL as below

GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' REQUIRE SSL;

Next, make sure the rds bundle which you downloaded from https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem is imported on the default java cacerts of the app server which is trying to connect to the AWS RDS.

Lastly, you need append the below three properties with value 'true' to your mysql url

?verifyServerCertificate=true&useSSL=true&requireSSL=true

Eg:

final String url = "jdbc:mysql://mysql_rds_enpoint:port/db_name?verifyServerCertificate=true&useSSL=true&requireSSL=true";

Hope this helps!

这篇关于使用 Java 建立到 MySQL Amazon RDS (SSL/TLS) 的安全连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆