SSL连接RDS MySQL数据库

本文介绍配置了SSL链路加密后,如何通过MySQL命令行终端以及JDBC连接数据库。

前提条件

操作步骤

使用云端证书连接MySQL

开启SSL加密后,客户端和RDS MySQL之间的连接是否加密与客户端的类型和设置有关。例如,客户端可能默认采用加密连接。您可以修改客户端的设置或代码,要求建立加密连接以及验证RDS MySQL的身份。

命令行

对于MySQL 5.7.11及以后版本的客户端,在连接命令中添加--ssl-mode选项可以设置SSL加密。

说明

对于MariaDB客户端以及MySQL 5.7.11之前的客户端,请使用--ssl和--ssl-verify-server-cert等选项。具体请参见MariaDB和MySQL官方文档。

  • --ssl-mode=DISABLED表示连接不加密。

  • --ssl-mode=PREFERRED或者不添加--ssl-mode选项,表示尝试加密连接,如果无法加密则采用非加密连接。

  • --ssl-mode=REQUIRED,表示必须加密连接,如果无法加密则连接失败。

  • --ssl-mode=VERIFY_CA,表示必须加密连接,并用本地的CA证书验证服务器证书是否有效。

  • --ssl-mode=VERIFY_IDENTITY,表示必须加密连接,并用本地的CA证书验证服务器证书是否有效,并验证服务器证书的主机名或IP地址是否与实际连接的主机名或IP地址匹配。

示例一:尝试加密连接,如果无法加密则采用非加密连接。

mysql -h {RDS连接地址} -u {RDS账号} -p --ssl-mode=PREFERRED

示例二:要求加密连接,并验证服务器证书的有效性。

mysql -h {RDS连接地址} -u {RDS账号} -p --ssl-mode=VERIFY_CA --ssl-ca={CA证书路径}/ApsaraDB-CA-Chain.pem
说明
  • 上述示例里的{RDS连接地址}、{RDS账号}和{CA证书路径}需替换为实际的值。

  • 更多关于--ssl-mode选项的说明,请参见MySQL官方文档。

MySQL Workbench

  1. 打开MySQL Workbench,选择Database > Manage Connections

  2. 填写RDS连接地址和账号密码。

  3. SSL页签下,设置Use SSL参数,指定SSL CA File为下载的PEM格式CA证书,然后单击Test Connection或者OK

    说明

    关于Use SSL参数的选项,可以参考命令行连接方式的--ssl-mode说明。

DMS

在DMS中录入RDS MySQL实例时,可设置开启SSL参数。具体操作,请参见云数据库录入

也可以在已录入的实例上右键,选择编辑实例,然后在高级信息中设置。

应用程序代码

Java

Connector/J(mysql-connector-java)是MySQL官方提供的JDBC驱动程序。本示例使用mysql-connector-java 8.0.19版本作为依赖。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.19</version>
</dependency>
说明

以下示例代码使用sslMode属性指定SSL模式。mysql-connector-java从8.0.13版本开始支持该属性,如果您使用更早的版本,则需要改为使用useSSL、requireSSL和verifyServerCertificate属性,具体请参见MySQL文档

示例代码:

package com.aliyun.sample;

import com.mysql.cj.jdbc.MysqlDataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class Sample {

    public static void main(String[] args) {

        Connection conn = null;
        MysqlDataSource mysqlDS=null;

        try{
            mysqlDS = new MysqlDataSource();
            //可按需设置SslMode。关于该属性的选项,请参见命令行连接方式的说明。
            mysqlDS.setSslMode("VERIFY_IDENTITY");
          
            //truststore用于存储CA证书,这里设置truststore类型为JKS。
            mysqlDS.setTrustCertificateKeyStoreType("JKS");
            // 请将file:/后面的路径改为您的ApsaraDB-CA-Chain.jks文件的路径。
            mysqlDS.setTrustCertificateKeyStoreUrl("file:/D:\\ApsaraDB-CA-Chain\\ApsaraDB-CA-Chain.jks");
            // 下载的JKS文件的密码为apsaradb,不能修改。
            mysqlDS.setTrustCertificateKeyStorePassword("apsaradb");
          
            // 您的数据库连接串
            mysqlDS.setServerName("rm-xxxxxx.mysql.rds.aliyuncs.com");
            // 您的数据库端口
            mysqlDS.setPort(3306);
            // 您的数据库账号
            mysqlDS.setUser("xxxxxx");
            // 您的数据库密码
            mysqlDS.setPassword("xxxxxx");
            // 您的数据库名
            mysqlDS.setDatabaseName("xxxxxx");

            conn = mysqlDS.getConnection();

        }catch(Exception e){
            e.printStackTrace();
        } finally {
            try {
                if (conn != null)
                    conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

Python

# 安装pymysql    pip install pymysql

import pymysql

try:
    ssl_config = {"ca":"/path/to/path/ca.crt", "mode":"VERIFY_CA"}   # ca为证书的路径,mode为ssl-mode
    conn = pymysql.connect(host='******.mysql.rds.aliyuncs.com', user='*****', passwd='******', db='*****', ssl=ssl_config)
    cursor = conn.cursor()
    cursor.execute('select version()')
    data = cursor.fetchone()
    print('Database version:', data[0])
    cursor.close()
except pymysql.Error as e:
    print(e)

使用自定义证书连接MySQL

命令行

对于MySQL 5.7.11及以后版本的客户端,在连接命令中添加--ssl-mode选项可以设置SSL加密。

说明

对于MariaDB客户端以及MySQL 5.7.11之前的客户端,请使用--ssl和--ssl-verify-server-cert等选项。具体请参见MariaDB和MySQL官方文档。

  • --ssl-mode=DISABLED表示连接不加密。

  • --ssl-mode=PREFERRED或者不添加--ssl-mode选项,表示尝试加密连接,如果无法加密则采用非加密连接。

  • --ssl-mode=REQUIRED,表示必须加密连接,如果无法加密则连接失败。

  • --ssl-mode=VERIFY_CA,表示必须加密连接,并用本地的CA证书验证服务器证书是否有效。

  • --ssl-mode=VERIFY_IDENTITY,表示必须加密连接,并用本地的CA证书验证服务器证书是否有效,并验证服务器证书的主机名或IP地址是否与实际连接的主机名或IP地址匹配。

示例:

  1. 尝试加密连接,如果无法加密则采用非加密连接。

    mysql -h {RDS连接地址} -u {RDS账号} -p --ssl-mode=PREFERRED
  2. 要求加密连接,并验证服务器证书的有效性。

    mysql -h {RDS连接地址} -u {RDS账号} -p --ssl-mode=VERIFY_CA --ssl-ca={自定义CA证书路径}
说明
  • 上述示例里的{RDS连接地址}{RDS账号}{CA证书路径}{自定义CA证书路径}需替换为实际的值。

  • 更多关于--ssl-mode选项的说明,请参见MySQL官方文档

MySQL Workbench

  1. 打开MySQL Workbench,选择Database > Manage Connections

  2. 填写RDS连接地址和账号密码。

  3. SSL页签下,设置Use SSL参数,如果为云端证书则指定SSL CA File为下载的PEM格式CA证书,如果配置的为自定义证书则指定SSL CA File为自定义的CA证书,然后单击Test Connection或者OK

说明

关于Use SSL参数的选项,可以参考命令行连接方式的--ssl-mode说明。

DMS

在DMS中录入RDS MySQL实例时,可设置开启SSL参数。具体操作,请参见云数据库录入

也可以在已录入的实例上右键,选择编辑实例,然后在高级信息中设置。

应用程序代码

Java

Connector/J(mysql-connector-java)是MySQL官方提供的JDBC驱动程序。本示例使用mysql-connector-java 8.0.19版本作为依赖。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.19</version>
</dependency>
重要

配置为自定义证书,需要手动生成JKS文件,具体步骤如下:

  1. 将你的客户端证书和私钥转换成PKCS#12格式,因为keytool不直接支持从PEM格式导入私钥和证书。使用OpenSSL做这个转换:

    openssl pkcs12 -export -in {自定义CA证书} -inkey {自定义CA证书私钥} -out keystore.p12 -name ganyang -CAfile {自定义CA证书}
    # 需要输入密码,连接时需要使用
    Enter Encryption Password:
    Verifying - Enter Encryption Password:
  2. 使用keytool导入刚才创建的PKCS#12文件到新的JKS文件):

    keytool -importkeystore -deststorepass JKS-password -destkeypass key-password -destkeystore keystore.jks -deststoretype pkcs12 -srckeystore keystore.p12 -srcstoretype pkcs12 -srcstorepass P12-password -alias your-alias

    关键词解释:

    -deststorepass 为JKS文件设置的密码。
    -destkeypass 为JKS文件里的密钥设置的密码。
    -destkeystore 想要创建或已有的JKS文件。
    -deststoretype 想要创建文件的类型是PKCS#12。
    -srckeystore 之前生成的PKCS#12文件。
    -srcstoretype 表明源文件的类型是PKCS#12。
    -srcstorepass 保护PKCS#12文件的密码。
    -alias 用户给的客户端证书和私钥设置的别名。
  3. 获取创建的JKS文:在keytool成功导入后可在执行目录下找到keystore.jks。

说明

以下示例代码使用sslMode属性指定SSL模式。mysql-connector-java从8.0.13版本开始支持该属性,如果您使用更早的版本,则需要改为使用useSSL、requireSSL和verifyServerCertificate属性,具体请参见MySQL文档

package com.aliyun.sample;

import com.mysql.cj.jdbc.MysqlDataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class Sample {

    public static void main(String[] args) {

        Connection conn = null;
        MysqlDataSource mysqlDS=null;

        try{
            mysqlDS = new MysqlDataSource();
            //可按需设置SslMode。关于该属性的选项,请参见命令行连接方式的说明。
            mysqlDS.setSslMode("VERIFY_IDENTITY");

            //以下为云端证书的JKS实现方式,如果MySQL配置为自定义证书,替换为通过自定义证书生成的JKS文件路径和对应密码即可
            //truststore用于存储CA证书,这里设置truststore类型为JKS。
            mysqlDS.setTrustCertificateKeyStoreType("JKS");
            // 请将file:/后面的路径改为您的ApsaraDB-CA-Chain.jks文件的路径
            mysqlDS.setTrustCertificateKeyStoreUrl("file:/D:\\ApsaraDB-CA-Chain\\ApsaraDB-CA-Chain.jks");
            // 下载的JKS文件的密码为apsaradb,不能修改。
            mysqlDS.setTrustCertificateKeyStorePassword("apsaradb");
          
            // 您的数据库连接串
            mysqlDS.setServerName("rm-xxxxxx.mysql.rds.aliyuncs.com");
            // 您的数据库端口
            mysqlDS.setPort(3306);
            // 您的数据库账号
            mysqlDS.setUser("xxxxxx");
            // 您的数据库密码
            mysqlDS.setPassword("xxxxxx");
            // 您的数据库名
            mysqlDS.setDatabaseName("xxxxxx");

            conn = mysqlDS.getConnection();

        }catch(Exception e){
            e.printStackTrace();
        } finally {
            try {
                if (conn != null)
                    conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}
Python
# 安装pymysql    pip install pymysql

import pymysql

try:
    ssl_config = {"ca":"/path/to/path/ca.crt", "mode":"VERIFY_CA"}   # ca为证书的路径,mode为ssl-mode
    conn = pymysql.connect(host='******.mysql.rds.aliyuncs.com', user='*****', passwd='******', db='*****', ssl=ssl_config)
    cursor = conn.cursor()
    cursor.execute('select version()')
    data = cursor.fetchone()
    print('Database version:', data[0])
    cursor.close()
except pymysql.Error as e:
    print(e)