MySQL 8.0.16+ 支持在my.cnf的[mysqld]段配置tls_version = TLSv1.2,TLSv1.3(无空格),需重启生效;8.0.28+已彻底禁用TLSv1/TLSv1.1;验证需执行SHOW GLOBAL VARIABLES LIKE 'tls_version'及STATUS查看实际协商版本。

MySQL 8.0 服务端如何配置 tls_version
MySQL 8.0.16+ 才真正支持通过 tls_version 配置项限制协议版本;低于这个版本,该变量只读,设了也无效。必须确认版本再操作,否则白改配置。
在 my.cnf 的 [mysqld] 段中添加:
tls_version = TLSv1.2,TLSv1.3
注意:tls_version 值是逗号分隔、**无空格**的字符串;MySQL 启动时会拒绝加载含空格或非法协议名的配置。
- MySQL 8.0.28+ 已彻底移除对
TLSv1和TLSv1.1的支持,即使写进配置也会被忽略 - 若只写
TLSv1.3,需确保客户端也支持(如 OpenSSL ≥ 1.1.1,且 Java ≥ 11 或 Python 3.10+) - 修改后必须重启
mysqld,热加载不生效
如何验证 tls_version 是否生效
连上 MySQL 后执行:
SHOW GLOBAL VARIABLES LIKE 'tls_version';
返回值应与配置一致;但仅看这个不够——它只说明“服务端允许哪些协议”,不代表连接真用了哪个。
更关键的是查当前会话实际协商结果:
SELECT * FROM performance_schema.status_by_thread WHERE VARIABLE_NAME = 'Ssl_version';
或者连接后直接运行:
STATUS;
在输出里找 SSL: 行,例如 SSL: Cipher in use is TLS_AES_256_GCM_SHA384,就能确认实际用的是 TLSv1.3。
- 如果
STATUS显示SSL: Not in use,说明客户端根本没走加密通道,跟tls_version无关 -
SHOW VARIABLES查到的值可能被系统级 OpenSSL 配置覆盖(比如/etc/ssl/openssl.cnf中的MinProtocol)
为什么设了 tls_version 还连不上?常见握手失败原因
典型报错是:SSL connection error: Unsupported protocol 或 SSL handshake failed。这不是证书问题,而是协议协商卡在第一步。
- 客户端编译链接的 OpenSSL 版本太低(如 OpenSSL 1.0.2),不支持 TLSv1.3,而服务端只配了
TLSv1.3 - Java 应用未显式启用 TLSv1.2+:JDK 8 默认支持 TLSv1.2,但某些旧版 JDBC 驱动(如 mysql-connector-java < 8.0.16)默认禁用,需加参数
enabledTLSProtocols=TLSv1.2 - Python 的
pymysql或mysqlclient未传ssl={'tls_versions': ['TLSv1.2']},驱动会 fallback 到最低可用版本 - MySQL 客户端命令行工具版本过低(如 5.7.x),不支持
--tls-version参数,也无法协商 TLSv1.3
require_secure_transport=ON 是不是必须配?
不是“必须”,但它是防止降级攻击的最后一道防线。只设 tls_version 不开 require_secure_transport,攻击者仍可强制走明文连接。
启用方式:
SET PERSIST require_secure_transport = ON;
或写入 my.cnf:
require_secure_transport = ON
注意:require_secure_transport=ON 会直接拒绝所有非加密连接请求,包括本地 socket 连接(除非明确指定 --socket 并信任本地环境)。
- 开启后,老客户端(如未加
--ssl-mode=REQUIRED的 mysql 命令)会报错ERROR 3159 (HY000): Connections using insecure transport are prohibited while --require-secure-transport=ON - 某些云数据库(如 Azure DB for MySQL)要求先开
require_secure_transport,再调tls_version,顺序反了可能不生效
真正容易被忽略的是:协议限制生效的前提,是客户端和服务端至少有一个共同支持的 TLS 版本,且双方都“愿意用”。tls_version 控制服务端“能接受什么”,而客户端是否“主动要”、是否“有能力要”,得靠各自显式配置来保证——服务端再严,也管不了客户端不伸手。


















