Redis 默认配置下,如果直接暴露在公网,攻击者能在几秒内通过未授权访问拿到服务器的完整控制权。这不是危言耸听,而是每天都在发生的真实案例。很多团队把 Redis 当作纯内存缓存用,上线时绑定 0.0.0.0、关闭保护模式、不设密码,以为内网环境就绝对安全。实际上,一次简单的 SSRF 攻击或内网横向移动,就能让这个“内网Redis”变成攻击者手中的跳板机。
Redis 本身的设计哲学是“信任内网环境”,所以它的安全机制相对简洁。问题在于,现代网络架构中“内网”边界早已模糊,容器、微服务、混合云让网络拓扑变得极其复杂。安全防护必须从部署、配置、运行时三个维度同时入手,缺一不可。
绑定地址与保护模式:第一道防线Redis 配置文件 redis.conf 中的 bind 参数决定了服务监听的网络接口。很多人图省事直接设为 bind 0.0.0.0,这意味着 Redis 对所有网卡开放。正确的做法是明确指定内网 IP,例如 bind 127.0.0.1 192.168.1.100,只允许本地回环地址和指定的内网接口访问。如果 Redis 仅被本机应用调用,直接绑定 127.0.0.1 是最安全的选择。
保护模式(protected-mode)是 Redis 3.2 版本后默认开启的安全特性。当 Redis 绑定非回环地址且未设置密码时,保护模式会拒绝外部连接并返回错误信息。这个机制能有效防止因配置疏忽导致的未授权访问。生产环境中,即使设置了密码,也建议保持保护模式开启,作为纵深防御的一环。
requirepass 与 ACL 权限体系:认证与授权分离设置访问密码是最基础的安全措施。在 redis.conf 中配置 requirepass 参数,客户端连接后必须执行 AUTH 命令才能执行其他操作。密码强度直接决定了暴力破解的难度,建议使用 32 位以上、包含大小写字母、数字和特殊字符的随机字符串。
Redis 6.0 引入的 ACL(Access Control List)机制彻底改变了权限管理方式。旧版本只有一个全局密码,任何通过认证的客户端都拥有全部命令的执行权限。ACL 允许创建多个用户,为每个用户分配独立的密码、可执行命令列表和可访问的键模式。以下是一个典型的 ACL 配置示例:
# 创建只读用户,仅允许 GET 和 MGET 命令,只能访问 cache: 前缀的键 ACL SETUSER readonly_user on >strong_password_123 ~cache:* +@read # 创建应用用户,允许常用命令但禁止危险命令 ACL SETUSER app_user on >another_password ~* +@all -@dangerous -FLUSHDB -FLUSHALL -CONFIG -DEBUG # 禁用 default 用户的无密码访问 ACL SETUSER default off
通过 ACL,你可以实现最小权限原则:只读业务只用只读账号,队列处理只开放 LPUSH/RPOP 等必要命令,运维操作使用独立的高权限账号。即使某个应用的 Redis 凭证泄露,攻击者也无法执行 FLUSHALL 清空数据或 CONFIG SET 修改配置。
命令重命名与禁用:消除高危操作面Redis 中有多个命令在生产环境中极度危险。CONFIG 命令可以动态修改服务器配置,包括将 RDB 文件写入 /etc/crontab 实现计划任务反弹 shell;FLUSHALL 和 FLUSHDB 能在瞬间清空所有数据;DEBUG 命令可能泄露内存中的敏感信息;EVAL 和 SCRIPT 系列命令如果被滥用,可以执行任意 Lua 脚本。
在 redis.conf 中使用 rename-command 指令可以将危险命令重命名为难以猜测的字符串,或者直接禁用。推荐做法如下:
# 直接禁用高危命令 rename-command FLUSHALL "" rename-command FLUSHDB "" rename-command CONFIG "" rename-command DEBUG "" rename-command SHUTDOWN "" # 重命名保留给内部运维使用的命令 rename-command EVAL "b8f3a9d2e1c7f4e6a0d3b5c8e2f1a7d9"
需要注意的是,部分 Redis 客户端库和监控工具依赖某些命令,禁用前务必确认业务兼容性。另外,重命名后的命令名称本身也是敏感信息,应作为凭据管理,避免泄露在代码仓库或日志中。
网络层隔离:iptables 与安全组策略操作系统级别的防火墙规则是 Redis 安全的重要补充。即使 Redis 自身配置正确,多一层网络过滤也能防御未知的 0day 漏洞或配置漂移。使用 iptables 限制只有指定的应用服务器 IP 才能访问 Redis 端口:
# 允许来自 192.168.1.0/24 网段的访问 iptables -A INPUT -p tcp --dport 6379 -s 192.168.1.0/24 -j ACCEPT # 拒绝其他所有来源的 6379 端口请求 iptables -A INPUT -p tcp --dport 6379 -j DROP
云环境下,安全组是第一道网络防线。配置安全组规则时,避免使用 0.0.0.0/0 的开放规则,精确指定允许访问的实例安全组或 IP 段。对于跨可用区部署的 Redis 集群,使用 VPC 对等连接或私有链路,避免流量经过公网。
TLS 传输加密:防止中间人嗅探Redis 从 6.0 版本开始原生支持 TLS 加密。在未加密的 TCP 连接上,AUTH 命令的密码和所有数据都以明文传输。如果应用服务器与 Redis 之间的网络路径经过交换机镜像、云平台底层网络或任何不可信节点,明文传输就意味着数据完全暴露。
启用 TLS 需要生成服务器证书和私钥,并在 redis.conf 中配置:
# 启用 TLS,指定证书和私钥路径 tls-port 6380 port 0 tls-cert-file /etc/redis/tls/redis.crt tls-key-file /etc/redis/tls/redis.key tls-ca-cert-file /etc/redis/tls/ca.crt tls-auth-clients yes
配置完成后,Redis 在 6380 端口监听 TLS 加密连接,原有的 6379 端口可以关闭。客户端连接时需要指定 --tls 参数并提供对应的证书。对于云上的 Redis 托管服务,通常内置了 TLS 选项,开启即可。需要注意 TLS 会带来约 5%-15% 的性能损耗,对于极高吞吐场景需要评估影响。
运行时安全:异常行为检测与审计Redis 的 MONITOR 命令可以实时查看所有客户端执行的命令,这既是调试利器也是安全审计工具。通过分析命令流,可以发现异常的键访问模式、未授权的 CONFIG 修改尝试或大规模数据导出行为。但 MONITOR 本身会显著降低吞吐量,不适合长时间开启。更实用的做法是周期性采样分析或使用慢日志(SLOWLOG)捕获执行时间异常的命令。
Redis 7.0 引入了细粒度的 ACL 日志功能,可以记录被拒绝的命令请求。当某个用户尝试执行未被授权的命令时,ACL LOG 会记录时间戳、用户名、客户端 IP 和具体命令。定期检查 ACL 日志能及时发现凭证泄露或内部越权行为:
# 查看最近的 ACL 拒绝记录 ACL LOG 10
文件系统层面,Redis 的数据目录权限必须严格控制。RDB 文件和 AOF 文件包含完整的内存数据镜像,如果被读取等同于数据泄露。确保 Redis 进程以专用用户运行,数据目录权限设置为 700,仅 Redis 用户可读写。
防入侵实战:利用 Redis 写入 webshell 的原理与防御攻击者最常利用的 Redis 未授权访问攻击链如下:首先通过端口扫描发现开放 6379 端口且无密码保护的 Redis 实例;接着使用 CONFIG SET dir 命令将 RDB 文件保存路径修改到 Web 目录;然后通过 CONFIG SET dbfilename 设置文件名为 .php 或 .jsp 后缀;最后执行 BGSAVE 或在 Redis 中写入包含恶意代码的键值,触发 RDB 持久化,从而在 Web 目录生成 webshell 文件。
防御这类攻击的核心措施是多层阻断:禁用 CONFIG 命令让攻击者无法修改持久化路径;即使 CONFIG 未被禁用,以非 root 用户运行 Redis 进程,使其无权写入 Web 目录;Web 服务器配置禁止解析 RDB 二进制文件,限制上传目录的执行权限。以下是一个加固后的 Redis 启动配置示例:
# 以专用用户运行 user redis # 工作目录设置为仅 redis 用户可写的路径 dir /var/lib/redis # 禁用危险命令 rename-command CONFIG "" rename-command BGSAVE "" rename-command BGREWRITEAOF ""
另一种更隐蔽的攻击手法是利用主从复制。攻击者搭建一个恶意的 Redis 主节点,通过 SLAVEOF 命令将受害 Redis 变为从节点,然后利用主节点向从节点同步恶意模块文件(Redis 4.x/5.x 的模块加载功能),最终通过 MODULE LOAD 加载 .so 文件执行系统命令。防御方法是禁用 SLAVEOF 和 MODULE 相关命令:
rename-command SLAVEOF "" rename-command REPLICAOF "" rename-command MODULE ""容器化环境的特殊风险
Docker 容器中运行 Redis 时,常见的安全误区是依赖容器隔离而忽略 Redis 自身配置。默认的 Redis 镜像通常不设置密码,如果容器端口被映射到宿主机公网 IP,风险等同于裸奔。更危险的是,部分编排工具会自动生成端口映射规则,开发者在不知情的情况下将 Redis 暴露出去。
容器化部署 Redis 时,建议使用自定义配置文件覆盖镜像默认配置,通过环境变量或 Secret 管理工具注入密码,避免将密码硬编码在 Dockerfile 或 docker-compose.yml 中。Kubernetes 环境下,使用 NetworkPolicy 限制只有特定 Pod 标签的应用可以访问 Redis Service,配合 RBAC 控制对 Redis Secret 的读取权限。
定期更新与漏洞响应Redis 官方对安全漏洞的响应速度很快,但前提是运维团队能够及时跟进。保持 Redis 版本在最新的稳定版,关注官方的安全公告邮件列表。对于无法立即升级的生产环境,至少确保启用了所有可用的安全配置选项。历史上 Redis 出现过整数溢出导致的堆溢出漏洞(CVE-2021-32625)、Lua 沙箱逃逸漏洞等,这些漏洞的利用前提往往是攻击者已经通过未授权访问获得了命令执行权限——再次印证了基础安全配置的重要性。
建立 Redis 安全基线检查清单,定期审计所有实例的配置:确认 bind 地址非 0.0.0.0、requirepass 已设置且强度达标、危险命令已禁用、ACL 规则符合最小权限原则、TLS 已启用(如果跨网络传输)、运行用户非 root、日志监控已覆盖。将检查结果纳入安全运营流程,对新增实例自动执行基线扫描,防止配置漂移引入风险。
