Mysql配置ssl证书
Mysql8主从配置ssl证书,openssl配置ssl证书
一、证书介绍
MySQL8 生成 SSL 证书主要有3 种方式,具体如下:
自动生成(推荐新手):MySQL 8 在启动时会自动检测数据目录(datadir)下是否缺少
ca.pem、server-cert.pem、server-key.pem等 SSL 文件。如果缺失且未指定 SSL 相关启动参数,服务器会自动生成一套自签名证书和密钥文件,包括ca.pem、server-cert.pem、server-key.pem、client-cert.pem、client-key.pem等。这种方式最省事,但生成的证书是自签名的,安全性相对较低,证书中没有对应的 SAN(Subject Alternative Name)。使用
mysql_ssl_rsa_setup命令生成:MySQL 8 自带的工具,执行mysql_ssl_rsa_setup --datadir=/var/lib/mysql --uid=mysql即可在数据目录下生成所需的证书和密钥文件,文件列表与自动生成方式一致。这是最简单、最标准的生成自签名证书的方法。它会自动生成 CA 证书、服务器证书和密钥,以及 RSA 密钥对(用于安全密码交换),这种方式生成的SSL证书不带主机名,适用于内部加密传输、不严格校验主机名的客户端连接。现代许多客户端库(如 Java 的 JDBC Driver、Python 的mysql-connector-python或 Go 的驱动)在进行 SSL 握手时,会严格校验服务器证书中的主机名。如果客户端通过 IP 地址(如192.168.1.100)或特定域名连接,而证书中既没有对应的 SAN,CN 也不是该 IP/域名(CN 是固定的长字符串),客户端可能会抛出类似ERROR 2026 (HY000): SSL connection error: error:0A000086:SSL routines::certificate verify failed或Certificate doesn't match的错误。**mysql_ssl_rsa_setup从 MySQL 8.0.34 开始被标记为弃用(deprecated),在 8.0.34 及后续 8.0.x 版本中仍可使用,但会提示弃用警告,官方建议不再依赖它。推荐使用 OpenSSL。**使用 OpenSSL 命令手动生成(适用于生产环境/自定义CA/等保):完全通过
openssl命令生成 CA 证书、服务器证书和客户端证书,可以自定义证书的有效期、密钥长度和扩展属性。这种方式灵活性最高,适合需要定制证书信息或满足特定安全要求的场景。
兼容性建议:
- 开发/测试环境:通常可以将客户端的 SSL 验证模式设置为
VERIFY_CA或PREFERRED,而不是严格的VERIFY_IDENTITY,这样可以绕过主机名匹配检查,仅验证证书是否由可信 CA 签发。 - 生产环境:如果需要严格的主机名验证(
VERIFY_IDENTITY),不建议使用mysql_ssl_rsa_setup生成的证书。应使用 OpenSSL 手动生成包含正确 SAN(如DNS:mydb.example.com,IP:192.168.1.100)的证书,或者使用 Let’s Encrypt 等公共 CA 签发的证书。
证书要求:
server-key.pem权限必须为600,属主mysql- 证书路径用绝对路径,且
mysqld进程用户可读,如果证书放置在mysql数据目录下,则可以不使用绝对路径 - 证书 CN 或 SAN 要包含主库实际访问地址(IP 或域名),否则握手会报证书校验失败
- 从库作为客户端连接时,也需要
ca.pem(CA 证书),把主库的client-cert.pem、client-key.pem一并拷贝过去
证书权限:
1 | 🔸确保所有 pem 文件属主为 mysql: |
SSL证书服务器名称解析机制:
SSL/TLS协议中的服务器名称验证是确保安全连接的关键环节。根据RFC 6125(通用服务器身份验证规范)和其前身RFC 2818(HTTPS特定规范),主机名验证遵循明确的优先级规则。当证书包含Subject Alternative Names(SAN)扩展时,系统必须优先使用SAN中的dNSName(域名)或iPAddress(IP地址)进行匹配。只有在SAN扩展不存在的情况下,才会回退到使用Common Name(CN)字段。
浏览器与Java实现的差异:
浏览器在处理证书验证时通常表现出更大的灵活性。许多浏览器实现会同时检查CN字段和SAN扩展,甚至在CN字段包含有效主机名时可能忽略SAN的缺失。这种宽松的实现方式源于历史兼容性考虑和RFC 2818中”most specific Common Name”定义的模糊性。
相比之下,Java的安全实现更加严格地遵循规范。从Java 7开始,sun.security.util.HostnameChecker类明确要求:当连接使用主机名时,证书必须包含匹配的dNSName SAN;当连接使用IP地址时,证书必须包含匹配的iPAddress SAN。如果缺少相应的SAN扩展,即使CN字段包含正确的主机名或IP地址,验证也会失败并抛出java.security.cert.CertificateException: No subject alternative names present异常。
SSL证书的主机名位置:
SSL证书的主机名不在server.key里,也不在CA证书里,而是在服务器证书(server.crt)的Subject字段(CN)或SAN扩展字段里。
简单说:
- server.key(私钥):只存密钥,不含主机名信息。
- ca.crt(CA根证书):是签发机构自己的证书,里面是CA的主机名,跟你的服务器主机名无关。
- server.crt(服务器证书):这才是关键。客户端校验主机名时,看的是这张证书里的 CN(Common Name)和 SAN(Subject Alternative Name)字段。
需要注意:现代浏览器和HTTP客户端主要校验SAN,CN只作为备用;如果证书里有SAN但没覆盖你访问的主机名,即使CN匹配也会报错。
生成证书时,确保:
🔸CN 填服务器主机名或IP,比如 server.example.com。
🔸SAN 通过 subjectAltName 显式声明域名和IP,比如 DNS:server.example.com, IP:192.168.1.100
二、mysql_ssl_rsa_setup生成ssl证书
1.创建ssl证书目录(主库和从库)
1 | mkdir /etc/mysql/ssl |
2.生成ssl证书(主库和从库)
1 | mysql_ssl_rsa_setup --datadir=/etc/mysql/ssl --uid=mysql |
3.配置my.cnf(主库和从库)
1 | 如果使用mysql自带的证书可以使用相对路径: |
4.重启数据库(主库和从库)
1 | systemctl restart mysql |
5.检查并验证ssl连接(主库和从库)
1 | SHOW VARIABLES LIKE 'have_ssl'; -- 必须为 YES |
6.复制帐号强制SSL(主库)
1 | mysql> select user,host from mysql.user; |
7.将主库ssl证书传输至从库(从库)
1 | # mkdir /etc/mysql/ssl_client |
8.从库连接主库测试ssl连接(从库)
1 | # mysql -urepl -p -h192.168.1.111 --ssl-ca=/etc/mysql/ssl_client/ca.pem --ssl-mode=VERIFY_CA |
9.停止复制(从库)
1 | mysql> stop replica; |
10.change replication source to(从库)
使用
CHANGE REPLICATION SOURCE TO(MySQL 8.0.22+) 或CHANGE MASTER TO(旧版) 显式指定 SSL 参数,change replication source to必须带上SSL参数,重要:必须提供SOURCE_SSL_CA以验证主库身份,防止中间人攻击。
1 | 如果主库的自签名证书缺失Subject Alternative Name (SAN)字段,MySQL 8.0.23+(尤其是 8.0.28+)在严格模式下会拒绝连接或导致 SSL 握手失败。 |
11.启动复制(从库)
1 | START REPLICA; |
12.检查复制状态(从库)
1 | SHOW REPLICA STATUS\G |
关键字段必须是:
Slave_IO_Running: YesSlave_SQL_Running: YesMaster_SSL_Allowed: YesMaster_SSL_Cipher非空(显示具体加密算法,如ECDHE-ECDSA-AES256-SHA384)
如果 Master_SSL_Allowed: No,说明 SSL 参数没传全,复制已静默回退到明文。
如果 Master_SSL_Allowed 为 No 或 Master_SSL_Cipher 为空,说明连接未加密,需检查从库的 CHANGE REPLICATION SOURCE TO 语句是否正确执行。
辟坑指南:
- 证书权限不对:
server-key.pem不是 600 权限时,MySQL 启动会静默忽略 SSL 配置,Ssl_cipher始终为空 - CA 不一致:从库
SOURCE_SSL_CA必须和主库ssl_ca是同一份文件,否则报SSL error: certificate verify failed - SELinux 拦截:日志出现
SSL_CTX_set_default_verify_paths failed,可临时sudo setenforce 0验证,长期需打 SELinux 策略 - 证书 CN 不匹配:证书 CN/SAN 必须包含主库实际访问的 IP 或域名,否则
X509_V_ERR_IP_ADDRESS_MISMATCH
- **客户端连接报错
certificate verify failed**:多半是连接的主机名和证书 CN/SAN 不匹配,自签名证书默认只含localhost和127.0.0.1,连 IP 要重新生成证书。
- **Java 程序连接报
Path does not chain**:需要把ca.pem导入 Java 的信任库(keytool -importcert)。 - SELinux 拦截:日志出现
SSL_CTX_set_default_verify_paths failed时,需要调整文件上下文或临时setenforce 0排查。
三、Openssl生成ssl证书
OPenssl配置ssl与mysql_ssl_rsa_setup的流程大体一致,以下仅列出不同之处
1.生成ssl证书(主库和从库)
1 | 🔹1.创建证书目录(建议与MySQL数据目录分离) |
2.从库连接主库测试ssl连接(从库)
1 | # mysql -urepl -p -h192.168.1.111 --ssl-ca=/etc/mysql/ssl_client/ca.pem --ssl-mode=VERIFY_IDENTITY |
3.change replicatioin source to
1 | CHANGE REPLICATION SOURCE TO |
- Title: Mysql配置ssl证书
- Author: 𝓓𝓸𝓷
- Created at : 2026-10-15 16:48:08
- Updated at : 2026-10-15 17:49:06
- Link: https://www.zhangdong.me/mysql_configuration_ssl_certificate.html
- License: This work is licensed under CC BY-NC-SA 4.0.
