用户权限配好了,谁在撞墙?ACL LOG 记录每一次被 ACL 拒绝的操作。这篇把它每个字段的含义、合并规则、上限都在本机触发一遍,并回答一个实际问题:暴力猜密码时它能告诉你什么。
> AUTH app pw "OK" > DEL app:1 (error) NOPERM User app has no permissions to run the 'del' command > GET other:1 (error) NOPERM No permissions to access a key > PUBLISH secret x (error) NOPERM User app has no permissions to run the 'publish' command > AUTH app wrongpw (error) WRONGPASS invalid username-password pair or user is disabled. ACL LOG 共 4 条(新的在前) reason=auth context=toplevel object=AUTH username=app count=1 age=0.001 reason=command context=toplevel object=publish username=app count=1 age=0.001 reason=key context=toplevel object=other:1 username=app count=1 age=0.001 reason=command context=toplevel object=del username=app count=1 age=0.001 一条完整记录的字段: count reason context object username age-seconds client-info entry-id timestamp-created timestamp-last-updated client-info 示例: id=7 addr=127.0.0.1:60726 laddr=127.0.0.1:9126 fd=11 name= age=0 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 watch=0 qbuf=36 qbuf-free=
reason 有 command(命令没权限)、key(key 没权限)、auth(认证失败),还有 channel(频道没权限,本文这一轮没有触发,没有验证)。PUBLISH 被记成 command,因为这个用户根本没有 +publish,判定停在命令那一层。client-info 是 CLIENT LIST 同样格式的一行,能看出是哪个连接(地址、name、库、最后命令)。
200 次 GET other:1 被拒后,条数 1,count=200,timestamp-created→last-updated 相差 14 ms 换一个 key 名 → 是另一条(object 不同): 条数变为 2
200 次相同的失败只有 1 条记录,count 是 200。所以 ACL LOG 是「什么类型的拒绝、多少次」的摘要,不是逐条流水。要逐条审计需要另外的手段(这里没有验证)。
用时 0.06 s,ACL LOG 1 条:reason=auth object=AUTH username=app count=500
500 次错误 AUTH 用了 0.06 s。Redis 对认证失败没有任何限速或锁定(本次实测中没有观察到),ACL LOG 只是把它们累加进一条 reason=auth 记录。所以:密码必须足够长且随机,并且不要把端口暴露给不可信网络(第 128、129 篇)。监控 count 的增长速度可以当告警信号。
> MULTI
"OK"
> DEL app:1
(error) NOPERM User app has no permissions to run the 'del' command
> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
> EVAL "return redis.call('DEL','app:9')" 0
(error) ERR ACL failure in script: User app has no permissions to run the 'del' command script: fab23d6dc04df4c1558e045e620940bbd0c2d064, on @user_script:1.
reason=command context=lua object=del
reason=command context=multi object=delMULTI 里被拒的命令让整个事务 EXECABORT;Lua 里被拒则整个脚本报错。ACL LOG 用 context 字段告诉你这是从哪里来的。
> CONFIG SET acllog-max-len 5 "OK" 制造 12 条不同的 key 拒绝后,日志里剩 5 条,保留的 object: ['z11', 'z10', 'z9', 'z8', 'z7'] ACL LOG 2 只取最新 2 条: 2 条 > ACL LOG RESET "OK" RESET 后: 0 条
日志有条数上限,超过 acllog-max-len 就挤掉最旧的。想长期留存要定期拉取(ACL LOG)并写到外部。