MySQL SSL连接必须同时满足服务端have_ssl=YES、用户权限含REQUIRE SSL、客户端真实完成TLS握手三条件,缺一即静默降级为明文;需验证ssl_ca/cert/key路径有效且文件可读,并启用require_secure_transport=ON强制加密。

MySQL SSL 连接不是“配了证书就自动加密”,必须三件事全对:服务端 have_ssl 是 YES、用户权限含 REQUIRE SSL、客户端真实完成 TLS 握手;漏掉任意一环,连接静默降级为明文——你连上了,但数据在裸奔。
确认服务端真正加载了 SSL 支持
很多问题卡在这一步:证书放好了、my.cnf 也改了、服务重启了,但连接仍是明文。根本原因是 mysqld 启动时压根没加载 OpenSSL 模块。
- 登录 MySQL 执行
SHOW VARIABLES LIKE 'have_ssl',返回值必须是YES;若为DISABLED或空,后续所有配置都无效 - 顺带查
SHOW VARIABLES LIKE 'ssl_ca'、ssl_cert、ssl_key—— 三项都必须返回非空的绝对路径,且对应文件真实存在、可被mysql用户读取 -
have_ssl = DISABLED常见于 MariaDB 精简版、Alpine 镜像(用 WolfSSL 替代 OpenSSL)、或编译时未加-DWITH_SSL=system;重装官方二进制包比自行编译修复更稳妥
生成并放置证书:路径、格式、权限一个都不能错
MySQL 对证书极其挑剔:只认绝对路径、只读 PEM 格式、私钥权限必须为 600。相对路径、~/、权限 >600 的私钥都会导致启动失败或连接被拒。
- 优先用内置工具生成(MySQL 8.0+):
mysql_ssl_rsa_setup --datadir=/var/lib/mysql --uid=mysql,它自动处理subjectAltName,避免X509_V_ERR_IP_ADDRESS_MISMATCH - 证书必须放在 MySQL 进程有读权限的目录,例如
/var/lib/mysql/或/etc/mysql/ssl/,不能放/root/或/home/deploy/ - 立刻修正权限:
chown mysql:mysql /var/lib/mysql/*.pem && chmod 600 /var/lib/mysql/server-key.pem—— MySQL 拒绝读取组/其他可读的私钥
配置 my.cnf 并强制启用 require_secure_transport
require_secure_transport = ON 不是可选优化项,而是生产环境的底线配置。它拒绝所有非 SSL 连接,比只设 ssl=ON 或仅依赖用户权限更可靠。
- 编辑
/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf,只在[mysqld]段添加:ssl-ca = /var/lib/mysql/ca.pem ssl-cert = /var/lib/mysql/server-cert.pem ssl-key = /var/lib/mysql/server-key.pem require_secure_transport = ON
- 路径必须是绝对路径,不能用
~/或相对路径;不要写在[client]段——那是客户端配置,对服务端无效 - 改完必须执行
systemctl restart mysqld(不是reload),SSL 配置不支持热加载
验证是否真正在用加密,而不是只看配置
SHOW VARIABLES LIKE '%ssl%' 只告诉你“配了啥”,不是“连上了啥”。关键要看当前连接是否加密。
- 用明文方式试连:
mysql -u app -p --protocol=tcp,如果能连上,说明require_secure_transport没生效 - 成功连接后执行
STATUS或SELECT @@session.ssl_cipher;,返回非空值(如TLS_AES_256_GCM_SHA384)才表示真正在用 TLS 加密 - 从库复制时,
SHOW SLAVE STATUS\G中Slave_SSL_Allowed: Yes且Master_SSL_Cipher非空,才是主从加密真正生效
最容易被忽略的点是:require_secure_transport = ON 必须写进配置文件并重启,SET GLOBAL 无效;server-key.pem 权限一旦不是 600,MySQL 启动日志里可能只报一句模糊的 “SSL error”,根本不会提示权限问题。


















