公网 MySQL 主从复制必须全程启用 TLS 加密,否则 binlog、账号凭证和 SQL 内容均以明文传输。主库需配置 require_secure_transport=ON 并重启,从库需在 CHANGE REPLICATION SOURCE TO 中显式指定 SOURCE_SSL_CA 等参数。
先说结论:仅配置证书不强制加密等于未锁门,必须主库强制加密、从库显式启用且验证、复制账号严格约束三者同时生效。
- 先判断:确认主库 SHOW VARIABLES LIKE 'have_ssl' 返回 YES,且 ssl_ca 路径真实可读。
- 优先做:主库 my.cnf 设置 require_secure_transport=ON 并重启,从库 CHANGE REPLICATION SOURCE TO 带全 SSL 参数。
- 再验证:检查从库 SHOW SLAVE STATUS\G 中 Slave_SSL_Allowed 为 Yes 且 Master_SSL_Cipher 非空。
命令速用版
以下命令基于 MySQL 8.0.22+ 语法,旧版本请将 SOURCE 替换为 MASTER。
\n# 主库检查 SSL 状态\nSHOW VARIABLES LIKE 'have_ssl';\n\n# 创建强制 SSL 的复制账号\nCREATE USER 'repl'@'192.168.10.5' IDENTIFIED BY 'StrongPass123!' REQUIRE SSL;\nGRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.10.5';\n\n# 从库配置加密复制\nCHANGE REPLICATION SOURCE TO\nSOURCE_HOST ='master.example.com',\nSOURCE_USER ='repl',\nSOURCE_PASSWORD ='xxx',\nSOURCE_SSL = 1,\nSOURCE_SSL_CA ='/etc/mysql/ca.pem',\nSOURCE_SSL_CERT ='/etc/mysql/client-cert.pem',\nSOURCE_SSL_KEY ='/etc/mysql/client-key.pem',\nSOURCE_LOG_FILE ='mysql-bin.000001',\nSOURCE_LOG_POS = 154;\n
为什么会这样
MySQL 主从复制默认走 TCP 明文,binlog 流中的 DML/DDL 内容甚至 SET PASSWORD 语句均可被 Wireshark 直接还原。SSL 加密的是复制协议层 I/O 线程拉取 binlog 的连接,而非 mysqld 启动时的 `--ssl-mode` 参数。若主库未设置 require_secure_transport=ON,即使从库配置了 SSL,主库仍会降级接受明文连接,导致加密失效。
分步处理
1. 生成并分发证书
使用 openssl 生成 CA 证书、主库服务端证书、从库客户端证书。所有证书文件权限必须设为 600,确保 mysqld 启动用户可读取。从库的 SOURCE_SSL_CA 必须和主库的 ssl_ca 是同一份 PEM 文件,否则握手失败。
2. 主库强制加密配置
在 [mysqld] 段配置 ssl_ca、ssl_cert、ssl_key 指向绝对路径,并添加 require_secure_transport = ON。修改配置后必须重启 mysqld,SET GLOBAL 方式无效。确认 SHOW VARIABLES LIKE 'have_ssl' 返回 YES。
3. 从库显式启用 SSL
执行 CHANGE REPLICATION SOURCE TO 时必须成对提供 SOURCE_SSL_CA、SOURCE_SSL_CERT 与 SOURCE_SSL_KEY。仅写 SOURCE_SSL = 1 毫无作用,MySQL 会静默降级回明文且不报错。
4. 复制账号约束
创建复制用户时必须加 REQUIRE SSL,并禁止用 % 通配符,明确指定从库 IP。配合系统防火墙或云安全组,只放行该 IP 的 3306 端口。
怎么验证是否生效
在从库执行 SHOW SLAVE STATUS\G,确认 Slave_SSL_Allowed 显示 Yes 且 Master_SSL_Cipher 非空。若 Master_SSL_Cipher 为空,说明实际仍走明文连接。也可在主库执行 SHOW STATUS LIKE 'Ssl_cipher' 查看当前连接加密状态。
常见坑
1. 配置未重启生效
require_secure_transport 修改后未重启 mysqld,导致从库仍可走明文连接。
2. 证书路径错误
ssl_ca 等参数错写在 [client] 段或路径非绝对路径,导致启动报 SSL error: Unable to get certificate from file。
3. 主机名校验失败
若主库用 IP 连接而证书 CN 是 localhost,需加 SOURCE_SSL_VERIFY_SERVER_CERT = 0 绕过校验,否则报 certificate verify failed。
4. 权限不足
证书文件权限未设为 600 或属主非 mysql 用户,SELinux 或 AppArmor 可能拦截读取。
常见问题
开启 SSL 后复制延迟是否明显升高
实测在千兆内网中,开启 SSL 后单线程复制延迟增加约 0.5–2ms/事件,对大多数 OLTP 场景无感。但在高并发大事务场景,CPU 可能成为瓶颈,需观察 Seconds_Behind_Master 状态。
为什么配置了 MASTER_SSL=1 还是明文
MySQL 复制客户端会静默回退到明文,必须靠 SHOW SLAVE STATUS 里 Slave_SSL_Allowed: Yes 和 Master_SSL_Cipher 非空来确认真正在用加密。漏配 CA 证书或路径错误均会导致降级。
binlog_encryption=ON 和 SSL 复制有什么区别
binlog_encryption 加密的是磁盘上的 binlog 文件,SSL 加密的是网络传输链路。两者需配合使用,仅开 binlog 加密无法防止网络抓包窃听。
参考来源
- 主从架构安全性:如何加固 MySQL 主从通信加密链路
- mysql 如何配置 SSL 加密主从传输_保证公网环境下复制安全性
- mysql 如何实现基于 SSL 的加密复制_mysql 安全链路同步配置
- MySQL 主从复制安全性如何加强_开启 SSL 加密传输保障数据安全
- mysql 加密复制_MySQL 主从复制使用 SSL 加密-CSDN 博客