Skip to content

MariaDB SSL/TLS 配置

SSL/TLS 概述

SSL(Secure Sockets Layer)和 TLS(Transport Layer Security)是用于在网络上建立安全加密连接的协议。通过配置 MariaDB 使用 SSL/TLS,可以:

  • 加密客户端和服务器之间的数据传输
  • 验证服务器身份,防止中间人攻击
  • 可选地验证客户端身份
  • 满足合规要求(如 GDPR、HIPAA 等)

MariaDB 从 5.5 版本开始支持 SSL/TLS 加密连接,并且在后续版本中不断增强和完善相关功能。

MariaDB SSL/TLS 支持

支持的协议版本

协议版本描述安全性适用场景
TLSv1.0早期 TLS 版本已过时,存在安全漏洞仅用于兼容旧客户端
TLSv1.1改进的 TLS 版本已过时,存在安全漏洞仅用于兼容旧客户端
TLSv1.2当前主流 TLS 版本安全可靠建议在生产环境中使用
TLSv1.3最新 TLS 版本更高的安全性和性能推荐在支持的环境中使用

支持的加密算法

MariaDB 支持多种加密算法,包括:

  • 密钥交换算法:RSA、DH、ECDH、ECDHE 等
  • 对称加密算法:AES-128、AES-256、ChaCha20 等
  • 哈希算法:SHA-256、SHA-384、SHA-512 等

证书准备

证书类型

  1. 自签名证书

    • 由自己生成和签名的证书
    • 适合测试环境和内部使用
    • 不被浏览器和操作系统信任
    • 成本低,易于生成
  2. CA 签名证书

    • 由可信的证书颁发机构(CA)签名的证书
    • 适合生产环境
    • 被浏览器和操作系统信任
    • 需要购买或申请

生成自签名证书

使用 OpenSSL 生成证书

bash
# 创建证书目录
mkdir -p /etc/mysql/ssl
chmod 700 /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 -out ca.pem

# 生成服务器私钥
openssl genrsa 2048 > server-key.pem

# 生成服务器证书签名请求(CSR)
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

# 生成客户端证书签名请求(CSR)
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 *.pem
chown mysql:mysql *.pem

申请 CA 签名证书

  1. 选择可信的 CA 机构(如 Let's Encrypt、DigiCert、GlobalSign 等)
  2. 生成证书签名请求(CSR)
  3. 向 CA 机构提交 CSR
  4. 验证域名所有权
  5. 下载 CA 签名证书
  6. 安装证书到 MariaDB 服务器

使用 Let's Encrypt 生成免费证书

bash
# 安装 Certbot
sudo apt-get update
sudo apt-get install certbot

# 生成证书
sudo certbot certonly --standalone -d db.example.com

# 证书位置
# 私钥:/etc/letsencrypt/live/db.example.com/privkey.pem
# 证书:/etc/letsencrypt/live/db.example.com/fullchain.pem

# 配置自动续期
crontab -e
# 添加以下行,每天凌晨 2 点检查证书是否需要续期
0 2 * * * /usr/bin/certbot renew --quiet

服务器 SSL/TLS 配置

基本配置

my.cnfmy.ini 文件中添加以下配置:

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-protocol=TLSv1.2,TLSv1.3

# 配置加密算法
ssl-cipher=TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256

# 要求客户端使用 SSL(可选)
# require_secure_transport=ON

高级配置

ini
[mysqld]
# 启用 SSL 会话缓存
ssl-session-cache-size=10m
ssl-session-cache-timeout=3600

# 配置 SSL 会话票证
ssl-session-tickets=ON

# 配置客户端证书验证级别
# ssl-verify-server-cert=ON

动态配置

可以通过 SET GLOBAL 语句动态修改部分 SSL 配置:

sql
SET GLOBAL require_secure_transport = ON;
SET GLOBAL ssl_cipher = 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256';

客户端 SSL/TLS 配置

MySQL 客户端配置

命令行客户端配置

bash
# 基本 SSL 连接
mysql -u username -p -h db.example.com --ssl

# 验证服务器证书
mysql -u username -p -h db.example.com --ssl-ca=/etc/mysql/ssl/ca.pem --ssl-verify-server-cert

# 使用客户端证书
mysql -u username -p -h db.example.com --ssl-ca=/etc/mysql/ssl/ca.pem --ssl-cert=/etc/mysql/ssl/client-cert.pem --ssl-key=/etc/mysql/ssl/client-key.pem

配置文件配置

~/.my.cnf 文件中添加以下配置:

ini
[client]
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-server-cert=1

应用程序配置

PHP (PDO)

php
$dsn = 'mysql:host=db.example.com;dbname=test;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
];

try {
    $pdo = new PDO($dsn, $username, $password, $options);
    echo "Connected successfully with SSL!";
} catch (PDOException $e) {
    die("Connection failed: " . $e->getMessage());
}

Python (MySQL Connector)

python
import mysql.connector

config = {
    'user': 'username',
    'password': 'password',
    'host': 'db.example.com',
    'database': 'test',
    '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
}

cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()
cursor.execute("SELECT @@version")
print(cursor.fetchone())
cursor.close()
cnx.close()

SSL/TLS 验证

验证服务器 SSL 配置

sql
-- 查看 SSL 配置
SHOW VARIABLES LIKE '%ssl%';

-- 查看当前连接是否使用 SSL
SHOW SESSION STATUS LIKE 'Ssl_cipher';

-- 查看所有连接的 SSL 状态
SHOW STATUS LIKE 'Ssl%';

验证客户端 SSL 连接

bash
# 使用 openssl 测试 SSL 连接
openssl s_client -connect db.example.com:3306 -CAfile /etc/mysql/ssl/ca.pem

# 使用 mysql 客户端测试 SSL 连接
mysql -u username -p -h db.example.com --ssl --execute="SHOW SESSION STATUS LIKE 'Ssl_cipher'"

SSL/TLS 最佳实践

1. 使用最新的 TLS 版本

  • 禁用过时的 SSLv2、SSLv3、TLSv1.0 和 TLSv1.1 协议
  • 优先使用 TLSv1.3,其次是 TLSv1.2
  • 定期更新 MariaDB 版本,以获取最新的 TLS 支持

2. 选择安全的加密算法

  • 使用强加密算法,如 AES-256-GCM、ChaCha20-Poly1305 等
  • 禁用弱加密算法,如 RC4、DES 等
  • 定期更新加密算法列表,以应对新的安全威胁

3. 合理配置 SSL 选项

  • 生产环境中建议启用 require_secure_transport=ON
  • 配置适当的 SSL 会话缓存,提高性能
  • 考虑启用 SSL 会话票证,进一步提高性能

4. 安全管理证书

  • 定期更换证书,避免证书过期
  • 使用强密码保护私钥
  • 限制证书文件的访问权限
  • 考虑使用证书管理工具,如 HashiCorp Vault、AWS KMS 等

5. 验证客户端身份

  • 对于敏感数据,建议启用客户端证书验证
  • 配置 MariaDB 要求客户端提供有效证书
  • 定期审查和更新客户端证书列表

6. 监控 SSL 连接

  • 监控 SSL 连接数和性能指标
  • 监控证书过期时间,提前预警
  • 记录 SSL 连接日志,便于审计和故障排查

7. 结合其他安全措施

  • 配合防火墙,限制对 MariaDB 端口的访问
  • 启用连接控制,防止暴力破解
  • 定期更新 MariaDB 和操作系统,修复安全漏洞
  • 实施最小权限原则,限制数据库用户权限

常见问题

如何查看 MariaDB 是否支持 SSL?

sql
SHOW VARIABLES LIKE 'have_ssl';

如果返回 YES,表示 MariaDB 支持 SSL。

如何查看当前连接是否使用 SSL?

sql
SHOW SESSION STATUS LIKE 'Ssl_cipher';

如果返回非空值,表示当前连接正在使用 SSL。

配置 SSL 后无法连接到 MariaDB?

解决方法

  1. 检查证书文件路径是否正确
  2. 检查证书文件权限是否正确(mysql 用户可访问)
  3. 检查证书是否过期或损坏
  4. 查看错误日志,了解具体失败原因
  5. 确保客户端和服务器使用的 TLS 版本兼容

如何强制所有连接使用 SSL?

my.cnfmy.ini 文件中添加以下配置:

ini
[mysqld]
require_secure_transport=ON

或动态设置:

sql
SET GLOBAL require_secure_transport = ON;

如何配置用户必须使用 SSL 连接?

sql
-- 创建要求 SSL 的用户
CREATE USER 'ssl_user'@'%' IDENTIFIED BY 'password' REQUIRE SSL;

-- 修改现有用户要求 SSL
ALTER USER 'existing_user'@'%' REQUIRE SSL;

-- 要求用户使用特定客户端证书
CREATE USER 'cert_user'@'%' IDENTIFIED BY 'password' REQUIRE X509;

SSL 连接会影响性能吗?

  • SSL 连接会增加一定的 CPU 开销,主要用于加密和解密数据
  • 影响程度取决于加密算法、密钥长度和服务器性能
  • 可以通过以下方式降低性能影响:
    • 使用硬件加速(如 AES-NI)
    • 配置适当的 SSL 会话缓存
    • 启用 SSL 会话票证
    • 使用高效的加密算法(如 ChaCha20-Poly1305)

如何更新 SSL 证书?

  1. 生成新的证书文件
  2. 替换旧的证书文件
  3. 重启 MariaDB 服务或动态重新加载证书
  4. 验证新证书是否正常工作

故障排除

证书验证失败

症状:客户端连接时提示 "SSL certificate validation failed"

解决方法

  1. 检查证书是否由可信 CA 签名
  2. 检查证书的 CN(Common Name)是否与服务器主机名匹配
  3. 检查证书是否过期
  4. 确保客户端信任服务器证书的 CA

协议版本不兼容

症状:客户端连接时提示 "Protocol version mismatch"

解决方法

  1. 检查客户端和服务器支持的 TLS 版本
  2. 在服务器配置中启用客户端支持的 TLS 版本
  3. 更新客户端或服务器,以支持兼容的 TLS 版本

加密算法不兼容

症状:客户端连接时提示 "No common cipher found"

解决方法

  1. 检查客户端和服务器支持的加密算法
  2. 在服务器配置中添加客户端支持的加密算法
  3. 更新客户端或服务器,以支持兼容的加密算法

结论

配置 MariaDB 使用 SSL/TLS 是保护数据库通信安全的重要措施。通过合理配置 SSL/TLS,可以加密客户端和服务器之间的数据传输,防止中间人攻击,满足合规要求。

在实施 SSL/TLS 配置时,建议使用最新的 TLS 版本和安全的加密算法,合理配置 SSL 选项,安全管理证书,并结合其他安全措施,构建多层次的安全防护体系。

定期监控和更新 SSL 配置,及时应对新的安全威胁,是确保 MariaDB SSL/TLS 连接持续安全的关键。通过实施这些最佳实践,可以显著提高 MariaDB 数据库的安全性,保护企业敏感数据。