必须同时满足服务端加载SSL模块、全局开启require_secure_transport=ON、客户端显式声明TLS握手意图三个条件,缺一即静默走明文;需确认have_ssl=YES、证书路径绝对且权限600、属主为mysql,并用--ssl-mode=REQUIRED连接。

必须同时满足三个条件:服务端真正加载了SSL模块、全局开启require_secure_transport = ON、客户端显式声明TLS握手意图;缺一就会静默走明文,连错误都不报。
确认have_ssl是YES,不是DISABLED或空值
这是最容易被跳过的致命检查。执行SHOW VARIABLES LIKE 'have_ssl';,结果必须是YES。如果返回DISABLED,说明MySQL二进制未链接OpenSSL,或者系统缺少openssl-devel(RHEL/CentOS)或libssl-dev(Debian/Ubuntu)。此时别折腾证书路径——重装官方MySQL包最省事。
验证是否真链接了SSL库:ldd $(which mysqld) | grep ssl,应输出类似libssl.so.1.1 => /lib/x86_64-linux-gnu/libssl.so.1.1的行。
常见假阳性:have_ssl=YES只表示编译时支持,不代表运行时已启用。必须连查ssl_ca、ssl_cert、ssl_key三个变量是否为非空绝对路径,且MySQL进程(通常是mysql用户)有读权限。
配置require_secure_transport = ON并重启mysqld
仅在用户权限里加REQUIRE SSL不够,它只校验已建立的连接;而require_secure_transport = ON是协议层开关,会直接拒绝所有未加密的TCP连接(包括root@127.0.0.1),这才是真正的“强制”。
- 推荐运行时启用:
SET PERSIST require_secure_transport = ON; - 配置文件启用:在
[mysqld]段末尾添加require_secure_transport = ON,路径无关,但必须systemctl restart mysqld(reload不生效) - 验证是否生效:
SELECT @@GLOBAL.require_secure_transport;返回1才算成功
注意:require_secure_transport对Unix socket连接(如mysql -u root -S /var/run/mysqld/mysqld.sock)默认无效,这是设计行为,不是bug。
客户端必须用--ssl-mode=REQUIRED发起握手
服务端开了强制,客户端不主动发Client Hello,连接会被直接终止,错误常是Access denied for user——这不是认证失败,而是协议被拦在门外。
命令行示例:mysql -u appuser -h 192.168.1.100 -p --ssl-mode=REQUIRED
其他客户端关键点:
- JDBC URL中必须含
sslMode=REQUIRED&enabledTLSProtocols=TLSv1.2(旧驱动用useSSL=true无效) - PHP mysqli需传入
MYSQLI_CLIENT_SSL标志 - PDO DSN中用
sslmode=require或完整指定证书路径 -
--ssl-mode=VERIFY_IDENTITY会校验证书CN与连接地址是否一致,自签名证书CN多为localhost,连IP会失败,测试阶段建议先用REQUIRED
证书路径、权限与SELinux三者必须全过关
用mysql_ssl_rsa_setup生成证书后,必须以mysql用户身份运行:sudo -u mysql mysql_ssl_rsa_setup --datadir=/var/lib/mysql。生成后检查:
-
ls -l /var/lib/mysql/{ca,server-cert,server-key}.pem——server-key.pem权限必须是-rw-------(600),且属主为mysql - my.cnf中
ssl_ca、ssl_cert、ssl_key的路径必须是绝对路径,不能用~、.或软链接 - SELinux常静默拦截:
tail -n 20 /var/log/mysql/error.log若出现SSL_CTX_set_default_verify_paths failed,大概率是它;临时验证:sudo setenforce 0
最后提醒:require_secure_transport = ON生效后,任何没带--ssl-mode=REQUIRED的TCP连接都会被立即断开,连登录界面都看不到——这不是配置失败,恰恰说明它起作用了。


















