Skip to content

Redis SSL/TLS 配置

SSL/TLS简介

什么是SSL/TLS?

SSL(Secure Sockets Layer)及其后续版本TLS(Transport Layer Security)是提供网络安全通信的加密协议。在Redis中,SSL/TLS提供:

  • 加密:保护传输中的数据不被窃听
  • 认证:验证Redis服务器和客户端的身份
  • 完整性:确保数据在传输过程中不被修改

何时使用SSL/TLS?

  • 公共网络:可通过互联网访问的Redis实例
  • 多租户环境:与其他服务共享基础设施
  • 合规要求:PCI DSS、HIPAA、GDPR等
  • 敏感数据:在Redis中存储机密信息
  • 跨区域通信:不同区域之间的数据传输

证书生成

自签名证书(用于测试)

步骤1:生成私钥

bash
openssl genrsa -out redis.key 2048

步骤2:生成证书签名请求(CSR)

bash
openssl req -new -key redis.key -out redis.csr

步骤3:生成自签名证书

bash
openssl x509 -req -days 365 -in redis.csr -signkey redis.key -out redis.crt

步骤4:验证证书

bash
openssl x509 -in redis.crt -text -noout

CA签名证书(用于生产)

步骤1:生成私钥和CSR

bash
openssl genrsa -out redis.key 2048
openssl req -new -key redis.key -out redis.csr

步骤2:向证书颁发机构提交CSR

  • 将CSR提交给受信任的CA(例如Let's Encrypt、DigiCert、Comodo)
  • 完成CA的验证过程
  • 接收签名证书和CA证书包

步骤3:安装证书

bash
# 将证书复制到适当位置
cp redis.crt /etc/redis/
cp redis.key /etc/redis/
cp ca-bundle.crt /etc/redis/

# 设置适当的权限
chown redis:redis /etc/redis/redis.crt /etc/redis/redis.key /etc/redis/ca-bundle.crt
chmod 600 /etc/redis/redis.key
chmod 644 /etc/redis/redis.crt /etc/redis/ca-bundle.crt

Redis配置

基础SSL/TLS配置

txt
# redis.conf

# 启用SSL/TLS
tls-port 6380
port 0  # 禁用非TLS端口

# 证书文件
tls-cert-file /etc/redis/redis.crt
tls-key-file /etc/redis/redis.key
tls-ca-cert-file /etc/redis/ca-bundle.crt

# 证书验证模式
tls-auth-clients no  # none, optional, required
tls-replication yes  # 为复制启用SSL
tls-cluster yes      # 为Redis Cluster启用SSL

# 密码套件配置
tls-prefer-server-ciphers yes
tls-ciphersuites TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256
tls-protocols TLSv1.2 TLSv1.3

配置参数

参数描述默认值
tls-portTLS监听端口0(禁用)
tls-cert-file服务器证书文件-
tls-key-file服务器私钥文件-
tls-ca-cert-fileCA证书包-
tls-auth-clients客户端认证模式no
tls-replication为复制启用TLSno
tls-cluster为Redis Cluster启用TLSno
tls-prefer-server-ciphers优先使用服务器密码顺序yes
tls-ciphersuitesTLS 1.3密码套件-
tls-ciphersTLS 1.2及以下版本的密码套件-
tls-protocols启用的TLS协议TLSv1.2 TLSv1.3

客户端认证

无认证

txt
tls-auth-clients no

可选认证

txt
tls-auth-clients optional

强制认证

txt
tls-auth-clients required
tls-ca-cert-file /etc/redis/ca-bundle.crt

客户端配置

使用SSL的Redis CLI

bash
# 基础SSL连接
redis-cli --tls --cert /path/to/client.crt --key /path/to/client.key --cacert /path/to/ca.crt -h redis-server -p 6380

# 带密码认证
redis-cli --tls --cert /path/to/client.crt --key /path/to/client.key --cacert /path/to/ca.crt -h redis-server -p 6380 -a your_password

编程语言客户端

Python (redis-py)

python
import redis

# SSL连接配置
ssl_config = {
    'ssl_certfile': '/path/to/client.crt',
    'ssl_keyfile': '/path/to/client.key',
    'ssl_ca_certs': '/path/to/ca.crt',
    'ssl_check_hostname': True
}

# 使用SSL连接到Redis
r = redis.Redis(
    host='redis-server',
    port=6380,
    password='your_password',
    ssl=True,
    **ssl_config
)

# 测试连接
r.ping()

Java (Jedis)

java
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.DefaultJedisSocketFactory;
import redis.clients.jedis.SSLJedisSocketFactory;

// SSL配置
SSLJedisSocketFactory sslSocketFactory = new SSLJedisSocketFactory(
    null, // TrustManagerFactory
    null, // KeyManagerFactory
    null, // password
    (hostname, session) -> hostname.equals("redis-server") // 主机名验证器
);

// Jedis连接池配置
JedisPoolConfig poolConfig = new JedisPoolConfig();
JedisPool jedisPool = new JedisPool(
    poolConfig,
    "redis-server",
    6380,
    Protocol.DEFAULT_TIMEOUT,
    "your_password",
    sslSocketFactory
);

// 使用连接
try (Jedis jedis = jedisPool.getResource()) {
    jedis.ping();
}

Node.js (ioredis)

javascript
const Redis = require('ioredis');

// SSL连接
const redis = new Redis({
  host: 'redis-server',
  port: 6380,
  password: 'your_password',
  tls: {
    key: fs.readFileSync('/path/to/client.key'),
    cert: fs.readFileSync('/path/to/client.crt'),
    ca: fs.readFileSync('/path/to/ca.crt'),
    checkServerIdentity: (host, cert) => {
      return host === cert.subject.CN;
    }
  }
});

// 测试连接
redis.ping()
  .then(() => console.log('Connected successfully'))
  .catch(err => console.error('Connection error:', err));

SSL复制配置

主节点配置

txt
# redis.conf on master
tls-port 6380
port 0
tls-cert-file /etc/redis/redis.crt
tls-key-file /etc/redis/redis.key
tls-ca-cert-file /etc/redis/ca-bundle.crt
tls-replication yes

从节点配置

txt
# redis.conf on slave
tls-port 6380
port 0
tls-cert-file /etc/redis/redis.crt
tls-key-file /etc/redis/redis.key
tls-ca-cert-file /etc/redis/ca-bundle.crt
tls-replication yes
replicaof master-ip 6380
masterauth your_password

Redis集群SSL配置

集群节点配置

txt
# redis.conf for all cluster nodes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
cluster-announce-ip <node-ip>
cluster-announce-port 6380
cluster-announce-bus-port 16380

tls-port 6380
port 0
tls-cert-file /etc/redis/redis.crt
tls-key-file /etc/redis/redis.key
tls-ca-cert-file /etc/redis/ca-bundle.crt
tls-cluster yes

创建SSL集群

bash
redis-cli --cluster create \
  --tls --cert /path/to/client.crt --key /path/to/client.key --cacert /path/to/ca.crt \
  node1:6380 node2:6380 node3:6380 node4:6380 node5:6380 node6:6380 \
  --cluster-replicas 1

监控与故障排查

检查SSL配置

bash
# 验证SSL端口正在监听
netstat -tuln | grep 6380

# 使用openssl测试SSL连接
openssl s_client -connect redis-server:6380 -CAfile /path/to/ca.crt

Redis Info SSL

bash
redis-cli --tls --cert /path/to/client.crt --key /path/to/client.key --cacert /path/to/ca.crt info server | grep tls

常见问题故障排查

证书不匹配

问题:"SSL: CERTIFICATE_VERIFY_FAILED" 错误

解决方案

  • 验证证书CN与服务器主机名匹配
  • 检查证书是否过期
  • 确保CA证书已正确安装
  • 仅在测试时禁用主机名验证

连接被拒绝

问题:使用SSL连接时出现"Connection refused"

解决方案

  • 检查tls-port配置是否正确
  • 验证Redis是否已启用SSL运行
  • 检查防火墙规则是否允许SSL端口(默认6380)
  • 确保SSL证书已正确配置

权限被拒绝

问题:读取证书文件时出现"Permission denied"

解决方案

  • 确保Redis用户对证书文件有读取权限
  • 设置正确的文件权限:chmod 600 redis.keychmod 644 redis.crt ca.crt
  • 验证证书文件归Redis用户所有:chown redis:redis *.crt *.key

性能考量

SSL开销

  • CPU使用率:SSL加密/解密会增加CPU负载
  • 延迟:SSL握手需要额外的往返次数
  • 吞吐量:最大吞吐量会略有降低

性能优化

  • 使用TLS 1.3:更快的握手和更好的加密
  • 优化密码套件:使用高效的密码,如CHACHA20_POLY1305
  • 启用会话恢复:减少重复连接的握手开销
  • 水平扩展:添加更多Redis实例来处理增加的CPU负载
  • 使用硬件加速:使用专用硬件进行SSL卸载

最佳实践

证书管理

  • 使用受信任的CA证书:生产环境避免使用自签名证书
  • 定期轮换证书:在证书过期前更换
  • 保护私钥:将私钥存储在安全位置,设置严格权限
  • 实施证书吊销:对吊销的证书使用CRL或OCSP

配置最佳实践

  • 禁用非SSL端口:使用SSL时设置port 0
  • 启用客户端认证:对敏感数据使用tls-auth-clients required
  • 使用强密码套件:配置安全的密码和协议
  • 启用主机名验证:防止中间人攻击
  • 使用一致的SSL设置:在所有节点上应用相同的SSL配置

监控与维护

  • 监控SSL连接:跟踪SSL握手失败和延迟
  • 设置证书过期警报:在证书过期前通知管理员
  • 定期测试SSL配置:在更改后验证SSL是否正常工作
  • 记录SSL设置:保留证书详情和配置记录

安全最佳实践

  • 结合其他安全措施:认证、授权、网络限制
  • 遵循最小权限原则:向Redis客户端授予最小权限
  • 定期更新Redis:使用带有安全补丁的最新版本
  • 实施网络分段:限制对Redis实例的访问

常见问题(FAQ)

Q1: Redis支持SSL/TLS吗?

A1: 是的,Redis从6.0版本开始支持SSL/TLS。早期版本需要使用stunnel或HAProxy等第三方解决方案来添加SSL支持。

Q2: SSL/TLS对Redis性能有什么影响?

A2: SSL/TLS会增加加密/解密的CPU开销,并由于SSL握手而略微增加延迟。影响因工作负载而异,但对于大多数用例,通常会降低约5-15%的性能。与旧版TLS相比,TLS 1.3减少了这种开销。

Q3: 我可以同时使用SSL和非SSL端口吗?

A3: 是的,您可以通过设置porttls-port参数来配置Redis同时监听SSL和非SSL端口。但是,出于安全原因,建议在生产环境中禁用非SSL端口。

Q4: 如何在不中断服务的情况下更新SSL证书?

A4: 要在不中断服务的情况下更新证书:

  1. 生成新的证书文件
  2. 将新证书复制到Redis服务器
  3. 如有需要,更新redis.conf中的证书文件
  4. 使用CONFIG SET在运行时重新加载证书(Redis 6.2+)
  5. 验证是否正在使用新证书

Q5: 我可以将Let's Encrypt证书与Redis一起使用吗?

A5: 是的,Let's Encrypt证书与Redis配合良好。您可以使用certbot等工具自动更新证书,并在Redis中重新加载证书而不会中断服务。

Q6: 如何为Redis Sentinel配置SSL?

A6: 要为Redis Sentinel配置SSL:

  1. 为Sentinel节点生成SSL证书
  2. 在sentinel.conf中配置SSL参数:
    txt
    tls-port 26380
    tls-cert-file /etc/redis/sentinel.crt
    tls-key-file /etc/redis/sentinel.key
    tls-ca-cert-file /etc/redis/ca-bundle.crt
    sentinel tls-replication yes
    sentinel tls-cluster yes
  3. 更新Sentinel监控配置以使用SSL端口
  4. 重启Sentinel实例

Q7: SSL需要客户端认证吗?

A7: 客户端认证是可选的,但建议用于增强安全性。您可以使用tls-auth-clients required并指定CA证书包来配置Redis要求客户端证书。