Redis 以高性能著称,但默认配置在生产环境中存在显著安全缺口:无认证、明文传输、无访问隔离。本文从威胁模型出发,系统讲解密码认证、ACL 权限体系、TLS 加密、网络加固、命令重命名、审计日志与 CVE 修复,帮助你构建一套可落地的 Redis 生产安全基线。
一、Redis 安全威胁模型:默认无认证风险
1.1 默认配置的危险性
Redis 默认配置存在以下安全隐患:
- 无认证要求:默认
requirepass为空,无需密码即可连接 - 监听所有接口:默认
bind 0.0.0.0,可从任意网络位置访问 - 明文传输:通信数据未加密,可被网络嗅探截获
- 无权限隔离:所有客户端拥有全部命令执行权限
- 危险命令开放:
FLUSHALL、CONFIG、DEBUG等命令可直接执行
1.2 常见攻击向量
+-------------------------------------------------------------+
| Redis 攻击向量 |
+-------------------------------------------------------------+
| 1. 未授权访问 -> 直接连接6379端口,读写/删除所有数据 |
| 2. 命令注入 -> 通过 Redis 写入恶意 SSH 公钥或 WebShell |
| 3. 网络嗅探 -> 抓取明文传输的数据包获取敏感信息 |
| 4. 内部横向 -> 拿到一台服务器权限后扫描内网 Redis 实例 |
| 5. 配置篡改 -> 修改持久化路径实现任意文件写入 |
| 6. 拒绝服务 -> FLUSHALL / KEYS * / DEBUG SEGFAULT |
+-------------------------------------------------------------+
1.3 安全加固三原则
- 最小权限:每个应用/服务使用独立用户,只授予必要命令权限
- 传输加密:所有跨网络通信必须启用 TLS/SSL
- 纵深防御:网络层(防火墙/VPC)+ 应用层(ACL/密码)+ 审计层(日志)多管齐下
二、密码认证:requirepass / masterauth
Redis 提供了最基本的密码认证机制,适用于 Redis 6.0 之前的单用户场景,或与 ACL 搭配作为兜底方案。
2.1 设置访问密码
在 redis.conf 中配置:
# 设置服务器连接密码
requirepass "MyStr0ngP@ssw0rd!2026"
# 如果该实例是副本,配置主库认证密码
masterauth "MyStr0ngP@ssw0rd!2026"
注意:
requirepass设置后,所有客户端必须使用AUTH password登录,否则只能执行少数几个命令(AUTH、HELLO、PING、QUIT)。
2.2 动态修改密码
# 在线修改密码(立即生效,不重启)
redis-cli AUTH MyStr0ngP@ssw0rd!2026
redis-cli CONFIG SET requirepass "NewStr0ngP@ssw0rd!2026"
# 同步修改副本的 masterauth
redis-cli CONFIG SET masterauth "NewStr0ngP@ssw0rd!2026"
# 确保写入配置文件持久化
redis-cli CONFIG REWRITE
2.3 密码强度建议
- 长度至少 32 个字符
- 混合大小写字母、数字与特殊符号
- 使用密码管理器生成随机密码
- 定期轮换(建议 90 天一次)
- 禁止硬编码在代码中,使用环境变量或密钥管理服务
三、ACL(Redis 6.0+):用户创建、权限位 +command/-command/@category
ACL(Access Control List)是 Redis 6.0 引入的多用户权限体系,替代了单一的 requirepass,支持用户隔离、细粒度命令控制和 Key 前缀匹配。
3.1 ACL 核心概念
| 概念 | 说明 |
|---|---|
| User | 独立账号,拥有自己的密码和权限 |
| Permission | 允许(+command)或拒绝(-command)特定命令 |
| Category | 命令分类(@read、@write、@admin 等),批量授权 |
| Selector | Key 模式匹配(~pattern),限制可访问的 Key |
| Channel | Pub/Sub 频道权限(&pattern) |
3.2 查看与理解默认用户
# 列出所有用户
redis-cli ACL LIST
# 典型输出:
# user default on nopass ~* &* +@all
# user app_backend on #e3b0c44298... ~app:* +@read +@write ~* -@dangerous
字段解析:
user default:用户名on:账号启用(off为禁用)nopass:无需密码(应修改为有密码)~*:允许访问所有 Key&*:允许订阅所有频道+@all:允许执行所有命令
3.3 创建与管理用户
# 1. 重置默认用户,移除 nopass
redis-cli ACL SETUSER default on >'MyStr0ngP@ssw0rd!2026' ~* +@all
# 2. 创建只读应用用户(只能读 app: 前缀的 Key)
redis-cli ACL SETUSER app_reader on >'ReaderP@ss123' ~app:* resetchannels +@read
# 3. 创建读写应用用户
redis-cli ACL SETUSER app_writer on >'WriterP@ss456' ~app:* resetchannels +@read +@write
# 4. 创建缓存用户(仅字符串操作)
redis-cli ACL SETUSER cache_user on >'CacheP@ss789' ~cache:* resetchannels +get +set +del +expire +ttl +mget +mset
# 5. 创建队列用户(仅限 List/Stream 操作)
redis-cli ACL SETUSER queue_user on >'QueueP@ss000' ~queue:* resetchannels +@list +@stream
# 6. 创建哨兵用户(仅监控相关命令)
redis-cli ACL SETUSER sentinel_user on >'Sentine1P@ss' +@sentinel +ping +info +role +config|get
# 7. 禁用用户
redis-cli ACL SETUSER old_app off
# 8. 删除用户
redis-cli ACL DELUSER old_app
3.4 权限位与分类详解
常用命令分类(+@category):
# 查看所有分类及命令数
redis-cli ACL CAT
# 查看某个分类包含的命令
redis-cli ACL CAT read
redis-cli ACL CAT write
redis-cli ACL CAT admin
redis-cli ACL CAT dangerous
redis-cli ACL CAT fast
关键分类说明:
| 分类 | 用途 |
|---|---|
@read | 只读命令:GET、HGET、LRANGE、ZRANGE 等 |
@write | 写命令:SET、HSET、LPUSH、ZADD 等 |
@keyspace | Key 管理:DEL、EXPIRE、RENAME、TYPE 等 |
@admin | 管理命令:ACL、CONFIG、CLIENT、SLOWLOG 等 |
@dangerous | 高危命令:FLUSHALL、FLUSHDB、KEYS、DEBUG、SHUTDOWN 等 |
@fast | 时间复杂度 O(1) 的快速命令 |
@slow | 可能阻塞服务器的慢命令 |
@connection | 连接命令:AUTH、PING、SELECT、QUIT 等 |
@pubsub | 发布订阅:SUBSCRIBE、PUBLISH、PSUBSCRIBE 等 |
@transaction | 事务命令:MULTI、EXEC、WATCH、DISCARD 等 |
@scripting | Lua 脚本:EVAL、EVALSHA、SCRIPT 等 |
@sortedset | Sorted Set 命令:ZADD、ZRANGE、ZREM 等 |
@list | List 命令:LPUSH、RPOP、LRANGE、BLPOP 等 |
@hash | Hash 命令:HSET、HGET、HGETALL、HDEL 等 |
@set | Set 命令:SADD、SREM、SMEMBERS、SISMEMBER 等 |
@string | String 命令:SET、GET、INCR、MSET 等 |
@bitmap | Bitmap 命令:SETBIT、GETBIT、BITCOUNT 等 |
@hyperloglog | HyperLogLog 命令:PFADD、PFCOUNT 等 |
@geo | GEO 命令:GEOADD、GEORADIUS 等 |
@stream | Stream 命令:XADD、XREAD、XGROUP 等 |
@sentinel | Sentinel 专用命令 |
3.5 细粒度权限控制
# 允许所有读写,但禁用危险命令
redis-cli ACL SETUSER app_safe on >'SafeP@ss123' ~app:* +@all -@dangerous
# 允许读全部,写仅限特定前缀,禁用 CONFIG
redis-cli ACL SETUSER app_mixed on >'MixedP@ss456' +@read +@write ~app:* -config -config|set -config|get
# 仅允许字符串和 List 操作
redis-cli ACL SETUSER app_limited on >'LimitP@ss789' ~* +@string +@list -@all
# 允许特定命令的精确控制
redis-cli ACL SETUSER app_precise on >'PreciseP@ss' ~data:* +get +set +hget +hset +lpush +lrange +del +expire +ttl -@all
# 添加多个 Key 前缀模式
redis-cli ACL SETUSER app_multi on >'MultiP@ss' ~app:* ~session:* ~cache:* +@read +@write
# 使用 ALLKEYS 和 ALLCOMMANDS 简写
redis-cli ACL SETUSER admin_user on >'AdminP@ss123' allkeys allchannels +@all
3.6 Key 前缀权限的进阶用法
# 使用 %R 和 %W 前缀只读/只写模式(Redis 7.0+)
# 允许读取所有 app: 开头的 Key,但不能写入
redis-cli ACL SETUSER app_readonly on >'RO_P@ss123' %R~app:* +@read
# 允许写入,但不能读取某些敏感字段
redis-cli ACL SETUSER app_writeonly on >'WO_P@ss456' %W~app:* +@write
3.7 ACL 配置文件持久化
# 方式一:从 ACL 文件加载
# redis.conf 中配置
aclfile /etc/redis/users.acl
# users.acl 内容示例:
user default on #e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 ~* &* +@all
user app_reader on >'ReaderP@ss123' ~app:* resetchannels +@read
user app_writer on >'WriterP@ss456' ~app:* resetchannels +@read +@write -@dangerous
user monitor on >'Monit0rP@ss' +info +ping +slowlog|get +memory|usage +client|list
user replication on >'Repl1caP@ss' +psync +replconf +ping
# 方式二:动态保存 ACL 到文件
redis-cli ACL SAVE
# 动态从文件加载
redis-cli ACL LOAD
# 将当前 ACL 生成配置文件格式输出
redis-cli ACL GENPASS 32
redis-cli ACL GETUSER app_writer
3.8 生产环境的 ACL 最佳实践
# 1. 先创建新用户测试
redis-cli ACL SETUSER test_user on >'TestP@ss' ~test:* +@read +@write
# 2. 使用 ACL DRYRUN 测试权限(Redis 7.0+)
redis-cli ACL DRYRUN app_writer SET app:key1 value1
# 返回 OK 表示允许
redis-cli ACL DRYRUN app_reader SET app:key1 value1
# 返回 (error) NOPERM 表示拒绝
# 3. 查看用户权限详情
redis-cli ACL GETUSER app_writer
# 4. 查看当前登录用户
redis-cli ACL WHOAMI
# 5. 密码哈希存储(更安全)
redis-cli ACL SETUSER app_hash on #d2d2d2d2... ~app:* +@read +@write
# 使用 # 后跟 SHA-256 哈希值代替明文密码
四、TLS/SSL 加密:tls-port / tls-cert-file、客户端证书
Redis 6.0 引入了对 TLS 的原生支持,允许在集群内部通信和客户端连接中启用加密传输,防止数据包被窃听或篡改。
4.1 TLS 配置基础
在 redis.conf 中配置 TLS 参数:
# === TLS 基础配置 ===
# 启用 TLS 端口(原端口可同时保留作为兼容入口)
tls-port 6380
port 6379
# 证书和私钥路径
tls-cert-file /etc/redis/certs/redis.crt
tls-key-file /etc/redis/certs/redis.key
tls-ca-cert-file /etc/redis/certs/ca.crt
# 客户端证书认证(双向 TLS,可选但推荐)
tls-auth-clients optional
# 仅允许 TLS 连接(禁用明文端口,生产推荐)
# port 0
tls-port 6379
# 允许的 TLS 协议版本
tls-protocols "TLSv1.2 TLSv1.3"
# 密码套件配置(偏好前向安全算法)
tls-ciphers DEFAULT:!MEDIUM
# 集群和副本通信启用 TLS
# cluster 模式
tls-cluster yes
tls-replication yes
# Sentinel 通信启用 TLS
# sentinel 需在各自配置中设置 tls-port
4.2 生成自签名证书(测试环境)
# 创建 CA 和服务器证书
mkdir -p /etc/redis/certs && cd /etc/redis/certs
# 1. 生成 CA 私钥和证书
openssl req -x509 -newkey rsa:4096 -keyout ca.key -out ca.crt \
-sha256 -days 3650 -nodes \
-subj "/CN=Redis CA/O=MyOrg"
# 2. 生成服务器私钥
openssl genrsa -out redis.key 4096
# 3. 创建证书签名请求(CSR)
openssl req -new -key redis.key -out redis.csr \
-subj "/CN=redis.example.com/O=MyOrg"
# 4. 创建扩展配置(SAN 包含 IP 和域名)
cat > redis.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage=digitalSignature,keyEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
[alt_names]
DNS.1=redis.example.com
DNS.2=*.redis.example.com
IP.1=127.0.0.1
IP.2=192.168.1.100
IP.3=10.0.0.5
EOF
# 5. 使用 CA 签发服务器证书
openssl x509 -req -in redis.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out redis.crt -days 365 -sha256 \
-extfile redis.ext
# 6. 设置正确权限
chmod 600 redis.key ca.key
chmod 644 redis.crt ca.crt
chown -R redis:redis /etc/redis/certs
4.3 强制双向 TLS(mTLS)
# redis.conf - 要求所有客户端提供有效证书
tls-auth-clients yes
# 验证客户端证书中的 CN 或 SAN(需配合 Lua 或外部验证实现)
# 也可通过防火墙/代理做二级验证
4.4 客户端 TLS 连接
# redis-cli 使用 TLS 连接
redis-cli --tls \
--cert ./client.crt \
--key ./client.key \
--cacert ./ca.crt \
-h redis.example.com -p 6380 \
AUTH app_writer WriterP@ss456
# Python 示例 (redis-py)
# pip install redis[ocsp]
"""
import redis
r = redis.Redis(
host='redis.example.com',
port=6380,
ssl=True,
ssl_certfile='./client.crt',
ssl_keyfile='./client.key',
ssl_ca_certs='./ca.crt',
ssl_check_hostname=True,
username='app_writer',
password='WriterP@ss456'
)
r.ping()
"""
# Go 示例 (go-redis)
"""
import (
"crypto/tls"
"crypto/x509"
"github.com/redis/go-redis/v9"
)
func NewRedisClient() *redis.ClusterClient {
cert, _ := tls.LoadX509KeyPair("client.crt", "client.key")
caCert, _ := os.ReadFile("ca.crt")
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
return redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{"redis.example.com:6380"},
TLSConfig: &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: caCertPool,
ServerName: "redis.example.com",
},
Username: "app_writer",
Password: "WriterP@ss456",
})
}
"""
4.5 仅启用 TLS(禁用明文端口)
# 完全禁用明文端口,只允许 TLS 通信
port 0
tls-port 6379
# 所有内部通信强制 TLS
tls-replication yes
tls-cluster yes
4.6 TLS 性能调优
# 使用硬件加速(需 OpenSSL 支持)
# 在 BIOS 中启用 AES-NI 指令集
# 连接池复用 TLS 会话
tls-session-caching yes
tls-session-cache-size 2048
tls-session-cache-timeout 300
# 长连接应用应启用连接池,避免频繁 TLS 握手开销
五、网络防护:bind / protected-mode / 防火墙
5.1 bind 地址限制
# 仅监听本地回环(单机本机访问场景)
bind 127.0.0.1 ::1
# 仅监听内网接口(应用与 Redis 同 VPC 场景)
bind 192.168.1.100 10.0.0.5
# 禁止公网暴露(永远不要监听 0.0.0.0 无限制)
# bind 0.0.0.0 # <- 危险!不要这样做
生产环境应将 Redis 部署在私有子网,仅允许应用服务器通过内网 IP 访问。
5.2 protected-mode(自动防护)
# 当 bind 未设置且未设置密码时,protected-mode 会自动拒绝外部连接
# 这是 Redis 3.2+ 的安全兜底机制
protected-mode yes
# 如果确认在安全网络中,可以关闭(但不建议)
# protected-mode no
5.3 防火墙规则
# iptables - 仅允许特定 IP 访问 Redis 端口
iptables -A INPUT -p tcp --dport 6379 -s 10.0.0.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -j DROP
# firewalld
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/24" port protocol="tcp" port="6379" accept'
firewall-cmd --permanent --remove-service=redis # 移除默认允许
firewall-cmd --reload
# UFW
ufw allow from 10.0.0.0/24 to any port 6379 proto tcp
ufw deny 6379
# 云安全组(AWS/阿里云/腾讯云示例规则)
# 入站规则:
# - 协议 TCP,端口 6379,来源 10.0.0.0/16(应用服务器子网)
# - 协议 TCP,端口 16379,来源 10.0.0.0/16(集群总线端口)
# - 拒绝所有其他来源
5.4 网络安全架构
+--------------------------------------------------+
| 公网用户 |
+--------------------------------------------------+
|
v
+--------------------------------------------------+
| API 网关 / 负载均衡 |
| (WAF + DDoS 防护) |
+--------------------------------------------------+
|
v
+--------------------------------------------------+
| 应用服务器集群 |
| (Nginx + 业务服务 + 缓存层) |
| |
| +---------+ +---------+ +---------+ |
| | App Svc | | App Svc | | App Svc | |
| +----+----+ +----+----+ +----+----+ |
| | | | |
| +------------+------------+ |
| | |
| v(TLS/mTLS) |
| +----------------------------------------+ |
| | Redis Cluster / Sentinel | |
| | (私有子网 + ACL + 防火墙 + 审计) | |
| | | |
| | Node1 Node2 Node3 Node4 Node5 | |
| +----------------------------------------+ |
+--------------------------------------------------+
六、命令重命名与禁用:rename-command FLUSHDB ""
除了 ACL 之外,Redis 还提供了一种更底层的命令控制方式——rename-command,通过将危险命令重命名或置空来防止误操作或恶意执行。
6.1 禁用高危命令
# redis.conf - 将危险命令设为空字符串(完全禁用)
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command KEYS ""
rename-command DEBUG ""
rename-command CONFIG ""
rename-command SHUTDOWN ""
rename-command BGREWRITEAOF ""
rename-command BGSAVE ""
注意:
rename-command必须放在配置文件末尾,且一旦禁用后所有客户端都无法调用原命令。
6.2 重命名为随机名称
# 将 CONFIG 重命名,只有知道新名称的管理员才能使用
rename-command CONFIG "a3b9f2e7d1c8x0w5v4q6"
# 将 SHUTDOWN 重命名
rename-command SHUTDOWN "z8k2m7n1p0o4i5u3y6t9"
使用时需要知道别名:
# 使用重命名后的命令
redis-cli a3b9f2e7d1c8x0w5v4q6 GET maxclients
redis-cli z8k2m7n1p0o4i5u3y6t9 NOSAVE
6.3 需要谨慎处理的命令
| 命令 | 风险 | 建议操作 |
|---|---|---|
FLUSHALL | 清空所有数据库数据 | 禁用或重命名 |
FLUSHDB | 清空当前数据库 | 禁用或重命名 |
KEYS * | O(N) 扫描全库 Key,阻塞服务器 | 禁用或重命名 |
DEBUG SEGFAULT | 触发崩溃,用于测试 | 禁用 |
CONFIG SET/GET | 修改配置、查看敏感信息 | 重命名为随机名 |
SHUTDOWN | 关闭服务器 | 重命名 |
SAVE | 阻塞式 RDB 持久化 | 重命名 |
BGSAVE | 后台 RDB 持久化 | 按需保留或重命名 |
BGREWRITEAOF | AOF 重写 | 按需保留或重命名 |
SLAVEOF/REPLICAOF | 改变主从关系 | 重命名 |
SYNC/PSYNC | 全量同步 | 重命名 |
EVAL/EVALSHA | 执行任意 Lua 脚本 | 限制或配合 ACL 控制 |
MODULE LOAD | 加载动态模块 | 禁用 |
6.4 rename-command 与 ACL 的配合
# 推荐策略:双重防护
# 1. 先用 rename-command 将危险命令重命名
rename-command CONFIG "cfg_admin_7x9k2m"
rename-command FLUSHALL ""
rename-command KEYS ""
# 2. 再用 ACL 控制谁能使用重命名后的命令
# users.acl:
# user admin on >'AdminP@ss123' allkeys allchannels +@all +cfg_admin_7x9k2m
# user app_safe on >'SafeP@ss456' ~app:* +@all -@dangerous
rename-command的优先级高于 ACL:即使 ACL 授予了命令权限,如果命令被 rename-command 禁用,客户端仍然无法执行。
6.5 模块扩展命令的防护
# 禁用 MODULE 命令防止加载未经验证的模块
rename-command MODULE ""
# 如果使用了 RedisSearch、RedisJSON 等模块,
# 可以通过 ACL 限制只有特定用户能使用模块命令
# user search_user on >'SearchP@ss' +ft.search +ft.info +ft.explain
七、审计日志:ACL LOG / MONITOR
安全加固后,持续的审计监控同样关键。Redis 提供了多种审计手段,帮助追踪异常访问和安全事件。
7.1 ACL LOG(Redis 6.0+)
ACL LOG 记录权限拒绝事件,是排查未授权访问的第一线工具。
# 查看最近的 ACL 拒绝日志
redis-cli ACL LOG
# 查看指定条数的日志(最多 128 条,默认可配置)
redis-cli ACL LOG 10
# 清空 ACL 日志
redis-cli ACL LOG RESET
典型输出解析:
# 1) 1) "entry"
# 2) 1) "count"
# 2) (integer) 5 # 该事件触发次数
# 3) "reason"
# 4) "command"
# 5) "context"
# 6) "toplevel"
# 7) "object"
# 8) "flushall"
# 9) "username"
# 10) "app_reader"
# 11) "age-seconds"
# 12) "12.345"
# 13) "client-info"
# 14) "id=7 addr=10.0.0.25:54321..."
# 15) "entry-id"
# 16) (integer) 42
字段含义:
count:同一事件的累计触发次数reason:拒绝原因(command/key/channel/auth)object:被拒绝的命令/Key/频道名username:触发拒绝的 ACL 用户名client-info:客户端连接信息(IP、端口、连接 ID)
7.2 配置 ACL LOG 参数
# redis.conf
# ACL LOG 最大条目数(默认 128)
acllog-max-len 1000
# 当达到上限时,最旧的条目自动淘汰
7.3 ACL LOG 的自动化监控
# 将 ACL LOG 接入日志收集系统
#!/bin/bash
# acl-log-monitor.sh
while true; do
LOGS=$(redis-cli --raw ACL LOG 1)
if [ -n "$LOGS" ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') ALERT: ACL Denial Detected"
echo "$LOGS" | logger -t redis-acl-denial
# 发送到企业微信/钉钉/飞书机器人
# curl -X POST ....
fi
sleep 10
done
# Python 监控脚本
import redis
import json
import time
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
last_entry_id = 0
while True:
logs = r.acl_log(count=10)
for entry in logs:
entry_id = entry.get('entry-id', 0)
if entry_id > last_entry_id:
print(f"[ALERT] ACL Denied: user={entry['username']} "
f"reason={entry['reason']} object={entry['object']} "
f"client={entry['client-info']}")
# 发送到 SIEM 或告警系统
last_entry_id = entry_id
time.sleep(5)
7.4 MONITOR 命令(实时流量监控)
# 实时输出所有执行的命令(性能开销大,仅用于调试)
redis-cli MONITOR
# 输出示例:
# 1691881234.567890 [0 10.0.0.25:54321] "GET" "app:user:12345"
# 1691881234.568012 [0 10.0.0.25:54322] "HGETALL" "app:config:default"
# 1691881234.570123 [0 10.0.0.25:54321] "SET" "app:session:abc" "xxx" "EX" "3600"
警告:
MONITOR会显著降低 Redis 性能(可达 50%),且输出量巨大。仅应在以下场景短时使用:
- 排查可疑命令执行
- 调试应用与 Redis 的交互模式
- 流量分析(需配合过滤脚本)
# MONITOR 的安全使用方法
# 1. 限制只有管理员能执行 MONITOR
redis-cli ACL SETUSER admin on >'AdminP@ss' allkeys +monitor +client|kill +client|list
# 2. 配合 timeout 限制监控时长
redis-cli --raw MONITOR | head -n 1000 > redis_monitor_$(date +%Y%m%d_%H%M%S).log
# 3. 过滤特定命令
redis-cli MONITOR | grep -E '"(FLUSHALL|CONFIG|DEBUG|KEYS)"'
7.5 SLOWLOG(慢查询日志)
# 查看慢查询日志(默认 >10ms)
redis-cli SLOWLOG GET 20
# 配置慢查询阈值(微秒)
redis-cli CONFIG SET slowlog-log-slower-than 5000 # 5ms
redis-cli CONFIG SET slowlog-max-len 1024
# 清空慢查询日志
redis-cli SLOWLOG RESET
慢查询日志字段:
id:日志唯一 IDtimestamp:执行时间(Unix 时间戳)duration:执行耗时(微秒)command:命令及参数数组client:客户端地址和端口name:客户端名称(如设置了CLIENT SETNAME)
7.6 持久化审计日志
# 将 Redis 日志重定向到文件,配合 rsyslog 转发
logfile /var/log/redis/redis-server.log
loglevel notice
# 系统日志集成
syslog-enabled yes
syslog-ident redis
syslog-facility local0
# rsyslog 配置 (/etc/rsyslog.d/50-redis.conf)
local0.* /var/log/redis/redis-audit.log
# logrotate 配置 (/etc/logrotate.d/redis)
/var/log/redis/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 644 redis redis
sharedscripts
postrotate
/bin/kill -HUP $(cat /var/run/redis/redis-server.pid 2>/dev/null) >/dev/null 2>&1
endscript
}
7.7 审计日志的 Elasticsearch 集成
# Filebeat 配置,将 Redis 日志发送到 Elasticsearch
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/redis/redis-server.log
- /var/log/redis/redis-audit.log
fields:
service: redis
environment: production
fields_under_root: true
output.elasticsearch:
hosts: ["https://es-cluster:9200"]
index: "redis-audit-%{+yyyy.MM.dd}"
# Kibana 中创建可视化看板:
# - ACL 拒绝事件趋势图
# - 慢查询 Top 10
# - 命令分布饼图
# - 异常 IP 访问热力图
八、CVE 修复流程:版本升级策略
Redis 社区活跃,安全漏洞(CVE)的发现和修复节奏较快。建立标准化的漏洞响应流程是保障生产安全的重要环节。
8.1 主要 CVE 历史回顾
| CVE 编号 | 影响版本 | 漏洞类型 | 风险等级 |
|---|---|---|---|
| CVE-2024-31228 | < 7.2.5, < 6.2.16 | ACL 绕过 | 高危 |
| CVE-2023-45145 | < 7.0.14 | 整数溢出 | 高危 |
| CVE-2023-28856 | < 7.0.11 | 拒绝服务 | 中危 |
| CVE-2023-25155 | < 7.0.9 | Lua 脚本越界读取 | 高危 |
| CVE-2023-22458 | < 7.0.8 | 整数溢出 | 高危 |
| CVE-2022-35977 | < 7.0.8 | Lua 栈溢出 | 中危 |
| CVE-2022-31144 | < 7.0.4 | 拒绝服务 | 高危 |
| CVE-2022-0543 | Debian/Ubuntu 包 | Lua 沙箱逃逸 | 严重 |
| CVE-2021-41099 | < 6.2.6, < 5.0.14 | 整数溢出 | 高危 |
| CVE-2021-32761 | < 6.2.6 | 拒绝服务 | 中危 |
| CVE-2020-14147 | < 6.0.6 | Lua 脚本整数溢出 | 高危 |
| CVE-2019-10192 | < 5.0.5 | 堆缓冲区溢出 | 高危 |
| CVE-2018-11219 | < 4.0.11, < 5.0-rc6 | 整数溢出 | 高危 |
| CVE-2015-8080 | < 3.0.4 | 拒绝服务 | 中危 |
| CVE-2015-4335 | < 3.0.3 | 拒绝服务 | 中危 |
| CVE-2013-7458 | < 2.6.17 | 信息泄露 | 低危 |
8.2 CVE 监控渠道
# 1. Redis 官方安全公告
# https://github.com/redis/redis/security/advisories
# 2. 邮件订阅
# 关注 Redis 官方 GitHub Releases 的 Watch -> Security alerts
# 3. NVD 国家漏洞数据库
# https://nvd.nist.gov/vuln/search/results?query=redis
# 4. 自动化漏洞扫描
# Clair、Trivy、Snyk、OpenVAS 等工具扫描 Redis 镜像与二进制
# 使用 Trivy 扫描
$ trivy image redis:7.2
$ trivy filesystem /usr/local/bin/redis-server
8.3 版本升级策略
版本策略矩阵:
+------------+------------+------------+------------+
| 环境 | 稳定版本 | 补丁周期 | 升级窗口 |
+------------+------------+------------+------------+
| 生产环境 | 最新稳定版减一 | 每 2 周 | 每月维护窗 |
| 预发布环境 | 最新稳定版 | 每周 | 按需 |
| 开发环境 | 最新版 | 随时 | 即时 |
+------------+------------+------------+------------+
升级流程:
# === 阶段一:测试验证 ===
# 1. 在测试环境部署新版本
docker run --rm -d --name redis-test redis:7.4.0 redis-server
# 2. 运行功能回归测试
redis-benchmark -h redis-test -p 6379 -n 100000 -c 50
# 3. 验证数据持久化兼容性
redis-cli SAVE
# 对比 RDB/AOF 文件是否正常
# 4. 验证主从复制正常
redis-cli INFO replication
# 确认 master_link_status:up
# === 阶段二:金丝雀发布 ===
# 5. 先升级一个副本节点
# 修改配置文件指向新版本二进制
# 重启该副本,观察复制状态
# === 阶段三:滚动升级 ===
# 6. Sentinel 模式下逐台升级副本
# 升级后 sentinel 自动发现新版本
# 7. Cluster 模式下一个节点一个节点升级
# 使用 redis-cli --cluster 管理节点替换
# === 阶段四:主库切换 ===
# 8. 手动故障转移将主库降级为副本
redis-cli SENTINEL failover mymaster
# 9. 升级原主库
# 10. 观察新主库稳定运行 24 小时
# === 阶段五:回滚预案 ===
# 11. 保留旧版本二进制和配置文件 7 天
# 12. 保留升级前 RDB 备份
8.4 热补丁(紧急 CVE 响应)
# 对于高危 CVE 需要紧急修复但无法立即重启时:
# 1. 使用 rename-command 临时禁用受影响命令
redis-cli CONFIG SET rename-command FLUSHALL ""
redis-cli CONFIG SET rename-command DEBUG ""
redis-cli CONFIG REWRITE
# 2. 通过防火墙限制访问
iptables -A INPUT -p tcp --dport 6379 -j DROP
# 仅允许白名单 IP
iptables -I INPUT -p tcp --dport 6379 -s 10.0.0.0/24 -j ACCEPT
# 3. 修改 ACL 降低暴露面
redis-cli ACL SETUSER default -@all +@read +ping +info
# 4. 启用审计,密切监控
# 开启 MONITOR(短时)或加强 ACL LOG 监控频率
8.5 版本生命周期
| 版本系列 | 发布日期 | 维护状态 | 建议 |
|---|---|---|---|
| Redis 7.4 | 2024-07 | 活跃维护 | 新环境首选 |
| Redis 7.2 | 2023-08 | 活跃维护 | 生产推荐 |
| Redis 7.0 | 2022-04 | 仅安全补丁 | 建议升级 |
| Redis 6.2 | 2021-03 | 仅安全补丁 | 规划升级 |
| Redis 6.0 | 2020-04 | 终止维护 | 必须升级 |
| Redis 5.x | 2018-10 | 终止维护 | 必须升级 |
| Redis 4.x | 2018-01 | 终止维护 | 必须升级 |
| Redis 3.x | 2015-04 | 终止维护 | 必须升级 |
原则:终止维护版本遇到 CVE 将不再获得补丁,应尽快制定升级计划。
九、安全基线检查清单
以下检查清单涵盖 Redis 生产环境的所有安全维度,可用于上线前的安全检查或定期审计。
9.1 认证与授权
-
requirepass已设置为强密码(32+ 字符,随机生成) - 已启用 ACL(Redis 6.0+),默认用户有密码且非
nopass - 为每个应用创建了独立的 ACL 用户,遵循最小权限原则
- ACL 用户权限已使用
ACL DRYRUN验证 - 已禁用或删除不再使用的 ACL 用户
- 密码未硬编码在代码中,使用环境变量/密钥管理(如 Vault)
- 密码有定期轮换机制(90 天周期)
- 主从复制的
masterauth与主库密码一致
9.2 网络安全
-
bind仅监听内网接口,未暴露0.0.0.0 -
protected-mode保持yes - 防火墙/安全组仅允许白名单 IP 访问 Redis 端口
- Redis 实例部署在私有子网,无公网路由
- 集群总线端口(16379)同样受防火墙保护
- Sentinel 通信端口(26379)仅限管理网段访问
- VPC/子网间有网络 ACL 二次隔离
9.3 传输加密
- 已启用 TLS(Redis 6.0+),
tls-port配置正确 - 证书文件权限为 600(私钥)/644(公钥)
- 证书由可信 CA 签发(自建 CA 或商业证书)
- 证书包含正确的 SAN(IP + 域名)
-
tls-protocols限制为 TLSv1.2+ - 生产环境已禁用明文端口(
port 0) - 副本复制和集群通信已启用
tls-replication yes/tls-cluster yes - 客户端支持并正确配置 TLS CA 验证
- 双向 TLS(mTLS)已启用(安全要求高的场景)
9.4 命令控制
-
FLUSHALL、FLUSHDB已通过rename-command禁用 -
KEYS命令已禁用(使用SCAN替代) -
DEBUG命令已禁用 -
CONFIG已重命名为随机字符串 -
SHUTDOWN已重命名 - Lua 脚本命令通过 ACL 做了限制(高危场景禁用
EVAL) -
MODULE命令已禁用
9.5 持久化与数据安全
- RDB/AOF 文件存储路径权限为
700 - 备份文件加密存储或存放在加密磁盘上
- 定期对 RDB 文件进行异地备份
- AOF 文件开启启用 fsync 策略(
appendfsync everysec或always) - 备份保留策略明确,旧备份已安全销毁
9.6 审计与监控
- ACL LOG 已启用,
acllog-max-len配置合理 - 慢查询日志
slowlog-log-slower-than<= 10ms - Redis 日志已集中收集到日志系统(ELK/PLG/Loki)
- 有 ACL 拒绝事件的实时告警机制
- 每日/每周审查慢查询和异常访问日志
- 监控 Redis 连接数突增、CPU/内存异常波动
-
MONITOR使用有审批流程,不可常驻开启
9.7 CVE 与版本管理
- 当前运行版本在官方维护期内
- 已订阅 Redis 安全公告
- 有自动化的漏洞扫描流程(Trivy/Clair)
- 有书面的版本升级预案和回滚方案
- 升级前在测试环境完成验证
- 保留升级前 7 天的 RDB 备份
9.8 高可用与灾备
- 主从复制已配置,副本可快速晋升
- Sentinel / Cluster 模式已部署且监控正常
- 有自动化故障切换脚本且经过演练
- 跨可用区部署,单点故障不影响可用性
- 最大客户端连接数
maxclients已合理限制 - 内存上限
maxmemory已配置,驱逐策略已设定
结语
Redis 安全不是单一配置就能解决的问题,而是需要从网络层、认证层、传输层、命令层、审计层构建纵深防御体系。核心要点回顾:
- 先网络隔离:
bind限制 + 防火墙白名单,确保 Redis 不暴露在外网 - 再身份认证:用 ACL 替代单一密码,按应用和用户粒度分配权限
- 加密传输:Redis 6.0+ 启用 TLS,跨网络通信全部加密
- 收缩攻击面:
rename-command禁用或重命名高危命令 - 持续审计:ACL LOG + 慢查询 + 日志集中监控
- 漏洞管理:订阅安全公告,建立升级和应急响应流程
安全是一个持续的过程,而非一次性的配置。建议每季度使用本清单进行一次安全检查,确保配置未因运维变更而回退。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。