资讯详情

资讯详情

Redis『4GB 边界』:集群总线 pub/sub 堆溢出该怎么查

一句话结论这次两家同时修的漏洞触发条件写得非常具体——集群模式、集群总线、PUBLISH/SPUBLISH、传播过程、消息大于 4GB五个条件缺一不可真正要动手的不是「有没有用 pub/sub」而是五个条件在你的拓扑里能不能同时成立。项内容摘要10 月 26 日 Redis 与 Valkey 同日发布安全版修的都是「集群模式下经集群总线传播超过 4GB 的 PUBLISH 消息导致堆溢出」。本文逐条拆官方公告的触发条件指出两家用语上的差异用零依赖脚本把 4GB 边界、集群总线扇出量与配置自查项算成可直接执行的清单。前置知识Redis Cluster 的基本形态节点间通过集群总线通信知道 PUBLISH/SPUBLISH 与集群总线的关系读过一次proto-max-bulk-len这类配置项阅读时间约 16 分钟代码环境Python 3.9零第三方依赖不联网输出确定无随机源脚本见_脚本/redis_cluster_bus_4gb.py读完你能做什么能在 10 分钟内判断自己集群是否落在触发条件里能解释为什么 4GB 不是「一个建议值」而是 32 位长度字段的天花板能给出升级之外的三条缓解路径能在变更单里写清跨七条 Redis 产品线的一致性修复范围一手来源有三处本文引用的每一句话都能在其中点到Redis Open Source 8.10 发布说明00-RELEASENOTES8.10.3Released Mon 26 Oct 2026Valkey 9.1.3 / 9.0.7 / 8.0.12 发布公告GHSA-f4q9-j22m-xqq9Released Mon 26 October 2026endoflife.date 的 Redis 版本与日期表2026-10-27 更新一、这两天到底发布了什么Redis 8.10.3 的发布说明很短头部三段可以直接逐字引Redis 8.10.3 Released Mon 26 Oct 2026 10:00:00 IST Update urgency: SECURITY: There are security fixes in the release. ### Security fixes - Heap buffer overflow when propagating a PUBLISH/SPUBLISH message larger than 4GB over the cluster bus in cluster mode一句话里有六个限定词堆缓冲区溢出heap buffer overflow、传播过程propagating、PUBLISH/SPUBLISH消息、大于 4GB、经集群总线over the cluster bus、集群模式in cluster mode。安全修复只有这一条没有第二条。Valkey 侧的公告是同一天编号GHSA-f4q9-j22m-xqq9措辞如下Fix a heap buffer overflow in cluster Pub/Sub message construction that could allow an authenticated client to potentially execute arbitrary code by publishing an oversized message修复同时进了三条产品线Valkey 9.1.3、9.0.7、8.0.12发布日期同为 2026 年 10 月 26 日对应 PR 为#5030。再看 Redis 的版本表会发现一件更有信息量的事——同一天新增补丁的不止一条产品线产品线当日新增版本日期安全支持状态Redis 8.108.10.32026-10-26是当前稳定Redis 8.88.8.42026-10-26是维护中Redis 8.68.6.82026-10-26是维护中Redis 8.48.4.82026-10-26是维护中Redis 8.28.2.112026-10-26是安全支持Redis 7.47.4.122026-10-26是安全支持Redis 7.27.2.172026-10-26是安全支持七条线同一天打补丁说明有问题的这段代码在多条线里共享存在的时间也不短。这也是为什么「我们用的是 7.2应该没事」这类判断不成立。二、触发条件逐条拆五个条件缺一不可官方给的触发条件可以拆成一个五项的与门几点容易被读错的细节「集群总线」不是「数据复制链路」。集群总线是节点之间用于 gossip、故障检测、迁移协商、以及 pub/sub 扇出的那条独立通道端口通常是客户端端口 10000。它和主从复制的数据链路不是一回事。这条链路在规范配置里不该暴露到公网或业务网。PUBLISH与SPUBLISH是两种 pub/sub 语义。前者是集群范围广播后者是分片shard范围内的广播。两者都在公告描述里说明问题出在「构造要送出去的总线消息」这个共同环节而不是某一种订阅形式。两家的前置条件描述不一致。Valkey 的公告写了authenticated client经过认证的客户端Redis 的发布说明只写了漏洞本体没有描述前置认证状态。这两个口径不能互相替代——看到 Valkey 写了「需要认证」就推断 Redis 侧也一样从而放松内网策略是不严谨的做法。正确做法是按各自公告的最小值执行[未被官方说明的部分一律按更保守的前提处理]。三、4GB 这个数字为什么眼熟4GB 不是随手写的「一个很大的值」。它不是 GiB 的整数典故而是 32 位无符号整数的天花板2^32 4,294,967,296字节 4 GiB一个uint32长度字段能表示的范围是0 … 2^32 - 1一旦真实长度越过2^32写进 32 位字段的值会被截断成一个远小于真实值的数推论部分需要明确标注Redis 与 Valkey 的公告都没有给出根因分析也没有说明是哪一个长度字段、哪一段内存分配出了问题。下面这句是工程推断不是官方结论——「按截断后的长度分配缓冲区再按真实长度写入就会写越界」。把这个推断写在纸上是为了让排查方向清楚不能拿它当成事实引用。真正准确的公开事实只有一条在官方描述的五个条件下会发生堆缓冲区溢出。四、动手验证把能算的部分算出来漏洞本体不需要也不是我们能复现的。但有三件事是可以直接算出来的它们决定了你的排查顺序。脚本_脚本/redis_cluster_bus_4gb.py零依赖本机实跑WindowsPython 3.13.12输出如下节选第 1 段2^32 边界真实消息长度 | 真实长度 | 按 uint32 截断后 | 分配缺口 ---------------------------------------------------------------------------------- 2^32 - 2 B | 4.00 GiB | 4.00 GiB | 0.00 B 2^32 - 1 B | 4.00 GiB | 4.00 GiB | 0.00 B 2^32恰好 | 4.00 GiB | 0.00 B | 4.00 GiB - 越过 4 GiB 边界 2^32 1 B | 4.00 GiB | 1.00 B | 4.00 GiB - 越过 4 GiB 边界 2^32 4 KiB | 4.00 GiB | 4.00 KiB | 4.00 GiB - 越过 4 GiB 边界 2^32 1 GiB | 5.00 GiB | 1.00 GiB | 4.00 GiB - 越过 4 GiB 边界 2^33两倍 | 8.00 GiB | 0.00 B | 8.00 GiB - 越过 4 GiB 边界跨越边界之后截断值直接掉到一个极小的数量级。「4GB 边界」在这类内存安全问题里通常意味着长度口径虽然是 64 位但中间某个环节把它塞进了 32 位。第 2 段集群总线扇出一条 4 GiB 的PUBLISH在全互联的总线拓扑里要被扇出到其余每一个节点搬运总量是(节点数 - 1) × 消息大小集群节点数总线搬运总量1 GbE10 GbE25 GbE40 GbE38.00 GiB76.4 s7.6 s3.1 s1.9 s620.00 GiB3.2 min19.1 s7.6 s4.8 s932.00 GiB5.1 min30.5 s12.2 s7.6 s1244.00 GiB7.0 min42.0 s16.8 s10.5 s30116.00 GiB18.5 min1.8 min44.3 s27.7 s100396.00 GiB63.0 min6.3 min2.5 min1.6 min脚本假定链路有效吞吐为线速的 90%只用于量级估算。这张表的用法不在于「攻击要多久」而在于爆炸半径节点越多一条超大消息占满总线的时间越长这段时间里 gossip、心跳、故障检测、槽迁移消息全部在排队。对一个 30 节点以上的集群来说即便不考虑内存安全本身把单条 pub/sub 消息做到 GiB 量级也已经是自伤行为。第 3 段配置自查proto-max-bulk-len 取值 | 单个 bulk 上限 | 能否越过 4 GiB 边界 ------------------------------------------------------------------------------ 512.00 MiB | 512.00 MiB | 不能 1.00 GiB | 1.00 GiB | 不能 2.00 GiB | 2.00 GiB | 不能 4.00 GiB | 4.00 GiB | 不能 8.00 GiB | 8.00 GiB | 能proto-max-bulk-len限制的是客户端协议里单个 bulk string 的大小Redis 默认值是 536870912 字节512 MiB。它是「多大的消息能被塞进来」的第一道闸门。需要说清楚的一句官方没有说明超限消息是通过哪条路径构造出来的——是单个超大 bulk还是内部构造总线消息时的累积结果。因此这一段只用于回答「我的配置有没有为超大消息开门」不能反过来推出「只要 proto-max-bulk-len 是 512MB 就绝对无风险」。五、常见误区误区一我们没用 pub/sub所以不用升级。补丁是发布级的发布里除安全修复外还有一批常规修复更重要的是修复后能不能构造出超限消息这件事对新行为是全局约束。按产品线版本直接升级不做「选择性升级」。误区二这是 Redis 的问题我们用的是 Valkey。两个项目这次修的是同一类代码问题Valkey 三条产品线同日发布补丁。用 Valkey 的团队要升级到 9.1.3 / 9.0.7 / 8.0.12 之一。误区三只看 Valkey 公告里的「认证过的客户端」。前文说过两家的前置条件描述不一致。内网 弱口令 PUBLISH 权限的组合在很多部署里是存在的。误区四把单实例的maxmemory当成防线。maxmemory管的是数据集不管单条协议消息的构造过程也不管集群总线的缓冲区。误区五只升级主节点。集群总线是全互联的任何一个未升级节点都保留着有问题的那一段代码。六、排查与缓解清单可直接进变更单#动作判定 / 目的地1列出全部集群实例的版本目标Redis ≥ 8.10.3 / 8.8.4 / 8.6.8 / 8.4.8 / 8.2.11 / 7.4.12 / 7.2.17Valkey ≥ 9.1.3 / 9.0.7 / 8.0.122检查proto-max-bulk-len实际值若被调到 4 GiB 以上回滚到业务需求的最小值并记录原因3检查集群总线端口客户端端口 10000网络可达性不该对公网、也不该对整个业务网开放4审计有PUBLISH/SPUBLISH权限的 ACL 用户收缩到必要的用户与必要的 channel 前缀5确认 pub/sub 消息体的业务上限在应用层加一道大小校验别让总线成为唯一的闸口6升级后回归至少覆盖集群广播、跨节点订阅、故障转移期间的订阅连续性顺序建议先 2、3、4不改版本成本低再排窗口做 1最后 5 进业务迭代。七、适用边界与产业坐标本文的结论建立在两家官方公告的原文之上不包含任何自己构造的攻击样本也没有复现过程。官方未给出 CVE 编号Redis 侧发布说明未引用 CVEValkey 侧用 GHSA 编号[本文写成时未见对应 CVE 编号以官方更新为准]也未说明根因——凡是涉及「为什么坏」的部分上文已明确标为推断。把视角从补丁拉回工程真正容易被忽略的不是这一条 CVE而是企业级缓存部署里 pub/sub 通常没有被当成一等公民治理。它对业务方是「一个广播功能」对运维方是「一条独立通信平面的持续负载」权限往往跟 Redis 用户一起被整体授予消息大小没有上限网络暴露也没有单独审查过。一旦铺开到几十个节点的集群边界在哪里没人说得清。回到国内环境的约束这类组件替换通常要在给定的信创软硬件生态里完成替换对象往往是存量 Redis 集群且要求业务代码不改调用语义。金蝶天燕 Apusic 这条线上分布式缓存 AMDC 承接的是会话与热点数据的缓存语义ADMQ 承接的是消息流本身对运维来说要回答的问题不是「能不能广播」而是广播发生在哪一层、上限设在哪里、谁有权调用——把这件事写进规范比等下一个补丁更有用。具体产品的能力边界以各自的官方文档为准。八、结论2026 年 10 月 26 日Redis 七条产品线同日发布安全补丁Valkey 三条产品线同步修复GHSA-f4q9-j22m-xqq9两者描述的是同一类问题集群模式下经集群总线传播大于 4GB 的PUBLISH/SPUBLISH消息导致堆缓冲区溢出。触发条件是五项的与门集群模式、集群总线、PUBLISH/SPUBLISH、传播过程、大于 4GB。逐条核一遍比整体判断「我们用不用」靠谱。4 GiB 2^32 字节是 32 位长度字段的天花板根因官方未说明相关的推断部分已在文中标出。六节点集群扇出一条 4 GiB 消息要搬 20 GiB在 10 GbE 上约 19 秒——这段时间总线是堵的。两家前置条件口径不一致Valkey 明确写了 authenticated clientRedis 未说明按更保守的前提处理。问一句你们集群的proto-max-bulk-len现在是多少集群总线端口有没有做过单独的网络隔离如果这两个问题的答案需要翻文档才知道建议今天就把它们写进配置基线。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →