mysql 8.0+ 默认启用 ssl 服务端支持但不强制加密;show variables like 'have_ssl' 返回 yes 且 ssl_mode 默认为 preferred,需通过 require ssl 授予用户级强制加密权限。

MySQL 8.0+ 默认是否启用 SSL?
MySQL 8.0 及以上版本在初始化安装后,mysqld 会自动生成一套测试用的 PEM 文件(如 ca.pem、server-cert.pem、server-key.pem),并默认开启 SSL 支持——但仅限于「服务端具备证书能力」,不等于所有连接都强制加密。
关键判断依据是:SHOW VARIABLES LIKE 'have_ssl'; 返回 YES,且 SHOW VARIABLES LIKE 'ssl_mode'; 默认为 PREFERRED(即客户端可选加密,不强制)。
- 若返回
DISABLED,说明证书路径配置错误或文件权限不合法(常见于 Windows 或 systemd 管理的 Linux) -
ssl_ca、ssl_cert、ssl_key这三个变量必须全部非空,SSL 才算真正就绪 - Linux 下务必确认
mysqld进程用户(通常是mysql)对证书文件有读取权限,否则日志里会出现SSL error: Unable to get private key
如何验证当前连接是否走 SSL?
连上 MySQL 后直接执行:STATUS; 或 SELECT * FROM performance_schema.status_by_thread WHERE variable_name = 'Ssl_cipher';。更简单的是:SELECT Ssl_cipher FROM information_schema.PROCESSLIST WHERE ID=CONNECTION_ID();
- 返回为空字符串或
NULL→ 当前连接未使用 SSL - 返回类似
ECDHE-ECDSA-AES256-SHA→ 已加密 - 注意:
mysql -u root -p默认不启用 SSL;必须显式加--ssl-mode=REQUIRED才会协商加密 - Java JDBC 连接需在 URL 后追加
&useSSL=true&requireSSL=true,否则即使服务端支持,客户端仍可能降级为明文
怎样让所有远程连接强制走 SSL?
仅靠全局 ssl_mode=REQUIRED 不生效——这个变量只影响服务端行为,不控制用户权限。真正起作用的是账号级别的 REQUIRE SSL 限制。
- 新建用户时:执行
CREATE USER 'app'@'%' IDENTIFIED BY 'pwd' REQUIRE SSL; - 已有用户补加:执行
ALTER USER 'app'@'%' REQUIRE SSL; - 执行后该用户任何 TCP 连接(包括 localhost 的 socket)都会被拒绝,除非客户端明确启用 SSL
- 若需更细粒度控制(例如只对某 IP 段强制 SSL),可用
REQUIRE X509或REQUIRE SUBJECT '...',但需配套分发客户端证书,运维成本显著上升
自签名证书够用吗?生产环境要注意什么?
开发/测试用自签名证书完全可行,MySQL 自带的 mysql_ssl_rsa_setup 工具生成的就是这类证书。但生产环境上线前必须检查三件事:
- 证书有效期:用
openssl x509 -in server-cert.pem -text -noout | grep "Not After"查看,避免某天凌晨连接批量中断 - 主机名匹配:服务端证书的
Subject Alternative Name (SAN)必须包含客户端实际访问的域名或 IP,否则 Java/.NET 客户端会因证书校验失败而拒绝连接 - 密钥安全:
server-key.pem必须设为chmod 600且属主为mysql用户;若误设为 644,MySQL 启动时会静默忽略 SSL 配置
真正容易被忽略的是:MySQL 的 SSL 配置不继承 my.cnf 中的 [client] 段,每个客户端工具(mysql、mysqldump、甚至某些 ORM)都要单独指定 --ssl-* 参数或等效配置,否则看起来“配好了”,其实流量还是裸奔。










