bigywater.tech
Redis · 126

Redis 认证流程

连上 Redis 之后到底要经过什么才能执行命令?这篇把认证流程每一步的服务端回答量出来:没登录能做什么,几种登录方式,requirepass 和 ACL 是什么关系,改密码对老连接的影响,密码会不会漏到监控里,以及最关键的——错误密码能试多快。

NOAUTH
设了密码后未登录的连接,除 AUTH / HELLO … AUTH / QUIT 外全部被拒
26089/s
本机回环上一问一答的错误 AUTH 速率;流水线约 332590/s,没有观察到任何限速或锁定
明文
CONFIG GET requirepass 返回明文密码;AUTH 在 MONITOR / SLOWLOG 里被打码

没设密码时的 AUTH,以及设了之后未登录能做什么

实测 · 本机执行输出
> AUTH whatever
(error) ERR AUTH <password> called without any password configured for the default user. Are you sure your configuration is correct?
实测 · 本机执行输出
> CONFIG SET requirepass S3cretPw
"OK"
> CONFIG GET requirepass
1) "requirepass"
2) "S3cretPw"
  PING                 → (error) NOAUTH Authentication required.
  GET k                → (error) NOAUTH Authentication required.
  SET k v              → (error) NOAUTH Authentication required.
  ECHO x               → (error) NOAUTH Authentication required.
  INFO                 → (error) NOAUTH Authentication required.
  COMMAND COUNT        → (error) NOAUTH Authentication required.
  CLIENT SETNAME x     → (error) NOAUTH Authentication required.
  SELECT 0             → (error) NOAUTH Authentication required.
  HELLO 2              → (error) NOAUTH HELLO must be called with the client already authenticated, otherwise the HELLO <proto> AUTH <user> <pass> opt
  QUIT                 → "OK"

设了 requirepass 后,未登录连接发出的几乎任何命令都是 NOAUTH,包括 PING、INFO、HELLO 2(不带 AUTH)。QUIT 回 OK(它只是关连接)。

三种登录方式

实测 · 本机执行输出
> AUTH wrongpw
(error) WRONGPASS invalid username-password pair or user is disabled.
> AUTH S3cretPw
"OK"
> ACL WHOAMI
"default"
> AUTH default S3cretPw
"OK"
> HELLO 2 AUTH default S3cretPw  → 登录后 ACL WHOAMI = default
> HELLO 2 AUTH default bad → (error) WRONGPASS invalid username-password pair or user is disabled.

错误的用户名、错误的密码、被 off 的用户,得到的是同一句 WRONGPASS,攻击者无法据此判断用户名是否存在。

requirepass 与 default 用户

实测 · 本机执行输出
> AUTH S3cretPw
"OK"
> ACL LIST
1) "user default on sanitize-payload #3556ff3510590c935379c2dda7554753f688a012855630f0b9979db3c58a0b3e ~* &* +@all"
> ACL SETUSER default nopass
"OK"
> CONFIG GET requirepass
1) "requirepass"
2) "S3cretPw"
> ACL LIST
1) "user default on nopass sanitize-payload ~* &* +@all"
  现在 default 已是 nopass,但 CONFIG GET requirepass 还显示旧密码。再执行一次相同值的 CONFIG SET requirepass:
> CONFIG SET requirepass S3cretPw
"OK"
> ACL LIST
1) "user default on nopass sanitize-payload ~* &* +@all"
> ACL SETUSER default resetpass >S3cretPw
"OK"
  用 ACL SETUSER default resetpass >S3cretPw 恢复:
> ACL LIST
1) "user default on sanitize-payload #3556ff3510590c935379c2dda7554753f688a012855630f0b9979db3c58a0b3e ~* &* +@all"
> CONFIG SET requirepass S3cretPw
"OK"

requirepass 只是设置 default 用户密码的旧接口。要小心两点:一是 CONFIG GET requirepass 返回的是明文,任何有 +config|get 权限的用户都能读到(第 123 篇的子命令粒度可以限制);二是 ACL SETUSER default nopass 之后 CONFIG GET requirepass 还显示旧值,同值的 CONFIG SET requirepass 没有效果。判断当前到底要不要密码,看 ACL LIST 里的 default 一行。

身份切换、改密码

实测 · 本机执行输出
> ACL SETUSER alice on >ap ~* +@all
"OK"
> ACL SETUSER bob on >bp ~* +@all
"OK"
> AUTH alice ap
"OK"
> ACL WHOAMI
"alice"
> AUTH bob bp
"OK"
> ACL WHOAMI
"bob"
> AUTH bob nope
(error) WRONGPASS invalid username-password pair or user is disabled.
> ACL WHOAMI
"bob"
实测 · 本机执行输出
> AUTH S3cretPw
"OK"
> CONFIG SET requirepass NewPw!
"OK"
> GET k
(nil)
> AUTH S3cretPw
(error) WRONGPASS invalid username-password pair or user is disabled.
> AUTH NewPw!
"OK"

同一条连接可以重新 AUTH 成另一个用户。失败的 AUTH 不改变当前身份。改密码只影响之后的登录,已经登录的连接继续有效——所以怀疑密码泄露时,改密码之后还要把旧连接踢掉(CLIENT KILL 本文没有验证)。

密码会不会漏到观察工具里

实测 · 本机执行输出
> AUTH NewPw!
"OK"
> CONFIG SET slowlog-log-slower-than 0
"OK"
  MONITOR 回复: OK
  MONITOR 里与认证相关的行:
    1790730769.580503 [0 127.0.0.1:61644] "AUTH" "(redacted)"
    1790730769.580666 [0 127.0.0.1:61644] "AUTH" "(redacted)" "(redacted)"
    1790730769.580796 [0 127.0.0.1:61644] "AUTH" "(redacted)" "(redacted)"
  SLOWLOG 里与认证相关的条目(命令参数):
    ['CONFIG', 'SET', 'requirepass', '(redacted)']
    ['ACL', 'SETUSER', '(redacted)', '(redacted)']
    ['AUTH', '(redacted)', '(redacted)']
    ['AUTH', '(redacted)', '(redacted)']
    ['AUTH', '(redacted)']
    ['AUTH', '(redacted)']
  CLIENT LIST 里有没有密码文本: False

AUTH 的参数、CONFIG SET requirepass 与 ACL SETUSER 里的密码在 SLOWLOG 里都是 (redacted);MONITOR 里 AUTH 也被打码。这次 MONITOR 抓取里没有出现 CONFIG SET 和 ACL SETUSER 两行(原因没有验证)。但要注意:redis.conf 里的 requirepass 是明文,备份与配置文件的权限见第 132 篇。

错误密码能试多快

实测 · 本机执行输出
  一问一答:5000 次错误 AUTH 0.19 s → 26089 次/秒
  流水线:20000 次错误 AUTH + 1 次正确 AUTH + PING 一次性发出,0.06 s 后收到 PONG;
  收到的全部回复字节数 2700,其中 WRONGPASS 42 条、OK 1 条、PONG 1 条
  服务端 INFO stats 里 acl_access_denied_auth 增加了 20000(这 20000 次错误尝试都被计数,但客户端只收到 42 条错误回复)

一问一答 26089 次/秒,流水线把 20000 次错误尝试在 0.06 s 里送完,最后的正确密码照样收到 OK。服务端把每次尝试都计入 acl_access_denied_auth,但流水线里的失败回复客户端只收到了 42 条——为什么没有验证,只是观察到的事实。这里没有观察到任何延迟、限速或锁定。所以 Redis 的密码不能当「有人试就会被挡住」的机制,它需要足够长的随机密码 + 不暴露在不可信网络。

分步演示:认证的每一步

Redis 认证
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Redis 8.10.2 独立实例(本机回环端口,save 关闭),redis-cli 风格输出由自写的 RESP 客户端打印;计时用 time.perf_counter,数字每次运行会有小幅抖动。本机回环、密码是测试用的短串
    • 没有验证:网络往返下的尝试速度、CLIENT KILL USER、多连接并发下的速率、Redis 8 之前版本的 MONITOR 打码行为、流水线里失败回复被合并/丢弃的原因、密码比较是否为常量时间
    京ICP备2026067502号-1京公网安备11010502063487号