真正强制加密连接的是require_secure_transport=ON,需先确认have_ssl=YES,再配置证书路径与权限、关闭SELinux干扰,并在客户端显式声明--ssl-mode=REQUIRED。

不能只靠 REQUIRE SSL 就算完事——它只校验已建立的连接是否加密,不拦明文连接;真正能“强制”的是服务端开关 require_secure_transport = ON,配合证书加载和客户端显式声明。
确认 have_ssl = YES 是前提
没这个,后面全无效。执行 SHOW VARIABLES LIKE 'have_ssl';,必须返回 YES。常见失败原因:
-
ssl_ca、ssl_cert、ssl_key没配或路径不是绝对路径(如/var/lib/mysql/ca.pem) - 证书文件权限不对:
server-key.pem必须是600且属主为mysql用户 - SELinux 或 AppArmor 静默拦截读取,临时用
setenforce 0测试可快速定位 - MySQL 编译时用了
--without-ssl,ldd $(which mysqld) | grep ssl查不到libssl.so
require_secure_transport = ON 才是真强制
它在协议层拒绝所有未加密的 TCP 连接,包括 root@127.0.0.1,不是“建议加密”,是“不加密就断开”。
- 运行时启用(推荐):
SET PERSIST require_secure_transport = ON; - 配置文件启用:
[mysqld]段加require_secure_transport = ON,然后systemctl restart mysqld - 验证生效:
SELECT @@GLOBAL.require_secure_transport;返回1 - 注意:Unix socket 连接默认不受影响,除非你额外禁用
用户级 REQUIRE SSL 只是叠加保障
它不替代全局强制,而是对特定账户加一层校验。创建或修改用户时用:
CREATE USER 'appuser'@'10.0.2.%' IDENTIFIED BY 'p4ssw0rd' REQUIRE SSL;ALTER USER 'appuser'@'%' REQUIRE SSL;- 支持更严要求:
REQUIRE X509、REQUIRE SUBJECT '/CN=appclient'等,但都依赖服务端 SSL 已启用
客户端不声明 --ssl-mode=REQUIRED 就白配
服务端全配好了,客户端不主动握手,连接仍是明文,错误常报 Access denied for user,实际卡在协议层。
- 命令行:
mysql -u appuser -h 192.168.1.100 -p --ssl-mode=REQUIRED - JDBC:
?useSSL=true&requireSSL=true&enabledTLSProtocols=TLSv1.2(旧驱动usessl=true无效) - PHP mysqli:连接时传
MYSQLI_CLIENT_SSL标志 - PDO DSN:
sslmode=require或完整指定证书路径 - 注意:
--ssl-mode=VERIFY_IDENTITY要求证书 CN 匹配连接地址,自签名证书 CN 多为localhost,连 IP 会失败
最容易被忽略的是三件事同时缺一不可:服务端证书真正加载(have_ssl = YES)、全局强制开关打开(require_secure_transport = ON)、客户端明确发起 TLS 握手(--ssl-mode=REQUIRED)。少一个,连接就退化成明文,还可能报错误导你去查密码或权限问题。


















