Redis 安全指南:从配置加固到漏洞防御

作者:杨帅      发布日期:2026.06.16

Redis Security Deep Dive

从配置加固到
漏洞防御的完整实践

Redis 的默认配置为开发便利而生,而非为生产安全而设。本文系统梳理六大核心防御维度,结合 2025 年最新披露的高危漏洞 CVE-2025-49844(CVSS 10.0),为你提供一套可落地的安全加固方案。

安全加固 生产运维 漏洞防御 附完整配置示例

为什么 Redis 安全问题如此普遍?

Redis 的安全问题几乎从不起源于黑客的精密攻击——它们起源于假设。团队假设 Redis 只在内部使用,网络是可信的,或者没有人会直接连接 Redis。这些假设在初期或许成立,但随着系统增长、网络变化和部署复杂化,它们往往会悄然失效。

当 Redis 被攻陷时,影响从来都不轻微:数据消失、内存异常飙升、服务器被劫持用于挖矿,或整个数据集被清空。而在大多数情况下,根本原因并非复杂的 0day 漏洞,而是早期被忽视的基础安全卫生

Redis 不会保护自己,除非你明确配置安全控制。
— Redis Security Best Practices, 2025

今年最值得关注的两个 CVE

在深入最佳实践之前,先了解两个 2025 年披露的真实漏洞——它们直接影响你的修复优先级。

CVE-2025-49844 · RediShell CVSS 10.0

经认证用户可通过精心构造的 Lua 脚本操控垃圾回收器,触发 use-after-free(UAF)内存损坏,进而实现远程代码执行。该漏洞在源码中潜伏长达 13 年,可能影响高达 75% 的云环境。

✓ 修复版本:6.2.20 · 7.2.11 · 7.4.6 · 8.0.4 · 8.2.2
CVE-2025-21605 · DoS CVSS 7.5

当 Redis 启用密码认证但客户端未提供密码时,持续触发"NOAUTH"响应可导致输出缓冲区无限增长,最终耗尽系统内存。需要 Redis 端口可从公网访问才能被利用。

✓ 修复版本:7.4.3+

CVE-2025-49844 临时缓解方案

无法立即升级时,通过 ACL 禁止普通用户执行 Lua 脚本:

redis-cli
# 禁止应用用户执行 Lua 相关命令
        ACL SETUSER appuser ~* &* +@all -EVAL -EVALSHA -EVALSHA_RO -EVAL_RO

        # 验证生效
        ACL LIST
        ACL WHOAMI

六层纵深防御体系

没有任何单一措施能解决所有问题。以下六层防御组合在一起,可以将攻击者的成本提高到大多数机会性攻击无法承受的程度。

🌐
Layer 01 · 网络隔离
永远不要将 Redis 暴露在公网

这是最重要的一条规则。Redis 应始终运行在私有网络中,访问权限仅限于真正需要它的应用服务器。网络隔离是第一道也是最强的防线——如果 Redis 可公网访问,其他所有保护措施都会退居次位。

redis.conf
# 仅监听本地回环和内网 IP,禁止 0.0.0.0
        bind 127.0.0.1 10.0.0.5

        # 保护模式默认开启,请勿关闭
        protected-mode yes
bash · iptables
# 只允许应用服务器子网访问 Redis 端口
        iptables -A INPUT -p tcp --dport 6379 -s 10.0.0.0/24 -j ACCEPT
        iptables -A INPUT -p tcp --dport 6379 -j DROP
        iptables-save > /etc/iptables/rules.v4
💡 云环境:将 Redis 部署在独立的私有子网(VPC),通过安全组限制只有应用层 EC2/Pod 可访问 6379。永远不要将 Redis 端口加入公网安全组。
🔑
Layer 02 · 身份认证
ACL 多用户访问控制(Redis 6.0+)

默认情况下,Redis 不要求密码即可连接。ACL 是 Redis 6.0 引入的重磅安全特性,支持细粒度的权限控制:每个用户可以分配不同的命令权限、Key 访问范围和 Channel 权限。

ACL 配置
# 禁用默认 default 用户(强烈建议)
        ACL SETUSER default off

        # 只读用户:仅能读取 cache: 前缀的 key
        ACL SETUSER readonly_user on >ReadOnlyPass123 \
          ~cache:* &* +GET +MGET +HGET +HGETALL +LRANGE +ZRANGE

        # 应用用户:读写权限,禁止危险命令
        ACL SETUSER app_user on >AppPass456 \
          ~* &* +@all -@dangerous -CONFIG -DEBUG -SHUTDOWN -FLUSHALL -FLUSHDB

        # 管理员:完整权限
        ACL SETUSER admin_user on >AdminPass789 ~* &* +@all

        # 持久化 ACL 规则
        ACL SAVE

ACL 权限速查

权限类别说明典型用途
+@all所有命令管理员
+@read所有读命令只读用户
-@dangerous排除危险命令类别应用用户
~cache:*Key 模式匹配按命名空间隔离
&channel:*Pub/Sub 频道访问消息订阅
⚠️ 注意:Redis 的认证在 TCP 握手后立即发生——如果没有 TLS,密码仍以明文传输。请务必结合下方的 TLS 配置。
🔒
Layer 03 · 传输加密
TLS + mTLS 双向证书认证

明文传输意味着任何网络中间人都可以嗅探 Redis 通信内容,包括认证密码和所有数据。Redis 6.0+ 原生支持 TLS。

bash · 生成证书
openssl genrsa -out redis.key 2048
        openssl req -new -x509 -days 365 -key redis.key -out redis.crt \
          -subj "/CN=redis-server/O=MyOrg"
        openssl dhparam -out redis.dh 2048
redis.conf · TLS 配置
port                      0         # 禁用明文端口
        tls-port                  6379
        tls-cert-file             /etc/redis/redis.crt
        tls-key-file              /etc/redis/redis.key
        tls-dh-params-file        /etc/redis/redis.dh
        tls-ca-cert-file          /etc/redis/ca.crt
        tls-auth-clients          yes       # 强制客户端证书 (mTLS)
        tls-protocols             "TLSv1.2 TLSv1.3"
        tls-prefer-server-ciphers yes
Python · TLS 客户端
import redis, ssl

        r = redis.Redis(
            host='10.0.0.5', port=6379,
            ssl=True,
            ssl_certfile='/path/to/client.crt',
            ssl_keyfile='/path/to/client.key',
            ssl_ca_certs='/path/to/ca.crt',
            ssl_cert_reqs=ssl.CERT_REQUIRED
        )
        r.ping()  # 验证 TLS 连接
⚔️
Layer 04 · 命令加固
禁用或重命名危险命令

某些 Redis 命令在误用或被攻击者利用时危害极大。FLUSHALL 可以一次性清空所有数据,CONFIG 可以在运行时修改服务器配置,EVAL 则是 RediShell 漏洞的攻击入口。

redis.conf · 命令禁用
# 彻底禁用(rename 为空字符串)
        rename-command FLUSHALL  ""
        rename-command FLUSHDB   ""
        rename-command DEBUG     ""
        rename-command CONFIG    ""
        rename-command SHUTDOWN  ""

        # 重命名为随机字符串(内部运维仍可用)
        rename-command KEYS     "KEYS_a8f3b2c1d9e7"
        rename-command MONITOR  "MONITOR_x5k2m9n4p7q1"

        # 禁用调试接口
        enable-debug-command no
⚠️ rename-command 在 Redis Cluster 模式下不适用,请改用 ACL -CONFIG -DEBUG -FLUSHALL 实现命令限制。
💾
Layer 05 · 数据持久化与加密
持久化配置 + 客户端加密
redis.conf · 持久化
# AOF 持久化(推荐生产环境)
        appendonly    yes
        appendfsync   everysec    # 每秒同步,平衡性能与安全

        # RDB 快照
        save 900 1
        save 300 10
        save 60 10000

        # 数据目录
        dir        /var/lib/redis
        dbfilename dump.rdb
Python · 客户端加密
from cryptography.fernet import Fernet
        import redis

        # 密钥安全存储到 Vault / AWS KMS
        key = Fernet.generate_key()
        cipher = Fernet(key)
        r = redis.Redis(host='localhost', port=6379)

        # 写入时加密
        encrypted = cipher.encrypt(b"sensitive user data")
        r.set('user:42:secret', encrypted)

        # 读取时解密
        decrypted = cipher.decrypt(r.get('user:42:secret'))
📡
Layer 06 · 监控与审计
持续可见性:知道 Redis 上正在发生什么

安全不只是配置,还需要持续监控。当攻击者进入内网后,行为指标往往比签名更早发出警报。

bash · 关键监控指令
# 拒绝的连接(可能是暴力破解)
        redis-cli INFO stats | grep rejected_connections

        # 异常命令统计
        redis-cli INFO commandstats | grep -E "flushall|config|debug|eval"

        # 慢日志(超过 10ms 的命令)
        redis-cli SLOWLOG GET 10

        # 内存使用
        redis-cli INFO memory | grep used_memory_human
YAML · Prometheus 告警规则
groups:
          - name: redis_security
            rules:
              - alert: RedisRejectedConnections
                expr: increase(redis_rejected_connections_total[5m]) > 10
                annotations:
                  summary: "Redis 拒绝连接异常,可能存在暴力破解"

              - alert: RedisFlushAllDetected
                expr: increase(redis_commands_total{cmd="flushall"}[1m]) > 0
                annotations:
                  summary: "检测到 FLUSHALL,立即排查"

              - alert: RedisHighMemoryUsage
                expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.9
                annotations:
                  summary: "Redis 内存使用率超过 90%"

安全加固对照表

逐项确认你的 Redis 实例是否达标,每个维度都是独立的防御层。

🌐 网络层
  • Redis 未绑定 0.0.0.0,仅监听内网 IP
  • 防火墙 / 安全组限制只有应用服务器可访问 6379
  • Redis 部署在私有子网,无公网入口
  • protected-mode yes 已启用
🔑 认证层
  • 已启用强密码认证(requirepass 或 ACL)
  • default 用户已禁用或降权
  • 不同角色使用不同 ACL 用户
  • 密码存储在 Secret Manager,而非代码或配置
🔒 传输层
  • 已启用 TLS,禁用明文 6379 端口
  • 启用客户端证书认证(mTLS)
  • TLS 版本限制为 1.2 及以上
⚔️ 命令层
  • FLUSHALL / FLUSHDB / DEBUG 已禁用
  • CONFIG 命令已通过 ACL 限制管理员
  • Lua 脚本权限已通过 ACL 限制(EVAL)
  • Redis 以非 root 用户运行
💾 数据层
  • 启用 AOF 持久化,appendfsync everysec
  • 数据目录权限 750,文件权限 640
  • 敏感数据实现客户端加密或磁盘加密
📡 补丁与监控
  • Redis 版本 ≥ 8.2.2(修复 CVE-2025-49844)
  • 已配置慢日志监控
  • Prometheus 告警:拒绝连接 + 危险命令
  • 定期安全审计(建议每季度一次)

把安全当作工程实践,而非一次性任务

大多数 Redis 安全事件是机会性的而非针对性的。六层防御体系的核心逻辑是纵深防御:即便某一层被突破,其他层仍能提供保护。

及时打补丁永远是最高优先级。CVE-2025-49844 的教训再次证明:一个潜伏 13 年的漏洞,在被披露后只需数天就会被大规模利用。保持版本更新,是所有安全措施中 ROI 最高的一项。