mysql服务端必须真正启用ssl(have_ssl=yes且ssl_ca/cert/key为非空绝对路径),否则require ssl会导致连接失败;启用后方可配置用户强制ssl、客户端显式启用tls、全局require_secure_transport=on强制加密。

MySQL 服务端没真正启用 SSL,直接给用户加 REQUIRE SSL 只会连不上——报错看着像权限拒绝,实际是 SSL 握手根本没发生。
确认服务端 SSL 已真正启用
这是所有后续操作的前提。很多“配了连不上”的问题都卡在这一步。
-
SHOW VARIABLES LIKE 'have_ssl';必须返回YES;若为DISABLED或空值,说明 OpenSSL 模块未加载或配置被忽略 -
SHOW VARIABLES LIKE 'ssl_%';中ssl_ca、ssl_cert、ssl_key三项必须是非空绝对路径(如/var/lib/mysql/ca.pem),不能是OFF、空字符串或相对路径 - 常见静默失败原因:证书文件权限不是
600、属主不是mysql用户、SELinux/AppArmor 拦截读取、路径写在[client]段而非[mysqld]段
给特定用户强制走 SSL 连接
服务端 SSL 启用后,才可对用户生效 REQUIRE SSL 策略。它只控制该用户的连接是否必须加密,不提供双向认证。
- 新建用户时直接指定:
CREATE USER 'appuser'@'10.0.2.%' IDENTIFIED BY 'p4ssw0rd' REQUIRE SSL; - 已有用户补加策略(MySQL 8.0.22+ 支持):
ALTER USER 'appuser'@'10.0.2.%' REQUIRE SSL; - 执行后需
FLUSH PRIVILEGES;,否则旧连接可能仍缓存旧权限状态 - 验证是否生效:
SELECT user, host, ssl_type FROM mysql.user WHERE user = 'appuser';,ssl_type应为ANY
客户端连接必须显式启用 SSL 模式
即使用户设了 REQUIRE SSL,客户端不主动发起 TLS 握手,连接仍会被拒绝——这不是认证失败,是协议层被拦在门外。
- 命令行连接必须加
--ssl-mode=REQUIRED:mysql -u appuser -h 192.168.1.100 -p --ssl-mode=REQUIRED - JDBC URL 需完整声明:
?useSSL=true&requireSSL=true&enabledTLSProtocols=TLSv1.2(旧驱动用usessl=true无效) - PHP PDO 连接需在 DSN 中加入
;sslmode=require或指定证书路径 - 避免用
--ssl-mode=VERIFY_IDENTITY配自签名证书:客户端会校验 CN 域名,而自签证书 CN 通常为localhost,与真实 IP 或域名不匹配,直接拒连
require_secure_transport=ON 是全局强制开关
仅靠用户级 REQUIRE SSL 不够,远程 TCP 连接仍可能绕过。要真正“一刀切”禁用明文连接,必须开启全局开关。
- 运行时启用(推荐):
SET PERSIST require_secure_transport = ON;(自动写入持久化配置) - 配置文件启用:在
[mysqld]段加require_secure_transport=ON,然后systemctl restart mysqld - 生效后,所有未加密的 TCP 连接(包括
root@127.0.0.1)都会被拒绝,错误提示类似Access denied for user,但本质是连接被服务端直接终止 - 验证:
SELECT @@GLOBAL.require_secure_transport;返回1
最容易被忽略的是:Unix socket 连接(如 mysql -u root -S /var/run/mysqld/mysqld.sock)默认绕过 require_secure_transport 和 REQUIRE SSL,生产环境若需彻底禁用明文,必须确保应用不走 localhost,改用 127.0.0.1 强制走 TCP,并配合网络层控制。











