根本原因是mysql启动时未成功加载ssl:server-key.pem权限非600、证书路径为相对路径、配置误写在[client]段而非[mysqld]段、未重启mysqld服务,或require_secure_transport未启用导致全局强制失效。

mysql_ssl_rsa_setup 生成证书后,为什么 have_ssl 还是 DISABLED?
根本原因不是证书没生成,而是 MySQL 启动时压根没加载成功。常见于:server-key.pem 权限不是 600、证书路径写成相对路径、或配置项误放在 [client] 段而非 [mysqld] 段。
- 用
sudo -u mysql ls -l /var/lib/mysql/server-key.pem确认权限是-rw-------;如果不是,立刻执行chmod 600 /var/lib/mysql/server-key.pem - 检查
my.cnf中ssl-ca、ssl-cert、ssl-key是否为绝对路径,且文件实际存在(ls -l验证) - 确认这些配置在
[mysqld]下,不是[client]或[mysqld_safe]—— 放错段落等于没写 - 重启必须用
systemctl restart mysqld(不是reload),否则配置不生效
require_secure_transport = ON 和 REQUIRE SSL 用户权限,哪个更关键?
require_secure_transport = ON 是服务端全局强制开关,它让所有连接(包括 root)都必须走 TLS;而 REQUIRE SSL 只对单个用户生效,且前提是服务端已启用 SSL。漏掉前者,后者形同虚设。
- 先配
require_secure_transport = ON,再建用户:例如CREATE USER 'app'@'%' IDENTIFIED BY 'pwd' REQUIRE SSL; - 如果只设
REQUIRE SSL但没开require_secure_transport,客户端连不上时会报Access denied,实际是静默降级失败,不是权限问题 - 验证是否真正强制:用明文命令试连
mysql -u app -p --protocol=tcp,应直接拒绝;若能连上,说明require_secure_transport没生效
客户端连接时 ssl-mode=REQUIRED 仍报错 “SSL is required but the server doesn't support it”
这个错误 90% 是服务端 have_ssl 为 DISABLED,而不是客户端参数写错。MySQL 不会告诉你“证书路径错了”,只会甩出这句模糊提示。
- 先登录 MySQL 执行
SHOW VARIABLES LIKE 'have_ssl';—— 必须是YES,否则停在这里排查 - 再查
SHOW VARIABLES LIKE 'ssl_%';,确认ssl_ca、ssl_cert、ssl_key三项值非空且路径可读 - 若用 OpenSSL 手动生成证书,避免
subjectAltName扩展(MySQL 8.0.28+ 默认拒绝含该扩展的证书),生成时加-extensions server_cert并确保配置段中禁用subjectAltName - 客户端加
--ssl-mode=REQUIRED只是要求加密,不解决服务端证书加载失败的问题
MySQL 8.0+ 用 mysql_ssl_rsa_setup 生成的证书,为什么 client 连接时还要指定 ca.pem?
因为 mysql_ssl_rsa_setup 只生成服务端证书链(ca.pem、server-cert.pem、server-key.pem),而客户端默认不信任自签名 CA。你得显式告诉客户端:“这个 CA 是可信的”。
- 命令行连接必须带
--ssl-ca=/var/lib/mysql/ca.pem,否则即使服务端强制加密,客户端也会因证书验证失败断开 - 应用代码里(如 Node.js 的
mysql2)需传入ssl: { ca: fs.readFileSync('/var/lib/mysql/ca.pem') } - 如果不想验证 CA(仅加密不验身份),可用
--ssl-mode=REQUIRED跳过验证,但生产环境不推荐 -
ca.pem文件本身不能被修改或重命名,MySQL 内部硬编码校验其内容结构
have_ssl 状态、客户端 CA 显式指定——这五点任何一处出错,都会导致看似配好了却始终明文传输。没人会告诉你哪一步错了,只能逐项验证。











