外观
TiDB SSL/TLS 配置
SSL/TLS 加密是保护 TiDB 集群通信安全的重要手段。通过配置 SSL/TLS,可以加密以下通信链路:
- 客户端与 TiDB 服务器之间的通信
- TiDB 服务器与 TiKV 服务器之间的通信
- TiDB 服务器与 PD 服务器之间的通信
- TiKV 服务器之间的通信
- PD 服务器之间的通信
证书准备
1. 生成 CA 证书
在配置 SSL/TLS 之前,需要生成证书颁发机构(CA)证书和各组件证书。首先创建证书目录并生成 CA 证书:
bash
# 创建证书存储目录
mkdir -p /path/to/cert
cd /path/to/cert
# 生成 CA 私钥(2048位)
openssl genrsa -out ca.key 2048
# 生成 CA 证书请求,主题为 TiDB CA
openssl req -new -key ca.key -out ca.csr -subj "/CN=TiDB CA"
# 自签名生成 CA 证书,有效期 10 年
openssl x509 -req -days 3650 -in ca.csr -signkey ca.key -out ca.crt2. 生成服务器证书
接下来需要为 PD、TiKV 和 TiDB 组件生成服务器证书,每个证书都包含对应的域名和 IP 地址:
生成 PD 证书
为 PD 集群生成证书,包含所有 PD 节点的域名和 IP 地址:
bash
# 生成 PD 私钥(2048位)
openssl genrsa -out pd.key 2048
# 生成 PD 证书请求,包含主题和扩展信息
openssl req -new -key pd.key -out pd.csr -subj "/CN=PD Server" -config <(cat << EOF
[req]
req_extensions = v3_req
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = pd0
DNS.2 = pd1
DNS.3 = pd2
IP.1 = 10.0.1.1
IP.2 = 10.0.1.2
IP.3 = 10.0.1.3
EOF)
# 使用 CA 证书签名生成 PD 证书,有效期 10 年
openssl x509 -req -days 3650 -in pd.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out pd.crt -extensions v3_req -extfile <(cat << EOF
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = pd0
DNS.2 = pd1
DNS.3 = pd2
IP.1 = 10.0.1.1
IP.2 = 10.0.1.2
IP.3 = 10.0.1.3
EOF)生成 TiKV 证书
为 TiKV 集群生成证书,包含所有 TiKV 节点的域名和 IP 地址:
bash
# 生成 TiKV 私钥(2048位)
openssl genrsa -out tikv.key 2048
# 生成 TiKV 证书请求,包含主题和扩展信息
openssl req -new -key tikv.key -out tikv.csr -subj "/CN=TiKV Server" -config <(cat << EOF
[req]
req_extensions = v3_req
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = tikv0
DNS.2 = tikv1
DNS.3 = tikv2
IP.1 = 10.0.1.4
IP.2 = 10.0.1.5
IP.3 = 10.0.1.6
EOF)
# 使用 CA 证书签名生成 TiKV 证书,有效期 10 年
openssl x509 -req -days 3650 -in tikv.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out tikv.crt -extensions v3_req -extfile <(cat << EOF
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = tikv0
DNS.2 = tikv1
DNS.3 = tikv2
IP.1 = 10.0.1.4
IP.2 = 10.0.1.5
IP.3 = 10.0.1.6
EOF)生成 TiDB 证书
为 TiDB 集群生成证书,包含所有 TiDB 节点的域名和 IP 地址:
bash
# 生成 TiDB 私钥(2048位)
openssl genrsa -out tidb.key 2048
# 生成 TiDB 证书请求,包含主题和扩展信息
openssl req -new -key tidb.key -out tidb.csr -subj "/CN=TiDB Server" -config <(cat << EOF
[req]
req_extensions = v3_req
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = tidb0
DNS.2 = tidb1
IP.1 = 10.0.1.7
IP.2 = 10.0.1.8
EOF)
# 使用 CA 证书签名生成 TiDB 证书,有效期 10 年
openssl x509 -req -days 3650 -in tidb.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out tidb.crt -extensions v3_req -extfile <(cat << EOF
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = tidb0
DNS.2 = tidb1
IP.1 = 10.0.1.7
IP.2 = 10.0.1.8
EOF)3. 生成客户端证书
生成用于客户端连接 TiDB 的证书,客户端可以使用此证书进行双向 TLS 认证:
bash
# 生成客户端私钥(2048位)
openssl genrsa -out client.key 2048
# 生成客户端证书请求,主题为 TiDB Client
openssl req -new -key client.key -out client.csr -subj "/CN=TiDB Client"
# 使用 CA 证书签名生成客户端证书,有效期 10 年
openssl x509 -req -days 3650 -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt配置 TiDB 集群 SSL/TLS
生成证书后,需要为 TiDB 集群的各个组件配置 SSL/TLS。以下是详细的配置步骤:
1. 配置 PD 集群
修改 PD 配置文件 pd.toml,启用 TLS 加密并指定证书路径:
toml
[security]
# 启用 TLS 加密通信
ssl-enabled = true
# CA 证书文件路径,用于验证其他组件的证书
ssl-ca-path = "/path/to/cert/ca.crt"
# PD 服务器证书文件路径
ssl-cert-path = "/path/to/cert/pd.crt"
# PD 服务器私钥文件路径
ssl-key-path = "/path/to/cert/pd.key"2. 配置 TiKV 集群
修改 TiKV 配置文件 tikv.toml,需要同时配置集群内通信和客户端通信的 TLS 设置:
toml
[security]
# 启用 TiKV 集群内节点间的 TLS 加密通信
cluster-ssl-enabled = true
# 集群内通信使用的 CA 证书路径
cluster-ssl-ca-path = "/path/to/cert/ca.crt"
# 集群内通信使用的服务器证书路径
cluster-ssl-cert-path = "/path/to/cert/tikv.crt"
# 集群内通信使用的服务器私钥路径
cluster-ssl-key-path = "/path/to/cert/tikv.key"
# 启用 TiKV 客户端 TLS 加密(用于 TiDB 连接 TiKV)
ssl-enabled = true
# 客户端通信使用的 CA 证书路径
ssl-ca-path = "/path/to/cert/ca.crt"
# 客户端通信使用的服务器证书路径
ssl-cert-path = "/path/to/cert/tikv.crt"
# 客户端通信使用的服务器私钥路径
ssl-key-path = "/path/to/cert/tikv.key"3. 配置 TiDB 集群
修改 TiDB 配置文件 tidb.toml,配置客户端连接和 PD 客户端的 TLS 设置:
toml
[security]
# 客户端连接使用的 TiDB 服务器证书路径
ssl-cert = "/path/to/cert/tidb.crt"
# 客户端连接使用的 TiDB 服务器私钥路径
ssl-key = "/path/to/cert/tidb.key"
# 客户端连接使用的 CA 证书路径
ssl-ca = "/path/to/cert/ca.crt"
# 是否要求客户端必须使用安全传输(false 表示允许非加密连接)
require-secure-transport = false
[pd-client]
# TiDB 连接 PD 时使用的客户端证书路径
ssl-cert = "/path/to/cert/tidb.crt"
# TiDB 连接 PD 时使用的客户端私钥路径
ssl-key = "/path/to/cert/tidb.key"
# TiDB 连接 PD 时使用的 CA 证书路径
ssl-ca = "/path/to/cert/ca.crt"4. 使用 TiUP 部署 SSL/TLS 集群
使用 TiUP 部署支持 SSL/TLS 的 TiDB 集群,需要在拓扑文件中添加 SSL 配置:
创建包含 SSL/TLS 配置的拓扑文件 ssl-topology.yaml:
yaml
global:
user: "tidb" # 部署用户
ssh_port: 22 # SSH 端口
deploy_dir: "/tidb-deploy" # 部署目录
data_dir: "/tidb-data" # 数据目录
ssl_enabled: true # 启用全局 SSL 配置
ssl_ca: "/path/to/cert/ca.crt" # 全局 CA 证书路径
ssl_cert: "/path/to/cert/tidb.crt" # 全局证书路径(主要用于 TiDB)
ssl_key: "/path/to/cert/tidb.key" # 全局私钥路径(主要用于 TiDB)
server_configs:
pd: # PD 组件配置
security.ssl-enabled: true
security.ssl-ca-path: "/path/to/cert/ca.crt"
security.ssl-cert-path: "/path/to/cert/pd.crt"
security.ssl-key-path: "/path/to/cert/pd.key"
tikv: # TiKV 组件配置
security.cluster-ssl-enabled: true
security.cluster-ssl-ca-path: "/path/to/cert/ca.crt"
security.cluster-ssl-cert-path: "/path/to/cert/tikv.crt"
security.cluster-ssl-key-path: "/path/to/cert/tikv.key"
security.ssl-enabled: true
security.ssl-ca-path: "/path/to/cert/ca.crt"
security.ssl-cert-path: "/path/to/cert/tikv.crt"
security.ssl-key-path: "/path/to/cert/tikv.key"
tidb: # TiDB 组件配置
security.ssl-cert: "/path/to/cert/tidb.crt"
security.ssl-key: "/path/to/cert/tidb.key"
security.ssl-ca: "/path/to/cert/ca.crt"
pd-client.ssl-cert: "/path/to/cert/tidb.crt"
pd-client.ssl-key: "/path/to/cert/tidb.key"
pd-client.ssl-ca: "/path/to/cert/ca.crt"
# 集群节点配置
pd_servers:
- host: 10.0.1.1
- host: 10.0.1.2
- host: 10.0.1.3
tidb_servers:
- host: 10.0.1.7
- host: 10.0.1.8
tikv_servers:
- host: 10.0.1.4
- host: 10.0.1.5
- host: 10.0.1.6使用 TiUP 部署 SSL/TLS 集群:
bash
# 使用 TiUP 部署支持 SSL/TLS 的 TiDB 集群
tiup cluster deploy <集群名称> <TiDB版本> ssl-topology.yaml --user <部署用户> -p客户端配置 SSL/TLS 连接
配置完服务器端 SSL/TLS 后,客户端需要相应配置才能建立安全连接。以下是常见客户端的配置方法:
1. MySQL 客户端连接
使用标准 MySQL 客户端连接启用了 SSL/TLS 的 TiDB 集群:
bash
# 使用 SSL 连接 TiDB(验证服务器证书)
mysql -h <tidb-host> -P 4000 -u root --ssl-ca=/path/to/cert/ca.crt
# 使用 SSL 连接 TiDB(双向认证:验证服务器证书和提供客户端证书)
mysql -h <tidb-host> -P 4000 -u root --ssl-ca=/path/to/cert/ca.crt --ssl-cert=/path/to/cert/client.crt --ssl-key=/path/to/cert/client.key
# 强制使用 SSL 连接,不允许非加密连接
mysql -h <tidb-host> -P 4000 -u root --ssl-mode=REQUIRED --ssl-ca=/path/to/cert/ca.crt2. TiDB 客户端库配置
Go 客户端
使用 Go 语言客户端连接启用 SSL/TLS 的 TiDB 集群:
go
import (
"database/sql"
"crypto/tls"
"crypto/x509"
"io/ioutil"
"github.com/go-sql-driver/mysql"
)
func main() {
// 加载 CA 证书
caCert, err := ioutil.ReadFile("/path/to/cert/ca.crt")
if err != nil {
// 处理错误
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// 加载客户端证书和私钥
clientCert, err := tls.LoadX509KeyPair("/path/to/cert/client.crt", "/path/to/cert/client.key")
if err != nil {
// 处理错误
}
// 配置 TLS
cfg := mysql.Config{
User: "root",
Passwd: "",
Net: "tcp",
Addr: "<tidb-host>:4000",
DBName: "test",
TLSConfig: "tidb-tls", // 引用注册的 TLS 配置
}
// 注册 TLS 配置
mysql.RegisterTLSConfig("tidb-tls", &tls.Config{
RootCAs: caCertPool, // 信任的 CA 证书池
Certificates: []tls.Certificate{clientCert}, // 客户端证书
})
// 建立连接
db, err := sql.Open("mysql", cfg.FormatDSN())
// ...
}Java 客户端
使用 Java 语言客户端连接启用 SSL/TLS 的 TiDB 集群:
java
import com.mysql.cj.jdbc.MysqlDataSource;
public class TiDBSslExample {
public static void main(String[] args) throws Exception {
MysqlDataSource ds = new MysqlDataSource();
// 配置 JDBC URL,启用 SSL 并验证服务器证书
ds.setURL("jdbc:mysql://<tidb-host>:4000/test?useSSL=true&requireSSL=true&verifyServerCertificate=true&trustCertificateKeyStoreUrl=file:/path/to/cert/truststore.jks&trustCertificateKeyStorePassword=password");
ds.setUser("root");
ds.setPassword("");
// 获取连接并使用
// ...
}
}验证 SSL/TLS 配置
配置完 SSL/TLS 后,需要验证各个组件是否正常工作。以下是验证方法:
1. 验证 PD 集群
bash
# 检查 PD 是否正常监听 2379 端口(PD 默认端口)
netstat -tuln | grep 2379
# 使用 openssl 验证 PD SSL 配置是否正确
openssl s_client -connect <pd-host>:2379 -CAfile /path/to/cert/ca.crt2. 验证 TiKV 集群
bash
# 检查 TiKV 是否正常监听 20160 端口(TiKV 默认端口)
netstat -tuln | grep 20160
# 使用 openssl 验证 TiKV SSL 配置是否正确
openssl s_client -connect <tikv-host>:20160 -CAfile /path/to/cert/ca.crt3. 验证 TiDB 集群
bash
# 检查 TiDB 是否正常监听 4000 端口(TiDB 默认端口)
netstat -tuln | grep 4000
# 使用 mysql 客户端验证 SSL 连接是否成功,并查看使用的加密套件
mysql -h <tidb-host> -P 4000 -u root --ssl-ca=/path/to/cert/ca.crt -e "SHOW STATUS LIKE 'Ssl_cipher';"证书管理
证书管理是 SSL/TLS 配置的重要组成部分,包括证书有效期监控、证书轮换和证书吊销等:
1. 证书有效期监控
定期检查证书有效期,避免证书过期导致服务中断:
bash
# 检查 CA 证书有效期
openssl x509 -in /path/to/cert/ca.crt -noout -dates
# 检查 TiDB 证书有效期
openssl x509 -in /path/to/cert/tidb.crt -noout -dates
# 检查 TiKV 证书有效期
openssl x509 -in /path/to/cert/tikv.crt -noout -dates
# 检查 PD 证书有效期
openssl x509 -in /path/to/cert/pd.crt -noout -dates2. 证书轮换
当证书即将过期或需要更新时,需要进行证书轮换。证书轮换可以通过滚动更新的方式进行,避免服务中断:
生成新证书
按照之前的证书生成步骤生成新的证书,可以使用相同的 CA 或新的 CA。
滚动更新配置
使用 TiUP 进行滚动更新,依次更新 PD、TiKV 和 TiDB 组件:
滚动更新 PD 集群:
bashtiup cluster reload <cluster-name> -R pd滚动更新 TiKV 集群:
bashtiup cluster reload <cluster-name> -R tikv滚动更新 TiDB 集群:
bashtiup cluster reload <cluster-name> -R tidb
3. 吊销证书
当证书泄露或不再使用时,需要吊销证书:
bash
# 生成证书吊销列表(CRL)
openssl ca -revoke /path/to/revoked.crt -keyfile ca.key -cert ca.crt
openssl ca -gencrl -keyfile ca.key -cert ca.crt -out ca.crl
# 更新 CRL 配置
# 在各组件配置文件中添加 CRL 路径
# ssl-crl-path = "/path/to/cert/ca.crl"SSL/TLS 最佳实践
1. 证书安全管理
- 保护 CA 私钥:CA 私钥是整个证书体系的核心,必须妥善保管,限制访问权限
- 定期轮换证书:建议每 1-3 年更换一次证书,避免证书过期风险
- 严格访问控制:实施严格的证书访问控制策略,只有授权人员才能访问证书文件
- 记录证书生命周期:记录证书的创建、使用和销毁过程,便于审计和追溯
2. 性能优化
- 选择合适的密钥长度:推荐使用 2048 位或 4096 位密钥,平衡安全性和性能
- 考虑硬件加速:对于高并发场景,可以考虑使用硬件加速 SSL/TLS
- 启用会话复用:减少 TLS 握手开销,提高性能
- 优化 TLS 握手过程:调整相关参数,减少握手延迟
3. 配置建议
- 生产环境启用双向 TLS 认证:双向认证提供更高的安全性,建议在生产环境启用
- 使用安全的 TLS 版本:推荐使用 TLS 1.2 或 TLS 1.3,禁用旧版本 TLS
- 配置安全的密码套件:选择安全的密码套件,避免使用弱加密算法
- 启用证书吊销检查:及时吊销和检查无效证书,提高安全性
4. 监控与告警
- 监控证书有效期:提前 30-90 天告警,避免证书过期导致服务中断
- 监控 SSL/TLS 握手失败:及时发现和解决 SSL/TLS 配置问题
- 监控 SSL/TLS 性能指标:关注 SSL/TLS 相关性能,及时优化配置
常见问题处理
1. 证书验证失败
问题:
ERROR 2026 (HY000): SSL connection error: SSL_CTX_set_default_verify_paths failed解决方法:检查 CA 证书路径是否正确,确保证书文件权限正确(建议设置为 600)问题:
ERROR 2026 (HY000): SSL connection error: certificate verify failed解决方法:检查证书的 CN(通用名称)和 SAN( Subject Alternative Name)是否包含服务器的主机名或 IP 地址
2. 连接被拒绝
- 问题:
ERROR 2003 (HY000): Can't connect to MySQL server on '[tidb-host]' (111)解决方法:检查 SSL 配置是否正确,确保端口开放,检查防火墙规则是否允许访问
3. 性能问题
- 问题:启用 SSL/TLS 后性能下降 解决方法:优化 SSL/TLS 配置,启用会话复用,考虑使用硬件加速,调整密钥长度
常见问题(FAQ)
Q1: TiDB 支持哪些 TLS 版本?
A1: TiDB 支持 TLS 1.0、TLS 1.1、TLS 1.2 和 TLS 1.3,推荐使用 TLS 1.2 或 TLS 1.3。
Q2: 如何强制客户端使用 SSL 连接?
A2: 在 TiDB 配置文件中设置 require-secure-transport = true,这样所有客户端连接都必须使用 SSL。
Q3: 可以只对特定用户启用 SSL 吗?
A3: 是的,可以通过 MySQL 授权语句为特定用户要求 SSL:
sql
GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' REQUIRE SSL;Q4: 如何在现有集群上启用 SSL/TLS?
A4: 可以通过滚动更新的方式为现有集群启用 SSL/TLS:
- 生成证书
- 修改各组件配置文件
- 使用
tiup cluster reload滚动更新各组件
Q5: TiDB 支持双向 TLS 认证吗?
A5: 是的,TiDB 支持双向 TLS 认证,需要配置客户端证书并在服务器端启用客户端证书验证。
Q6: 如何在 Kubernetes 上配置 TiDB 集群 SSL/TLS?
A6: 在 Kubernetes 上,可以使用 cert-manager 自动管理证书,或手动创建 Secret 存储证书,然后在 TiDB Operator 配置中引用这些 Secret。
Q7: SSL/TLS 对性能有什么影响?
A7: 启用 SSL/TLS 会增加 CPU 开销,主要用于加密解密和握手过程。通过优化配置(如启用会话复用、使用硬件加速)可以减少性能影响。
Q8: 如何备份和恢复 SSL/TLS 配置?
A8: 备份证书文件和配置文件,恢复时确保证书文件路径和配置一致。建议将证书存储在安全的位置,并定期备份。
