1. MySql ssl

1.1 查看是否已经开启SSL

-- 查看所有会话连接哪些用了加密连接 , VARIABLE_VALUE='' 的为未加密
​
select t2.PROCESSLIST_ID,t2.PROCESSLIST_USER,t2.PROCESSLIST_HOST,t1.VARIABLE_NAME,t1.VARIABLE_VALUE 
from performance_schema.status_by_thread t1 
join performance_schema.threads t2 on t1.THREAD_ID=t2.THREAD_ID  
where t1.VARIABLE_NAME like 'Ssl_cipher' ;
​
-- 当前session
SHOW SESSION STATUS LIKE 'Ssl_cipher';

使用命令查看: show variables like '%ssl%';

1302413-20230802103708453-1174167837

yes是已经打开了 , 如果是DISABLE则表示没有。

TLS查看:

1302413-20230802110122479-1494771805

1.2 如何开启SSL

前提 : 没有开启ssl , 没有生成证书 (一般mysql 5.7.5以上版本 , 以及8.0都会默认开启)

  1. 步骤1, 关闭mysql

  2. 步骤2, 使用mysql_ssl_rsa_setup, 生成证书

    mysql_ssl_rsa_setup --datadir=/opt/data8.0 --verbose (不写参数也行 , 会存放到默认的 datadir 下)

    1302413-20230802110453753-652349784

    安装完成后: 一般在 datadir 目录下会有(注意这些密钥的权限问题 , 如果需要则执行 : chown -R mysql.mysql *.pem)

    [root mysql_data]# ll *.pem
    -rw------- 1 mysql mysql 1675 Jun 12 17:22 ca-key.pem         #CA私钥
    -rw-r--r-- 1 mysql mysql 1074 Jun 12 17:22 ca.pem             #自签的CA证书 , 客户端连接也需要提供
    -rw-r--r-- 1 mysql mysql 1078 Jun 12 17:22 client-cert.pem    #客户端连接服务器端需要提供的证书文件
    -rw------- 1 mysql mysql 1675 Jun 12 17:22 client-key.pem     #客户端连接服务器端需要提供的私钥文件
    -rw------- 1 mysql mysql 1675 Jun 12 17:22 private_key.pem    #私钥/公钥对的私有成员
    -rw-r--r-- 1 mysql mysql 451 Jun 12 17:22  public_key.pem     #私钥/公钥对的共有成员
    -rw-r--r-- 1 mysql mysql 1078 Jun 12 17:22 server-cert.pem    #服务器端证书文件
    -rw------- 1 mysql mysql 1675 Jun 12 17:22 server-key.pem     #服务器端私钥文件
  3. 步骤3 : 配置文件里加入SSL变量参数

    [mysqld]
    ssl-ca=/usr/local/mysql/data/ca.pem
    ssl-cert=/usr/local/mysql/data/client-cert.pem
    ssl-key=/usr/local/mysql/data/client-key.pem
     
    [mysql]
    ssl-ca=/usr/local/mysql/data/ca.pem
    ssl-cert=/usr/local/mysql/data/client-cert.pem
    ssl-key=/usr/local/mysql/data/client-key.pem
  4. 步骤4 : 重启 mysql , 核验

    service mysqld restart
    ​
    SHOW SESSION STATUS LIKE 'Ssl_cipher';
    \s

    1302413-20230802111921009-221179650

1.3 mysql客户端配置

MySQL 客户端连接 Server 时 , 通过 --ssl-mode 参数指定 :

  • --ssl-mode=PREFFERED , 默认行为 , client 端尝试使用加密进行连接 , 如果无法构建加密连接 , 则会退回到未加密的连接

  • --ssl-mode=REQUIRED时 , Client 端需要加密连接 , 如果无法构建连接 , 则 Client 端将失败

  • --ssl-mode=DISABLED , Client 端使用未加密的连接

  • --ssl-mode=VERIFY_CA , Client 端需要加密连接 , 并且还对 CA 证书进行验证

  • --ssl-mode=VERIFY_IDENTITY , Client 端需要加密的连接 , 并且还针对 CA 证书和其证书中的服务器主机名执行验证

注意 : 主机名身份验证 VERIFY_IDENTITY 不适用于由服务器自动创建或使用 mysql_ssl_rsa_setup 手动创建的自签名CA证书。

如果没有使用ssl , 则显示为Not in use

如果不想使用ssl则增加--ssl=0选项或--ssl-mode=DISABLED

一般localhost环境默认是不开启ssl的 , 如果想强制使用ssl , 则增加--ssl-mode=REQUIRED 选项

mysql -uroot -proot --ssl=0
mysql -uroot -proot --ssl-mode=DISABLED   # 5.7及之后新版本建议使用该参数
mysql -uroot -proot --ssl-mode=REQUIRED   # 5.7及之后新版本建议使用该参数

1302413-20230802112656476-1266824724

1.4 如何强制必须使用SSL?

如果要所有的均必须开启 , 则修改 my.cnf

[mysqld]
require_secure_transport=ON

1.5 如何强制用户必须使用SSL加密方式链接?

//新建用户
mysql> grant select on *.* to 'dba'@'%' identified by 'xxx' REQUIRE SSL; 
//修改用户
mysql> ALTER USER 'dba'@'%' REQUIRE SSL; 
flush privileges;

2. mysql复制使用SSL

2.1 mysql ssl握手过程

上述示例已有详细说明 , 这里再简要总结一下 :

  1. 客户端发起 ssl 连接请求 ;

  2. MySQL Server 发送数字证书 server-cert.pem 给客户端(server-cert.pem包含 : 服务器公钥、CA签名信息 ) ;

  3. 客户端使用CA 证书 ca.pem ( 由于这是 MySQL 自签名的CA证书 , 无法从操作系统的可信任区获取 ( 压根不在这里边 ) , 所以事先必须在客户端本地保存 CA 证书文件 ) 中的 CA 公钥解密 server-cert.pem 中的签名 , 进行验证 ;

  4. 验证通过后 , 生成对称密钥 , 使用 server-cert.pem 中的公钥加密“对称密钥” , 发送给 MySQL Server ;

  5. MySQL Server 使用自己保留的私钥 server-key.pem 解密 , 得到“对称密钥” ;

  6. 接下来传输数据则使用“对称密钥”进加密和解密。

如果仅指定 --ssl-mode=REQUIRED , 不指定 --ssl-mode=VERIFY_CA 或者 --ssl-mode=VERIFY_IDENTITY , 则不需要步骤3

2.2 复制通道SSL开启加密连接

理由 : MySQL主从复制也会使用 TCP/IP 协议传输数据 , 同样为了减少数据泄漏的风险 , 建议为主从复制或者组复制配置 SSL 加密。

检查方法 , 在从库执行 : select Enabled_ssl,Ssl_ca,Ssl_verify_server_cert from mysql.slave_master_info;

  • Enabled_ssl 表示复制线程是否开启了 ssl 连接

  • Ssl_ca 表示是否配置了主库的 CA 证书文件 , 需从主库拷贝到从库服务器上 , 验证 CA 证书可以避免中间人攻击 , 建议配置 ( SSL中验证证书不是必须的 , 但是建议验证 )

  • Ssl_verify_server_cert 表示是否要求验证 CA 身份 , 开启时自签名证书无法通过验证 , 必须购买受信任的CA机构颁发的数字证书

使用方法 :

( 前提 : 主库已开启 SSL 功能 , 允许客户端创建 SSL 加密连接 ) `

##只开启 ssl
change master to master_ssl=1;
​
##开启 ssl , 并验证 CA 证书 ( 需拷贝主库上的 CA 证书 ) 
change master to master_ssl=1,master_ssl_ca='/tmp/ca.pem';
​
##开启 ssl , 验证 CA 证书并要求验证 CA 身份 , 这个需要购买受信任的CA机构颁发的数字证书 , 服务器和浏览器都会有权威CA机构的信任列表 , 可以自动获取 , 不再需要配置 master_ssl_ca
change master to master_ssl=1,master_ssl_verify_server_cert=1;

3. JDBC如何配置SSL

3.1 jdbc开启ssl连接

首先 MySQL Server 端必须生成 SSL 证书和密钥文件 , 并且在启动时指定启动参数 : --ssl ( 一般将其写到 my.cnf 中 ) 。

MySQL8.0 启动时会自动生成SSL 证书和密钥文件 , 并默认使用 --ssl 参数。

JDBC 开启 ssl 连接示例 : jdbc:mysql://localhost:3306/hucq?useSSL=true

JDBC 关闭 ssl 连接示例 : jdbc:mysql://localhost:3306/hucq?useSSL=false

如果 MySQL Server 使用 caching_sha2_password ( MySQL8.0默认的认证插件 ) 、sha256_password 认证插件 , 则还必须指定 AllowPublicKeyRetrieval=True

因为 caching_sha2_password 插件要求交换密码时必须使用 RSA 公钥加密 ( 在没有使用SSL加密连接的情况下 ) , AllowPublicKeyRetrieval=True 参数作用是请求 MySQL Server 端发送 RSA 公钥给客户端。

如果不请求 RSA 公钥并且又没有指定客户端本地RSA公钥文件 ( 先从 MySQL 服务器上拷贝 RSA 公钥到本地 ) , 则连接会报错。

应该配置 : jdbc:mysql://localhost:3306/hucq?useSSL=false&AllowPublicKeyRetrieval=True ( 8.0 )

JDBC 开启 SSL 连接 , 意味着要求安全连接 , 则应该开启 CA 证书认证 , 跟 mysql 客户端一样 , 需要将 MySQL 的自签名 CA 证书导入到客户端 , 或者放到 ftp 上 , 再通过 JDBC 参数指定 CA 证书路径 , 比较复杂.

请参考官方文档 : https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-using-ssl.html

3.2配置JDBC的几种方法

mysql使用ssl连接官方文档 : https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-using-ssl.html

第一种方法 ( 自定义密钥库 ) :

  1. 如果直接配置了连接属性verifyServerCertificate=true&useSSL=true&requireSSL=true , 启动项目会报错 , 缺少证书

    1302413-20230802114203170-1780944759

  2. 所以我们需要把服务器端的data/ca.pem文件拿到客户端 , 再执行命令 , 添加到truststore密钥库

    keytool -importcert -alias MySQLCACert -file ca.pem -keystore truststore -storepass mypassword

    1302413-20230802114132493-501088499

    执行完毕会在当前文件夹生成一个truststore文件

  3. 然后把该文件的路径配置到连接属性

    &trustCertificateKeyStorePassword=mypassword&trustCertificateKeyStoreUrl=file:///Users/sumengnan/fsdownload/truststore

    或是直接增加java启动参数-Djavax.net.ssl.trustStore=/Users/sumengnan/fsdownload/truststore -Djavax.net.ssl.trustStorePassword=mypassword

  4. 如果mysql配置了双向认证 , 则参考https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-using-ssl.html

    如果不想使用服务器生成的客户端密钥和证书文件 , 也可以手动使用openssl创建密钥 : https://dev.mysql.com/doc/refman/5.7/en/creating-ssl-rsa-files.html

    这种方法缺点是 , java会放弃原来的cacerts默认密钥库 , 如果你用到了其他的证书 , 那在truststore密钥库没有证书 , 会报错的。

第二种方法 ( 添加到cacerts默认密钥库 ) :

数据库连接增加属性verifyServerCertificate=true&useSSL=true&requireSSL=true

提示 : 默认密钥库位置 : $JAVA_HOME/jre/lib/security/cacerts

keytool -importcert -alias MySQLCACert -file /Users/sumengnan/fsdownload/ca.pem -keystore cacerts ( 一条命令搞定 , 连密码和连接配置都不需要了 )

默认的密钥库口令是 : "changeit"

1302413-20230802114039076-914301577


参考链接

https://www.jianshu.com/p/75b098430508

https://blog.csdn.net/sumengnan/article/details/114086217

mysql ssl - 郭大侠1 - 博客园


熊熊