必须同时满足have_ssl= yes、ssl_mode非preferred、require_secure_transport= on三条件;仅have_ssl=yes仅表示编译支持,不保证运行时启用ssl加密。

确认 MySQL 是否真正支持 SSL,而不是只编译了选项
很多用户执行 SHOW VARIABLES LIKE 'have_ssl'; 看到 YES 就以为万事大吉,其实这只是说明 MySQL 编译时带了 SSL 支持,不代表运行时已启用加密能力。关键要看 ssl_mode 变量是否为 REQUIRED 或更严格值(如 VERIFY_CA),默认是 PREFERRED —— 它允许客户端降级走明文,等于没开。
必须连查两个变量:
-
SHOW VARIABLES LIKE 'have_ssl';→ 必须返回YES -
SHOW VARIABLES LIKE 'ssl_mode';→ 必须不是PREFERRED,且服务端已设require_secure_transport = ON
如果 ssl_mode 仍是 PREFERRED,改配置或重启都无效,得先配好证书路径再开 require_secure_transport = ON,否则 MySQL 启动时会静默忽略 SSL 配置。
用 mysql_ssl_rsa_setup 生成证书,但别以为生成完就自动生效
这个工具只做一件事:在指定目录下生成合规的 PEM 文件(ca.pem、server-cert.pem、server-key.pem),它不写配置、不重启服务、也不创建强制 SSL 用户。很多人执行完就去连,结果 Ssl_cipher 为空,连接仍是明文。
正确姿势是:
- 先确认数据目录归属:
ls -ld /var/lib/mysql/,属主必须是mysql用户 - 切换到
mysql用户执行:sudo -u mysql mysql_ssl_rsa_setup --datadir=/var/lib/mysql - 检查生成文件权限:
ls -l /var/lib/mysql/server-key.pem必须是-rw------- (600),且属主为mysql - 若报
Permission denied或日志出现SSL_CTX_set_default_verify_paths failed,大概率是 SELinux 拦截,临时关掉验证:sudo setenforce 0
my.cnf 配置必须写全四行,且路径全是绝对路径
只写 ssl_ca、ssl_cert、ssl_key 三行不够,缺了 require_secure_transport = ON 就等于白配——客户端仍可绕过 SSL 连接。这行不支持热加载,必须重启 mysqld。
常见错误配置:
- 路径写成相对路径,比如
ssl-ca = ca.pem→ 必须写ssl-ca = /var/lib/mysql/ca.pem - 证书放在
/root/或用户家目录 → MySQL 进程(mysql用户)读不到 - 漏掉
require_secure_transport = ON→ 即使证书全对,have_ssl是YES,Ssl_cipher仍是空
推荐配置段(加在 [mysqld] 下):
require_secure_transport = ON ssl-ca = /var/lib/mysql/ca.pem ssl-cert = /var/lib/mysql/server-cert.pem ssl-key = /var/lib/mysql/server-key.pem
客户端连不上?检查三个地方:用户权限、连接地址、SSL 模式
服务端配得再严,客户端不配合也白搭。最容易被忽略的是:localhost 默认走 Unix socket,完全绕过 SSL。测试必须用 127.0.0.1 或远程 IP。
另外,用户权限是逐个控制的,不是全局开关:
- MySQL ≥ 8.0.22:可用
ALTER USER 'app'@'%' REQUIRE SSL; - MySQL ≤ 8.0.21:只能重建用户:
CREATE USER 'app'@'%' IDENTIFIED BY 'pwd' REQUIRE SSL; - 验证用户是否生效:
SELECT user, host, ssl_type FROM mysql.user WHERE user = 'app';,ssl_type应为ANY
客户端命令行必须显式校验证书,不能只加 --ssl-mode=REQUIRED(它只加密,不防中间人):
- 安全连接应为:
mysql -u app -p --ssl-mode=VERIFY_CA --ssl-ca=/path/to/ca.pem - JDBC URL 要含:
&useSSL=true&verifyServerCertificate=true&serverSslCert=/path/to/ca.pem
真正生效的标志不是配置写对了,而是连上去后执行 SHOW STATUS LIKE 'Ssl_cipher'; 返回非空值,且 Ssl_version 显示 TLSv1.2 或 TLSv1.3。











