mysql ssl加密连接需同时满足三个条件:服务端have_ssl=yes、用户权限显式声明require ssl、客户端连接时真实触发tls握手,缺一不可。

MySQL SSL 加密连接不是“配完证书就自动生效”,必须同时满足三个硬性条件:服务端 have_ssl = YES、用户权限显式声明 REQUIRE SSL、客户端连接时真实触发 TLS 握手。漏掉任一环,连接仍走明文。
确认 MySQL 已真正启用 SSL 支持
很多配置失败的根源是服务端根本没加载 SSL 模块。登录 MySQL 后直接执行:
SHOW VARIABLES LIKE 'have_ssl';
如果返回 DISABLED 或空值,说明 mysqld 启动时未链接 OpenSSL(常见于 MariaDB 精简版、或编译时未加 -DWITH_SSL=system)。此时即使写了 ssl_ca 配置也完全无效。
-
have_ssl = YES是一切的前提,否则后续所有操作都是空转 - 顺带检查
SHOW VARIABLES LIKE 'tls_version';,确认支持的协议(如TLSv1.2),旧客户端连不上时可能需临时放宽 - 若为
DISABLED,优先重装官方 MySQL 二进制包(自带 OpenSSL 支持),不建议自行编译修复
生成并放置证书:路径、权限、命名都不能错
MySQL 只认绝对路径,且证书文件必须由 mysql 用户可读(server-key.pem 还必须是 600)。相对路径、~/、权限过宽都会导致启动失败或连接被拒。
- 推荐用内置工具生成(MySQL 8.0+):
mysql_ssl_rsa_setup --datadir=/var/lib/mysql --uid=mysql,比手写 OpenSSL 命令更稳妥(避免 CN 不匹配等坑) - 证书必须放在
mysql用户可读目录,例如/var/lib/mysql/ca.pem,不能放/home/deploy/ssl/ - 检查权限:
sudo -u mysql ls -l /var/lib/mysql/ca.pem /var/lib/mysql/server-key.pem,server-key.pem必须是-rw------- - 配置文件中必须写死绝对路径:
ssl_ca = /var/lib/mysql/ca.pem,不能省略开头的/
用户权限必须显式绑定 REQUIRE SSL
REQUIRE SSL 不是全局开关,而是写在每个用户的权限记录里。MySQL 8.0.21 及更早版本不支持对已有用户追加该要求,只能重建用户。
- 新建用户:
CREATE USER 'app'@'%' IDENTIFIED BY 'pwd' REQUIRE SSL; - 修改已有用户(仅限 MySQL ≥ 8.0.22):
ALTER USER 'app'@'%' REQUIRE SSL; - 验证是否生效:
SELECT user, host, ssl_type FROM mysql.user WHERE user = 'app';,ssl_type应为ANY - 注意:
localhost连接默认走 Unix socket,绕过所有 SSL 限制;测试务必用127.0.0.1或远程 IP
客户端连接必须主动发起 TLS 握手
绝大多数客户端驱动(JDBC、pymysql、mysql-client)默认关闭 SSL 握手。哪怕服务端强制了 REQUIRE SSL,客户端不发 Client Hello,连接照样降级为明文。
- JDBC 示例连接串需显式开启:
jdbc:mysql://host:3306/db?useSSL=true&requireSSL=true&trustCertificateKeyStoreUrl=file:/path/to/ApsaraDB-CA-Chain.jks&trustCertificateKeyStorePassword=apsaradb - pymysql 示例:
pymysql.connect(..., ssl={'ca': '/path/to/ca.pem'}) - 命令行测试:
mysql -u app -p --ssl-ca=/path/to/ca.pem --ssl-mode=REQUIRED -h 127.0.0.1 - 务必确认连接后执行
STATUS或查SHOW STATUS LIKE 'Ssl_cipher';,非空才表示真加密
最容易被忽略的是:证书文件存在 ≠ SSL 生效;用户建了 REQUIRE SSL ≠ 客户端真走加密;have_ssl = YES ≠ 所有连接都加密——每一步都得单独验证,缺一不可。











