必须在服务端强制开启 require_secure_transport = on 且用户创建时明确写 require x509 或 require subject,缺一不可;仅配证书路径或仅写 require ssl 不触发客户端证书校验。

必须在服务端强制开启 require_secure_transport = ON,同时用户创建时明确写 REQUIRE X509 或更严格的 REQUIRE SUBJECT,缺一不可。只配证书路径或只写 REQUIRE SSL 都不会触发客户端证书校验。
服务端必须设 require_secure_transport = ON
这是双向验证的硬性前提——它让 MySQL 拒绝所有非 TLS 连接。不设这个,哪怕证书全对、用户也写了 REQUIRE X509,客户端仍能用 mysql -u u -p 明文连上,认证逻辑根本不会执行。
常见错误:
-
ssl_mode = REQUIRED是客户端行为参数,服务端完全不读它,不能替代require_secure_transport - 该配置必须写在
[mysqld]段,改完要重启 mysqld - 开启后,未走 TLS 的连接会直接报错
ERROR 3159 (HY000),不是密码错,而是协议被拒
用户创建必须用 REQUIRE X509 或 REQUIRE SUBJECT
GRANT ... REQUIRE X509 无效,只有 CREATE USER 或 ALTER USER 支持该语法。且 REQUIRE X509 只校验证书格式和签名链,生产环境应锁定身份。
实操要点:
- 推荐写法:
CREATE USER 'api'@'%' REQUIRE SUBJECT '/CN=api-client/OU=Service/O=MyOrg/C=CN' -
SUBJECT值必须与openssl x509 -in client-cert.pem -subject -noout输出**逐字一致**,包括大小写、字段顺序、斜杠和等号之间**不能有空格** -
ALTER USER ... REQUIRE X509会覆盖之前所有REQUIRE条件,无法叠加;想加ISSUER就得重写整条语句
客户端连接必须显式传三证书参数
mysql 命令行工具不读配置文件或系统级 SSL 设置,漏掉任一参数都会失败,且错误提示模糊(常报 Access denied 或 SSL connection error)。
最小可行命令:
mysql --ssl-mode=REQUIRED --ssl-ca=/path/to/ca.pem --ssl-cert=/path/to/client-cert.pem --ssl-key=/path/to/client-key.pem -u api -p
关键约束:
-
--ssl-mode=REQUIRED不能省,设成PREFERRED或DISABLED会导致降级为明文连接,被require_secure_transport = ON直接拒连 -
--ssl-cert和--ssl-key必须成对出现,且私钥不能加密(mysql 客户端不支持交互输密码) - 服务端若用了
REQUIRE SUBJECT,客户端证书的Subject必须严格匹配,否则握手阶段就失败
证书链验证失败是最常见的隐形卡点
MySQL 服务端不会自动信任任意客户端证书,它依赖 OpenSSL 的验证逻辑:必须能从 client-cert.pem 逐级向上验证到配置的 ca.pem(即 CA 根证书),中间不能断链。
排查建议:
- 先手动验证:
openssl verify -CAfile ca.pem client-cert.pem,不通过就别指望 MySQL 认证成功 - 如果用了中间 CA,
ca.pem必须是合并文件:根 CA 在前、中间 CA 在后,顺序不能反 - 所有 PEM 文件(
ca.pem、server-cert.pem、client-cert.pem等)属主必须是mysql用户,否则 mysqld 启动时静默失败,日志只显示Failed to set up SSL
真正起作用的是三者协同:服务端开关、用户级约束、客户端显式参数。少一个,X509 就只是个摆设。最容易被忽略的是 require_secure_transport = ON 的强制性,以及 openssl verify 这一步的手动链验证。











