mysql异地容灾主从复制必须启用ssl双向加密:主库需设require_secure_transport=on强制加密连接,从库change replication source to须显式指定source_ssl_ca/cert/key,复制账号必须用require subject精确绑定证书dn,三者缺一不可。

异地容灾场景下,MySQL主从复制必须启用SSL双向加密——单向验证(仅校验主库)无法防止中间人伪造从库接入主库,攻击者可冒充从库拉取全量binlog并拖库;双向加密要求主库验证从库身份,且从库也验证主库身份,缺一不可。
主库必须设 require_secure_transport=ON 且拒绝明文连接
这是整个链路的强制开关,不是“建议开启”。不加这句,即使从库配了 SOURCE_SSL=1,主库仍会静默接受明文连接,SHOW SLAVE STATUS\G 里 Slave_SSL_Allowed: Yes 看起来正常,但实际走的是裸奔 TCP。
-
require_secure_transport = ON必须写在[mysqld]段,且 MySQL 重启后生效;SET GLOBAL动态设置无效 - 确认生效:执行
SHOW VARIABLES LIKE 'require_secure_transport';,返回值必须是ON - 常见失效原因:配置文件语法错误(如漏掉等号)、写错段落(放在
[client]或[mysqldump]里)、未重启 mysqld
从库 CHANGE REPLICATION SOURCE TO 必须显式指定全部 SSL 参数
MySQL 不会自动继承主库的证书路径或默认行为,SOURCE_SSL=1 单独出现等于没写——它只是个开关标记,真正起作用的是后面成对的 CA、cert、key 路径。
- 必须提供:
SOURCE_SSL_CA(指向主库签发的 CA 根证书,即ca.pem),SOURCE_SSL_CERT和SOURCE_SSL_KEY(从库自己的客户端证书和私钥) - 示例命令(MySQL 8.0.22+):
CHANGE REPLICATION SOURCE TO SOURCE_HOST = 'master-prod.example.com', SOURCE_USER = 'repl', SOURCE_PASSWORD = 'xxx', SOURCE_SSL = 1, SOURCE_SSL_CA = '/etc/mysql/ssl/ca.pem', SOURCE_SSL_CERT = '/etc/mysql/ssl/client-cert.pem', SOURCE_SSL_KEY = '/etc/mysql/ssl/client-key.pem', SOURCE_LOG_FILE = 'mysql-bin.000001', SOURCE_LOG_POS = 154;
- 权限陷阱:所有 PEM 文件必须是
600,且mysqld进程用户(通常是mysql)能读取;用sudo -u mysql cat /etc/mysql/ssl/client-key.pem测试是否可读
复制账号必须 REQUIRE X509 或 REQUIRE SUBJECT 绑定客户端证书
只写 REQUIRE SSL 是单向验证,主库只确保连接加密,不校验对方是谁;容灾场景下必须让主库“认脸”,否则任意持有合法证书的客户端都能连上来拉 binlog。
- 创建账号时必须用
REQUIRE X509(基础双向)或更严格的REQUIRE SUBJECT '/CN=slave-beijing'(精确匹配证书 DN) - DN 字符串必须与从库证书完全一致:大小写、空格、斜杠顺序都不能错;可用
openssl x509 -in client-cert.pem -text -noout | grep Subject查看真实值 - 不要对同一账号反复执行
ALTER USER ... REQUIRE SUBJECT,后一次会覆盖前一次;如有变更,先DROP USER再重建
验证是否真正在用双向加密,别信 SHOW SLAVE STATUS 的表面字段
Slave_SSL_Allowed: Yes 只表示“允许 SSL”,不代表“正在用”;Master_SSL_Cipher 为空或为 0x00 就是降级明文。真正可靠的验证方式只有两个:
- 在主库执行
SELECT * FROM performance_schema.threads WHERE PROCESSLIST_COMMAND = 'Binlog Dump';,看SSL_CIPHER列是否非空 - 在从库所在机器抓包:
tcpdump -i any -nn -s 0 port 3306 -w repl.pcap,然后用 Wireshark 打开,过滤ssl.handshake.certificate—— 如果能看到双向证书交换记录,且后续 payload 是 TLS 加密流,才算真正生效 - 容易被忽略的点:云厂商安全组或防火墙若拦截了 TLS 握手的 ClientHello,连接会卡在 SYN-ACK 阶段,表现为
ERROR 2003 (HY000): Can't connect to MySQL server,而非 SSL 相关报错











