首页 / Redis 入门教程 / 安全机制与 ACL 权限控制

Redis 入门教程

安全机制与 ACL 权限控制

本教程共 40 篇 · 第 36 篇 · 更新于 2026-08-02

安全ACLrequirepass命令重命名网络安全权限

36. 安全机制与 ACL 权限控制

「码上学」提醒你:Redis 默认是一个「不设防」的服务——只要能连上,就能执行任何命令、读走全部数据。把开发环境默认配置直接搬到生产,相当于把数据库钥匙挂在门上。本章带你把 Redis 的安全闸门关好:从最朴素的密码,到 Redis 6 引入的 ACL 细粒度权限,再到网络层面的保护。

本节目标

  • 理解 Redis 默认安全模型(无密码、绑定环回、protected-mode)及其风险。
  • 掌握 requirepass 兼容密码的设置、验证与持久化方法。
  • 掌握 ACL 用户体系:创建用户、限制命令类别与键模式、查看拒绝日志。
  • 了解命令重命名(rename-command)的取舍与替代方案。
  • 落实网络层防护:绑定地址、protected-mode、防火墙与传输加密。

一、Redis 的默认安全现状

Redis 8.x(最新稳定版)安装后,默认配置有几个关键特征,理解它们才能知道「缺了什么」:

  1. 默认无密码requirepass 为空,连上即可执行命令。
  2. 绑定环回地址bind 127.0.0.1 -::1,只接受本机连接。
  3. 保护模式开启protected-mode yes,当默认用户无密码且未显式关闭时,仅允许本地 IPv4/IPv6 环回和 Unix 套接字连接。

这三点组合在一起,让「单机本机」的开发场景相对安全。但一旦你把 bind 改成 0.0.0.0(监听所有网卡)又没设密码,且关掉了 protected-mode,实例就会暴露给整张网络——这是 Redis 被攻击、被植入挖矿程序最常见的原因。

提示:永远不要让无密码的 Redis 监听公网 IP。如果确实需要远程访问,至少同时做到「设强密码 + 绑定内网地址 + 防火墙白名单 + 传输加密」。

二、requirepass:最朴素的密码保护

requirepass 是 Redis 最早期就存在的密码机制,在 Redis 6 之后它本质上是 ACL 系统的一层兼容外壳:设置它等于给 default 用户设置一个密码。

查看当前是否设置了密码:

127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) ""

空字符串表示未设置密码。临时设置(重启后失效)用 CONFIG SET

127.0.0.1:6379> CONFIG SET requirepass "S3cretP@ss"
OK
127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) "S3cretP@ss"

设置之后,任何未认证的连接执行命令都会被拒绝:

127.0.0.1:6379> GET mykey
(error) NOAUTH Authentication required.

客户端通过 AUTH 命令验证身份:

127.0.0.1:6379> AUTH "S3cretP@ss"
OK
127.0.0.1:6379> SET mykey "hello"
OK
127.0.0.1:6379> GET mykey
"hello"

永久生效需要把改动写回配置文件。可以运行 CONFIG REWRITE 让 Redis 自动重写 redis.conf

127.0.0.1:6379> CONFIG REWRITE
OK

也可以直接在 redis.conf 中写入:

requirepass S3cretP@ss

然后重启服务。命令行连接时也能用 -a 直接带密码:

redis-cli -h 127.0.0.1 -p 6379 -a "S3cretP@ss"

requirepass 简单,但只能给整个实例设一个全局密码,无法区分「哪些人能做什么」,所有知道密码的人权限完全一样。多应用、多团队共用一个实例时,这种粗放模型就不够用了——这正是 ACL 登场的原因。

三、ACL:细粒度的用户权限体系

从 Redis 6 起,ACL(Access Control List)提供了「用户 + 命令权限 + 键模式 + 频道权限」的完整授权模型。先看看当前身份:

127.0.0.1:6379> ACL WHOAMI
"default"

查看已有用户:

127.0.0.1:6379> ACL LIST
1) "user default on nopass ~* +@all"

这行含义:default 用户启用(on)、无密码(nopass)、可访问所有键(~*)、拥有全部命令权限(+@all)。

3-1 创建受限用户

假设有一个「缓存应用」只需要读写 cache: 前缀的键,不能碰 FLUSHALLCONFIG 等危险命令:

127.0.0.1:6379> ACL SETUSER appcache on >app123 ~cache:* +get +set +del +expire
OK
127.0.0.1:6379> ACL LIST
1) "user appcache on #e3c7... ~cache:* +get +set +del +expire"
2) "user default on nopass ~* +@all"

字段拆解:

  • on:启用该用户。
  • >app123:设置密码(明文前缀 >,存储为 SHA-256 哈希)。
  • ~cache:*:只能访问匹配 cache:* 模式的键。
  • +get +set +del +expire:明确放行的命令(白名单)。

用该用户登录后,越权命令会被拒绝:

127.0.0.1:6379> AUTH appcache app123
OK
127.0.0.1:6379> SET cache:user:1 "tom"
OK
127.0.0.1:6379> GET cache:user:1
"tom"
127.0.0.1:6379> DEL other:key
(error) NOSCRIPT No permissions to access a key
127.0.0.1:6379> FLUSHALL
(error) NOPERM User appcache has no permissions to run the 'flushall' command

3-2 用命令类别授权

逐条列命令太繁琐。Redis 把命令归为多个类别(category),用 +@类别 整体授权。常见类别有:@all(全部)、@admin(管理类如 CONFIG/ACL/SHUTDOWN)、@dangerous(危险类如 FLUSHALL/KEYS/DEBUG)、@read@write@connection@string@hash@list@set@sortedset@pubsub@transaction@scripting 等。

例如创建一个「只读数据分析师」用户:

127.0.0.1:6379> ACL SETUSER analyst on >analyst123 ~* +@read -@admin -@dangerous
OK

+@read 放行所有读命令,-@admin -@dangerous 再剔除管理与危险类别。注意 ACL 规则按从左到右顺序求值:先 +@read 再加禁,与「先禁后加」结果不同,写规则时要留意顺序。

3-3 持久化 ACL 与外部文件

运行时 ACL SETUSER 创建的用户在重启后会丢失。两种方式持久化:

  1. redis.conf 直接写 user 行(与 ACL SETUSER 语法一致)。
  2. 用独立 ACL 文件,配置 aclfile /etc/redis/users.acl,再执行:
127.0.0.1:6379> ACL SAVE
OK

注意:requirepassaclfile/ACL LOAD 不兼容——启用外部 ACL 文件后,requirepass 会被忽略。二者只能取其一。

3-4 审计:ACL LOG

当命令被 ACL 拒绝时,事件会记入内存中的 ACL 日志,便于排错与安全审计:

127.0.0.1:6379> ACL LOG 1
1) 1) "username"
   2) "appcache"
   3) "reason"
   4) "command the user is not allowed to run"
   5) "command"
   6) "flushall"

日志长度由 acllog-max-len 128 控制(来自 redis.conf 默认值)。排错完毕后可用 ACL LOG RESET 清空。

四、命令重命名(rename-command)

在共享环境中,可以把危险命令改名成难以猜测的字符串,或直接禁掉。它在 redis.conf 中配置:

# 把 CONFIG 改成一个随机串,仅内部工具知晓
rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
# 彻底禁用 FLUSHALL
rename-command FLUSHALL ""

重要:redis.conf 中明确标注该选项已弃用(DEPRECATED)。官方建议改用 ACL——把危险命令从 default 用户移除,单独建一个 admin 用户来持有它们。此外,被改名的命令如果写进了 AOF 文件或同步给从节点,可能造成兼容性问题。

五、网络层与传输安全

密码和 ACL 解决「谁能执行什么」,但网络层决定了「谁能连上来」。

  • 绑定地址 bind:生产环境应绑定内网/特定网卡地址(如 bind 10.0.0.1),不要 0.0.0.0 裸奔。
  • 保护模式 protected-mode:无密码时强制只接受本地连接;只有在「确定要开放远程且无密码」时才关闭,而这本身不推荐。
  • 防火墙:在云安全组/iptables 上只允许应用服务器 IP 访问 6379 端口。
  • 传输加密:Redis 原生支持 TLS(编译时开启 BUILD_TLS=yes,用 redis-cli --tls 连接)。若不便启用,可在前置放 stunnel 之类的隧道,避免明文密码与数据在公网传输。
  • 禁用或重命名危险命令:结合第四节,最大限度缩小爆炸半径。

六、常见误区

  • 误区一:「设了 requirepass 就高枕无忧。」它只解决认证,不解决越权;多租户场景请用 ACL。
  • 误区二:「bind 127.0.0.1 已经够安全,公网也暴露无所谓。」一旦有反向代理或容器端口映射把它透出,保护模式可能被绕过,仍需密码。
  • 误区三:「用 rename-command 改名等于加密。」改名只是提高门槛,不是真正的保密手段,且已被官方标记为弃用。
  • 误区四:「Redis 跑在容器里默认安全。」容器默认常把端口映射到 0.0.0.0,务必检查宿主机防火墙与 bind

提示:本章正文统一以 Redis 8.x(最新稳定版) 表述。需补充的是,官方 redis.io 下载页另将 8.8 标注为 “Latest stable”,而 GitHub 上 redis/redis 的最新发布 tag 为 8.10.0;二者同属 8.x 系列,命令与权限模型对教材内容没有影响。