外观
MySQL 传输加密
SSL/TLS 加密配置
1. 生成 SSL/TLS 证书
自签名证书生成
bash
# 创建证书存储目录
mkdir -p /etc/mysql/ssl
cd /etc/mysql/ssl
# 生成 CA 私钥
openssl genrsa 2048 > ca-key.pem
# 生成 CA 证书
openssl req -new -x509 -nodes -days 3650 -key ca-key.pem > ca.pem
# 生成服务器私钥
openssl genrsa 2048 > server-key.pem
# 生成服务器证书请求
openssl req -new -key server-key.pem -out server-req.pem
# 生成服务器证书
openssl x509 -req -in server-req.pem -days 3650 -CA ca.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem
# 生成客户端私钥
openssl genrsa 2048 > client-key.pem
# 生成客户端证书请求
openssl req -new -key client-key.pem -out client-req.pem
# 生成客户端证书
openssl x509 -req -in client-req.pem -days 3650 -CA ca.pem -CAkey ca-key.pem -set_serial 02 > client-cert.pem
# 转换私钥格式(可选)
openssl rsa -in server-key.pem -out server-key.pem
openssl rsa -in client-key.pem -out client-key.pem
# 设置权限
chmod 600 *-key.pem
chown mysql:mysql *商业证书配置
- 从证书颁发机构(CA)获取商业证书
- 将证书文件上传到服务器
- 确保证书文件权限正确
2. MySQL 服务器 SSL 配置
配置文件设置
ini
[mysqld]
# SSL 配置
ssl-ca=/etc/mysql/ssl/ca.pem
ssl-cert=/etc/mysql/ssl/server-cert.pem
ssl-key=/etc/mysql/ssl/server-key.pem
# 强制客户端使用 SSL(可选)
# require_secure_transport=ON
# 禁用旧版加密协议
ssl-cipher=DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256重启 MySQL 服务
bash
# 重启 MySQL 服务
systemctl restart mysqld验证 SSL 配置
sql
-- 查看 SSL 配置状态
SHOW VARIABLES LIKE '%ssl%';
-- 验证 SSL 证书
SHOW STATUS LIKE 'Ssl_cipher';客户端 SSL 连接配置
1. MySQL 命令行客户端
bash
# 使用 SSL 连接(不验证服务器证书)
mysql -u root -p --ssl
# 使用 SSL 连接并验证服务器证书
mysql -u root -p --ssl-ca=/etc/mysql/ssl/ca.pem --ssl-cert=/etc/mysql/ssl/client-cert.pem --ssl-key=/etc/mysql/ssl/client-key.pem
# 强制使用 SSL
mysql -u root -p --ssl-mode=REQUIRED2. 应用程序连接配置
Java 应用(JDBC)
java
// JDBC URL 配置
String url = "jdbc:mysql://localhost:3306/mydb?useSSL=true&requireSSL=true&verifyServerCertificate=true&serverTimezone=UTC";
// 加载证书
System.setProperty("javax.net.ssl.trustStore", "/path/to/truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "password");
// 建立连接
Connection conn = DriverManager.getConnection(url, username, password);Python 应用(MySQL Connector/Python)
python
import mysql.connector
# 配置 SSL 连接
cnx = mysql.connector.connect(
host="localhost",
user="root",
password="password",
database="mydb",
ssl_ca="/etc/mysql/ssl/ca.pem",
ssl_cert="/etc/mysql/ssl/client-cert.pem",
ssl_key="/etc/mysql/ssl/client-key.pem",
ssl_verify_cert=True
)PHP 应用(PDO)
php
// PDO 配置
$dsn = "mysql:host=localhost;dbname=mydb;charset=utf8mb4";
$options = [
PDO::MYSQL_ATTR_SSL_CA => "/etc/mysql/ssl/ca.pem",
PDO::MYSQL_ATTR_SSL_CERT => "/etc/mysql/ssl/client-cert.pem",
PDO::MYSQL_ATTR_SSL_KEY => "/etc/mysql/ssl/client-key.pem",
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => true
];
// 建立连接
$pdo = new PDO($dsn, $username, $password, $options);加密协议与 cipher 选择
1. 加密协议选择
- TLS 1.3:推荐使用,提供更好的安全性和性能
- TLS 1.2:兼容模式,支持较旧的客户端
- 禁用 TLS 1.1 及以下:这些协议存在安全漏洞
2. 安全 cipher 套件
ini
# 推荐的 cipher 套件配置
ssl-cipher=ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA3843. 配置示例
ini
[mysqld]
# 启用 TLS 1.2 和 1.3
tls_version=TLSv1.2,TLSv1.3
# 配置安全 cipher 套件
ssl-cipher=ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384证书管理
1. 证书有效期监控
sql
-- 查看证书有效期
SHOW STATUS LIKE 'Ssl_server_not_after';2. 证书轮换
服务器证书轮换
- 生成新的服务器证书
- 更新 MySQL 配置文件
- 重启 MySQL 服务
- 验证新证书生效
客户端证书轮换
- 生成新的客户端证书
- 分批次更新客户端配置
- 验证客户端连接正常
3. 证书撤销
- 维护证书撤销列表(CRL)
- 配置 MySQL 使用 CRL
ini
[mysqld]
# 配置 CRL
ssl-crl=/etc/mysql/ssl/ca-crl.pem加密性能优化
1. 硬件加速
- 确保服务器支持 AES-NI 硬件加速
- 验证硬件加速是否启用
bash
# 检查 AES-NI 支持
grep -m1 -o aes /proc/cpuinfo2. 连接池配置
- 使用连接池减少 SSL 握手开销
- 调整连接池参数优化性能
3. 选择性加密
- 对于内部网络通信,可根据安全需求决定是否启用加密
- 对于外部网络通信,强制使用加密
安全最佳实践
1. 证书安全
- 定期更换证书(建议每年)
- 使用强密钥长度(至少 2048 位)
- 保护私钥文件不被未授权访问
- 使用商业 CA 证书或内部 CA 基础设施
2. 配置安全
- 强制客户端使用 SSL 连接
- 禁用旧版加密协议
- 使用安全的 cipher 套件
- 定期审计 SSL 配置
3. 监控与审计
- 监控 SSL 连接状态
- 审计 SSL 配置变更
- 记录 SSL 连接日志
常见问题(FAQ)
Q1: 如何验证 MySQL 连接是否使用了 SSL?
A1: 可以通过以下方式验证:
sql
-- 方法1:查看连接状态
SHOW STATUS LIKE 'Ssl_cipher';
-- 方法2:查看会话变量
SELECT @@session.ssl_cipher;
-- 方法3:从客户端验证
mysql -u root -p -e "status" | grep SSLQ2: 启用 SSL 会影响 MySQL 性能吗?
A2: 启用 SSL 会带来一定的性能开销,主要体现在:
- SSL 握手过程的额外开销
- 数据加密和解密的 CPU 消耗
但在现代硬件上,这种开销通常在可接受范围内,特别是启用硬件加速后。对于对安全性要求高的场景,建议启用 SSL。
Q3: 如何强制所有客户端使用 SSL 连接?
A3: 可以通过以下两种方式:
在配置文件中设置:
ini[mysqld] require_secure_transport=ON为用户设置 REQUIRE SSL 选项:
sqlALTER USER 'user'@'host' REQUIRE SSL;
Q4: 如何配置 MySQL 复制使用 SSL?
A4: 主从复制使用 SSL 的配置步骤:
- 在主从服务器上都配置 SSL
- 在主服务器上创建复制用户并要求 SSL:sql
CREATE USER 'repl'@'slave_host' IDENTIFIED BY 'password' REQUIRE SSL; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'slave_host'; - 在从服务器上配置复制连接使用 SSL:sql
CHANGE MASTER TO MASTER_HOST='master_host', MASTER_USER='repl', MASTER_PASSWORD='password', MASTER_SSL=1, MASTER_SSL_CA='/etc/mysql/ssl/ca.pem', MASTER_SSL_CERT='/etc/mysql/ssl/client-cert.pem', MASTER_SSL_KEY='/etc/mysql/ssl/client-key.pem';
Q5: 如何处理 SSL 证书过期问题?
A5: 处理证书过期的建议:
- 提前监控证书有效期,设置告警
- 在证书过期前生成新证书
- 制定证书轮换计划,避免业务中断
- 对于集群环境,分批次更新证书
Q6: 可以同时支持加密和非加密连接吗?
A6: 是的,MySQL 支持同时处理加密和非加密连接。可以通过以下方式配置:
- 不设置
require_secure_transport=ON - 为需要加密的用户设置
REQUIRE SSL - 其他用户可以选择是否使用 SSL 连接
Q7: 如何选择合适的加密协议版本?
A7: 加密协议版本选择建议:
- 优先使用 TLS 1.3,提供最好的安全性和性能
- 兼容模式下同时支持 TLS 1.2 和 TLS 1.3
- 禁用 TLS 1.1 及以下版本,这些协议存在安全漏洞
Q8: 自签名证书和商业证书有什么区别?
A8: 主要区别:
| 特性 | 自签名证书 | 商业证书 |
|---|---|---|
| 颁发机构 | 自己生成 | 可信 CA 机构 |
| 信任度 | 需要手动信任 | 被广泛信任 |
| 成本 | 免费 | 收费 |
| 有效期 | 可自定义 | 通常 1-3 年 |
| 适用场景 | 内部测试、开发环境 | 生产环境、对外服务 |
Q9: 如何配置 MySQL Workbench 使用 SSL 连接?
A9: MySQL Workbench SSL 配置步骤:
- 打开 MySQL Workbench
- 新建或编辑连接
- 在"SSL"标签页中:
- 选择"Require SSL"
- 浏览并选择 CA 证书、客户端证书和客户端私钥文件
- 测试连接,确认 SSL 连接成功
Q10: 启用 SSL 后如何排查连接问题?
A10: 排查 SSL 连接问题的方法:
- 检查 MySQL 错误日志
- 验证证书文件权限和路径
- 验证证书有效期和完整性
- 检查加密协议和 cipher 套件配置
- 使用
openssl s_client测试 SSL 连接:bashopenssl s_client -connect localhost:3306 -CAfile /etc/mysql/ssl/ca.pem - 检查客户端 SSL 配置是否正确
案例分析
案例1:生产环境 SSL 配置
场景描述
某金融机构需要为生产环境的 MySQL 数据库启用 SSL 加密,确保客户端与服务器之间的通信安全。
解决方案
证书管理:
- 使用内部 CA 基础设施生成证书
- 配置证书有效期为 2 年
- 建立证书轮换机制
服务器配置:
ini[mysqld] ssl-ca=/etc/mysql/ssl/ca.pem ssl-cert=/etc/mysql/ssl/server-cert.pem ssl-key=/etc/mysql/ssl/server-key.pem tls_version=TLSv1.2,TLSv1.3 ssl-cipher=ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384 require_secure_transport=ON客户端配置:
- 所有应用程序配置 SSL 连接
- 使用连接池减少 SSL 握手开销
- 定期更新客户端证书
监控与审计:
- 监控证书有效期
- 审计 SSL 连接日志
- 定期检查 SSL 配置
实施效果
- 所有客户端连接强制使用 SSL 加密
- 加密通信性能开销控制在 5% 以内
- 满足金融行业合规要求
- 提高了数据传输的安全性
案例2:复制架构 SSL 配置
场景描述
某电商平台的 MySQL 主从复制架构需要启用 SSL 加密,确保主从服务器之间的数据传输安全。
解决方案
证书配置:
- 在主从服务器上部署相同的 CA 证书
- 为主从服务器分别生成证书
主服务器配置:
sql-- 创建复制用户并要求 SSL CREATE USER 'repl'@'%' IDENTIFIED BY 'strong_password' REQUIRE SSL; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';从服务器配置:
sql-- 配置复制连接使用 SSL CHANGE MASTER TO MASTER_HOST='master.example.com', MASTER_USER='repl', MASTER_PASSWORD='strong_password', MASTER_SSL=1, MASTER_SSL_CA='/etc/mysql/ssl/ca.pem', MASTER_SSL_CERT='/etc/mysql/ssl/client-cert.pem', MASTER_SSL_KEY='/etc/mysql/ssl/client-key.pem';验证配置:
sql-- 在从服务器上验证 SSL 复制 SHOW SLAVE STATUS\G
实施效果
- 主从复制通信使用 SSL 加密
- 复制延迟无明显增加
- 提高了复制架构的安全性
- 满足了合规要求
