MySQL强制SSL需同时满足:服务端证书运行就绪(ssl_ca/cert/key为绝对路径且权限正确)、require_secure_transport=ON并重启生效、客户端显式指定--ssl-mode=REQUIRED;任一缺失均静默降级明文。

必须同时满足三个条件:服务端证书加载成功(have_ssl = YES)、全局开启强制开关(require_secure_transport = ON)、客户端显式声明 TLS 意图(如 --ssl-mode=REQUIRED);缺一就会降级为明文连接,且不报错。
确认 have_ssl 真实启用,不是“编译支持”而是“运行就绪”
很多人执行 SHOW VARIABLES LIKE 'have_ssl'; 看到 YES 就以为完事了,其实这只是说明 MySQL 编译时带了 OpenSSL 支持。真正关键的是它是否能读取并加载证书文件。
- 检查
ssl_ca、ssl_cert、ssl_key三个变量是否为非空的**绝对路径**:SHOW VARIABLES LIKE 'ssl_%'; - 路径必须是 MySQL 进程(通常是
mysql用户)可读的,server-key.pem权限必须是-rw-------(600),属主为mysql - SELinux 或 AppArmor 常静默拦截——临时执行
setenforce 0后再查have_ssl,若变为YES,就是权限策略在挡路 - 别把证书丢进
/etc/mysql/就不管了;mysqld默认只从数据目录或my.cnf中显式指定的路径加载
配置 require_secure_transport = ON 并重启 mysqld
这个变量才是“强制所有 TCP 连接走 SSL”的总开关。它不支持热加载,改完必须完整重启服务,reload 无效。
- 在
[mysqld]段落中写入:require_secure_transport = ONssl_ca = /var/lib/mysql/ca.pemssl_cert = /var/lib/mysql/server-cert.pemssl_key = /var/lib/mysql/server-key.pem - 路径必须绝对,不能用
./ca.pem、不能是软链接、不能含环境变量(如$DATADIR) - 重启后立即验证:
SELECT @@GLOBAL.require_secure_transport;应返回ON;SHOW STATUS LIKE 'Ssl_cipher';应非空 - 如果
ssl_ca等仍为空,去错误日志看具体加载失败原因:tail -n 20 /var/log/mysql/error.log
客户端必须主动发起 SSL 握手,不能依赖服务端“拉一把”
哪怕服务端设了 require_secure_transport = ON,MySQL CLI、JDBC、pymysql 等默认仍尝试明文连接——它们根本不会发 Client Hello。结果不是证书错误,而是直接 Access denied。
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
- 命令行连接必须加:
mysql -u user -p --ssl-mode=REQUIRED;--ssl或--ssl-mode=PREFERRED会自动降级,无法验证是否真加密 - JDBC URL 必须包含:
&sslMode=REQUIRED&enabledTLSProtocols=TLSv1.2;旧版驱动用useSSL=true是无效的,且可能和caching_sha2_password插件冲突 - 测试务必用
127.0.0.1或远程 IP,localhost走 Unix socket,完全绕过 SSL 校验 - 自签名证书下慎用
--ssl-mode=VERIFY_IDENTITY,因为 CN 通常为localhost,与实际连接地址不一致会导致拒绝
常见失败现象与对应排查点
连不上、报错模糊、看似成功实则明文——这些都不是偶然,背后有明确线索。
-
Access denied for user:大概率是require_secure_transport = ON已生效,但客户端没加--ssl-mode=REQUIRED -
SSL connection error: protocol version mismatch:服务端tls_version和客户端支持的 TLS 协议不匹配,查SELECT @@GLOBAL.tls_version;,必要时调整为TLSv1.2 -
SSL_CTX_set_default_verify_paths failed:SELinux/AppArmor 拦截,或证书路径不可读,不是证书内容问题 -
have_ssl = DISABLED且ldd $(which mysqld) | grep ssl无输出:MySQL 编译时未启用 SSL,需重装或换发行版包
最容易被忽略的是:证书生成只是第一步,mysql_ssl_rsa_setup 不配置、不重启、不赋权;而 require_secure_transport = ON 一旦开启,所有未声明 SSL 意图的连接都会被拒——没有警告,没有日志提示“你该加 --ssl-mode”,只有沉默的拒绝。










