mysql数据库中使用SSL加密连接与安全配置

来源:这里教程网 时间:2026-02-28 20:52:00 作者:

MySQL 客户端连接报错
SSL connection error: protocol version mismatch
怎么办

这个错误通常不是 SSL 本身没启用,而是客户端和服务端支持的 TLS 协议版本不一致。MySQL 5.7 默认最低启用

TLSv1.2
,而旧版 MySQL 客户端(如 5.6 或某些嵌入式驱动)可能只支持
TLSv1.0
,握手直接失败。

检查服务端支持的协议:
SHOW VARIABLES LIKE 'tls_version';
返回值类似
TLSv1.2,TLSv1.3
表示仅允许这两个版本
临时放宽服务端限制(仅测试用):
SET PERSIST tls_version='TLSv1,TLSv1.1,TLSv1.2,TLSv1.3';
注意
SET PERSIST
会写入
mysqld-auto.cnf
,重启后仍生效
生产环境更推荐升级客户端驱动:比如 Python 的
pymysql
需 ≥1.0.2,
mysql-connector-python
需 ≥8.0.23;Java 的
mysql-connector-j
需 ≥8.0.29
不要在命令行用
--ssl-mode=DISABLED
绕过——这等于放弃加密,不是解决问题,是掩盖问题

如何验证当前连接是否真的走 SSL

即使加了

--ssl-mode=REQUIRED
,也不代表一定加密成功。MySQL 会静默降级到非加密连接(尤其当服务端未正确配置证书时),必须主动确认。

连接后立即执行:
STATUS;
查看输出中
SSL:
一行,若显示
Cipher in use is AES256-SHA
类似内容,说明已加密;若为
Not in use
,则未启用
更可靠的方式是查会话变量:
SELECT * FROM performance_schema.status_by_thread WHERE variable_name = 'Ssl_cipher';
非空值才表示当前连接使用了 SSL 加密
注意:
SHOW STATUS LIKE 'Ssl%';
显示的是全局累计统计,不能反映单个连接状态,容易误判

require_secure_transport=ON
是不是一劳永逸的安全开关

这个系统变量确实能强制所有新连接必须使用 SSL/TLS,但它不是银弹,有明确前提和副作用。

必须确保所有合法客户端都支持并配置了 SSL,否则运维账号、备份脚本、监控探针全部连不上,直接导致服务中断 它只控制 TCP 连接,对本地 socket 连接(
localhost
)无效——因为 Unix socket 不经过网络层,SSL 不适用
开启后,
GRANT ... REQUIRE SSL
类语句变得冗余,但已有用户权限不会自动更新,需手动清理非 SSL 用户或重置权限
某些云数据库(如 AWS RDS、阿里云 RDS)默认已设为
ON
,但提供专用的 CA 证书和连接串模板,不要自行替换证书路径

自签名证书在生产环境能不能用

能连上,但不建议。核心问题是信任链断裂带来的两类风险:中间人攻击无法识别 + 应用层校验逻辑易出错。

MySQL 客户端默认不校验证书域名(不像浏览器),所以
subjectAltName
为空或不匹配也不会报错,只要证书格式正确就接受
Python 示例中若用
ssl_disabled=False
但没传
ssl_ca
,实际仍走加密但不验签,等同于“裸 TLS”
真正安全的做法是:用私有 CA 签发服务端证书,并把该 CA 证书分发给所有客户端,在连接时显式指定
ssl_ca='/path/to/ca.pem'
如果用 Let’s Encrypt,注意其证书有效期仅 90 天,且 MySQL 不支持 OCSP stapling,需配合定期 reload 证书的运维流程

MySQL 的 SSL 配置关键不在“有没有”,而在“验不验”和“降不降级”。最常被忽略的是应用代码里没传

ssl_ca
却以为自己已经安全,或者 DBA 开了
require_secure_transport
却没同步通知所有依赖方——这两类疏漏,比证书过期更难排查。

相关推荐