作者:蔡玮
中间件dble测试成员,主要负责dble的日常测试工作,热衷于探索发现,学习新技术。
本文来源:原创投稿
SSL协议简介
SSL 之 DBLE 篇
概述
使用说明
证书制作
openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca.pem复制
2、 创建私钥和签发服务端的数字证书
openssl req -newkey rsa:2048 -days 3600 -nodes -keyout server-key.pem -out server-req.pem
openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -req -in server-req.pem -days 3600 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem复制
3、创建私钥和签发客户端的数字证书(与上相似)
openssl req -newkey rsa:2048 -days 3600 -nodes -keyout client-key.pem -out client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -req -in client-req.pem -days 3600 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem复制
4、验证服务端和客户端数字证书是否可信,当输出的结果为OK,表示通过
openssl verify -CAfile ca.pem server-cert.pem client-cert.pem
复制
证书类型转换
1、将 ca.pem 导入 Java 平台的密钥库中,java 支持密钥库类型有:JKS 、JCEKS 、PKCS12 、PKCS11 和 DKS ,这里生成 JKS 扩展名的 truststore.jks 密钥库,密码可自定义,此处定义为123456
keytool -import -noprompt -file ca.pem -keystore truststore.jks -storepass 123456
复制
2、将 server-cert.pem 和 server-key.pem 转成 p12 类型的密钥库,然后在转成 JKS 类型的密钥库,密码可自定义,此处定义为123456
openssl pkcs12 -export -in server-cert.pem -inkey server-key.pem -out serverkeystore.p12 -passout pass:123456
keytool -importkeystore -srckeystore serverkeystore.p12 -srcstoretype PKCS12 -destkeystore serverkeystore.jks -srcstorepass 123456 -deststorepass 123456复制
3、同样,将客户端用到的证书文件转换为 JKS 类型的密钥库,密码可自定义,此处定义为123456
openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -out clientkeystore.p12 -passout pass:123456
keytool -importkeystore -srckeystore clientkeystore.p12 -srcstoretype PKCS12 -destkeystore clientkeystore.jks -srcstorepass 123456 -deststorepass 123456复制
至此,我们一共得到了以下密钥文件信息:
证书 | 说明 |
---|---|
ca.pem | 自签名CA证书;用于验证数字证书的可信度 |
server-cert.pem、server-key.pem | 服务端数字证书和私钥;作为服务端身份,适用于 除java以外的语言 |
client-vert.pem、client-key.pem | 客户端数字证书和私钥;作为客户端身份,适用于除java以外的语言 |
truststore.jks | 包含自签名CA证书的JKS密钥库;适用于java语言 |
serverkeystore.jks | 包含服务端数字证书和私钥的JKS密钥库;适用于java语言 |
clientkeystore.jks | 包含客户端数字证书和私钥的JKS密钥库;适用于java语言 |
服务端 DBLE 配置
在使用 SSL 时,DBLE 作为服务端需要手动进行配置相关的文件信息,并开启相关的功能。和 MySQL 一致,我们提供了一个开关 supportSSL ,用于标识 SSL 是否启用,默认值为 false ,如果需要使用 SSL 连接时,首先需要确保此开关处于打开的状态。同时需要配置使用到的一些证书信息,在 bootstrap.cnf 中进行如下配置:
-DsupportSSL=true
-DserverCertificateKeyStoreUrl=${path}/serverkeystore.jks
-DserverCertificateKeyStorePwd=123456
-DtrustCertificateKeyStoreUrl=${path}/truststore.jks
-DtrustCertificateKeyStorePwd=123456复制
为了便于查询 SSL 的一些状态信息,我们在 DBLE 的管理端 dble_information 库中新增了一些用于维护相关的 SSL 的元数据信息,确保配置无误并重启 dble 之后,可在 DBLE 管理端查询到对应的 SSL 配置信息以及状态:

客户端连接配置
在使用 SSL 连接 MySQL 时区分了多种连接模式,此方式同样适用于 DBLE ,以下提供两种常见的 Client 加密连接时的客户端配置:
模式 | 连接参数配置 |
---|---|
DISABLED | MySQL client:mysql -uroot -proot --ssl-mode=DISABLED JDBC:jdbc:mysql://ip:port/schema?useSSL=false |
PREFERRED | MySQL client:mysql -uroot -proot --ssl-mode=PREFERRED JDBC:jdbc:mysql://ip:port/schema?requireSSL=false&useSSL=true&verifyServerCerti |
REQUIRED | JDBC:jdbc:mysql://ip:port/schema?requireSSL=true&useSSL=true&verifyServ |
VERIFY_CA | 单向认证(客户端会认证服务端的身份) MySQL client:mysql -uroot -proot --ssl-mode=VERIFY_CA --ssl-ca='${自签名CA证书}' JDBC:jdbc:mysql://ip:port/schema?requireSSL=true&useSSL=true&verifyServerCertificate=true&trustCertificateKeyStoreUrl=file:${自签名CA的JKS格式证书}&trustCertificateKeyStorePassword=${自签名CA证书的JKS密钥库的密码} 双向认证 MySQL client:mysql -uroot -proot --ssl-mode=VERIFY_CA --ssl-ca='${自签名CA证书}' --ssl-cert='${客户端数字证书}' --ssl-key='${客户端私钥}' JDBC:jdbc:mysql://ip:port/schema?requireSSL=true&useSSL=true&verifyServerCertificate=true&trustCertificateKeyStoreUrl=file:${自签名CA证书的JKS密钥库}&trustCertificateKeyStorePassword=${自签名CA证书的JKS密钥库password}&clientCertificateKeyStoreUrl=file:${客户端数字证书和私钥的JKS密钥库}&clientCertificateKeyStorePassword=file:${客户端数字证书和私钥的JKS密钥库password} |
VERIFY_IDENTITIY | 基于VERIFY_CA模式,追加了证书中服务器的主机验证;但上面自签名证书不适宜此模式,因此这里不推荐 |
实验
disabled 模式
1、非加密连接 DBLE ,以下为 JDBC Demo 可供参考,与 DBLE 建立连接并查询 user 表数据:
public class SslTest {
private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException {
List<User> res = disabled();
System.out.println(res);
}
public static List<User> disabled() throws ClassNotFoundException, IOException, SQLException {
List<User> usersList = new ArrayList<>();
Properties pro = new Properties();
FileInputStream fis = new FileInputStream("E:\\jdbc\\src\\main\\resources\\dble.properties");
pro.load(fis);
Class.forName(JDBC_DRIVER);
String url = "jdbc:mysql://" + pro.getProperty("host") + ":" + pro.getProperty("port") + "/" + pro.getProperty("db");
String fullUrlString = url + "?useSSL=false"; // 非加密连接
Connection conn = DriverManager.getConnection(fullUrlString, pro.getProperty("user"), pro.getProperty("password"));
PreparedStatement ps = conn.prepareStatement("select username from user");
ResultSet rs = ps.executeQuery();
while(rs.next()){
String name = rs.getString("username");
usersList.add(new User(name));
}
ps.close();
rs.close();
conn.close();
return usersList;
}
}复制
2、开启抓包后,执行相关 demo 进行查询,将数据包过滤、解析后如下所示:

required 模式
在此仅以某一种 SSL 加密模式为例进行测试演示——required ,在以上的 JDBC Demo 中稍加修改,将 URL 参数变更为相应的模式参数【如下所示】,即可进行加密通信:
String fullUrlString = url
+ "?useSSL=true&requireSSL=true&verifyServerCertificate=false";复制

总结
同时需要注意区别的是,DBLE 侧在进行 SSL 设置时,并没有像 MySQL 一样设置了【require_secure_transport】 类似的强制要求使用安全连接参数设置,也没有按照用户去区分 SSL 配置的适用对象,只要 DBLE 服务端开启并正确配置了 SSL 选项,所有用户与 DBLE 建立连接时均可自主选择是否需要采用 SSL 加密连接。
相关推荐:
MySQL binlog 分析工具 analysis_binlog 的使用介绍

社区近期动态

