Skip to content

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.crt

2. 生成服务器证书

接下来需要为 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.crt

2. 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.crt

2. 验证 TiKV 集群

bash
# 检查 TiKV 是否正常监听 20160 端口(TiKV 默认端口)
netstat -tuln | grep 20160

# 使用 openssl 验证 TiKV SSL 配置是否正确
openssl s_client -connect <tikv-host>:20160 -CAfile /path/to/cert/ca.crt

3. 验证 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 -dates

2. 证书轮换

当证书即将过期或需要更新时,需要进行证书轮换。证书轮换可以通过滚动更新的方式进行,避免服务中断:

生成新证书

按照之前的证书生成步骤生成新的证书,可以使用相同的 CA 或新的 CA。

滚动更新配置

使用 TiUP 进行滚动更新,依次更新 PD、TiKV 和 TiDB 组件:

  1. 滚动更新 PD 集群

    bash
    tiup cluster reload <cluster-name> -R pd
  2. 滚动更新 TiKV 集群

    bash
    tiup cluster reload <cluster-name> -R tikv
  3. 滚动更新 TiDB 集群

    bash
    tiup 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:

  1. 生成证书
  2. 修改各组件配置文件
  3. 使用 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: 备份证书文件和配置文件,恢复时确保证书文件路径和配置一致。建议将证书存储在安全的位置,并定期备份。