今日重点:🏷️ 术语卡——今天雷达的头条之一是 kTLS 学会 KeyUpdate:RFC 9846 把 TLS 1.3 的密钥用量上限从建议写成 MUST,内核记录层连夜补课。这个系列自带一条词汇链: 先给「在哪做」起名,再给「做什么」起名,然后是「用什么做」,最后是「什么时候必须做」。 四个词按「层 → 消息 → 材料 → 大限」串起来记,因为它们本来就在 同一条因果链上:只有 record layer 数得清记录数,所以换钥匙只能在这里做。 定义逐字取自系列头封,发出于北京时间 10-30 晚,今天还在评审中。

📖 原文(真实定义,逐字引用)

/ section
GnuTLS sends a KeyUpdate after 2^24 records when it runs its own record layer. With kTLS, the record layer is handled in the kernel and GnuTLS therefore never runs the check.
RFC 9846 (July 2026), which obsoletes RFC 8446, makes the limit mandatory (section 5.5): "Implementations MUST either close the connection or do a key update as described in Section 4.7.3 prior to reaching these limits."

出处:Martin Belanger(Dell)的系列头封 [PATCH RFC net-next v3 0/5] tls: perform TLS 1.3 KeyUpdate in the kernel。 下面四张卡的定义全部出自这一封邮件。 顺带一处用词:作者写 obsoletes RFC 8446——RFC 新替旧的标准动词就是 obsolete(及物),比 "replaces" 正式,写协议相关文字时直接用。

🏷️ 术语一:record layer —— 层

/ column

★ record layer(记录层)

TLS 里负责加密分帧的那一层,也是唯一能数清记录数的地方

原文定义 With kTLS, the record layer is handled in the kernel. / KeyUpdate must be handled where the records are built.
中文与角色 TLS 连接里,应用看到的是字节流,线上跑的是一条条 record(记录);负责把字节流切片、加密、封装成记录的那一层就是 record layer。kTLS 把它下沉进内核之后,用户态库不再自己跑这一层。注意原文第二句的定义方式:不解释概念,直接给判据——KeyUpdate 必须住在「盖记录的地方」,因为 2^24 是记录计数,只有这一层看得清拆分合并后的真实计数。
为什么位置这么讲究 作者实测:在 NVMe/TCP 原型里按 send 次数猜记录数,4 KB I/O 时猜得对,1 MB I/O 时差了 21 倍——一次 send 会被内核拆成多少条记录并不固定。所以 It's simply not possible to precisely guess the number of records based on the number of send calls.
记忆钩子 看到 layer,先问:这一层能看见什么别人看不见的状态?record layer 能看见记录的真实边界与计数——这就是它不可替代的原因。

🏷️ 术语二:KeyUpdate —— 消息

/ column

★ KeyUpdate(在线换密钥消息)

TLS 1.3 的不停机密钥轮换:不断连、不重握手

原文定义 The KeyUpdate must also go at a precise place in the record stream (section 4.7.3). It is encrypted with the old key, and every record after it with the new key.
中文与角色 KeyUpdate 是 TLS 1.3 协议里的一条控制消息,作用就一句话:从这条消息之后,换新密钥。两个约束都被原文点死:位置精确——它本身用旧密钥加密,之后的每条记录立刻换新密钥,钥匙只能在两条记录之间换;时机有 deadline——对端发来 update_requested 时,我们的 KeyUpdate 必须赶在下一条 Application Data 记录之前发出去。
工程形态 这个系列里它的落地分两侧:接收侧 kTLS consumes the KeyUpdate, installs the next key and continues(对 recvmsg / splice / read_sock 都生效);发送侧到 2^24 条记录自动发,并回应 update_requested。另有一条防线:对端一秒内发超过 8 个 KeyUpdate 直接断连——与 GnuTLS 同款限速,防恶意刷消息。
记忆钩子 KeyUpdate 不是「重新握手」,是在记录流里插队的一条换岗通知:旧钥匙签退,新钥匙从下一条记录上岗。

🏷️ 术语三:traffic secret —— 材料

/ column

★ traffic secret(流量秘密)

新密钥的推导原料,握手后由用户态注册进内核

原文定义 With this series, kTLS handles KeyUpdate in both directions for a socket that registers its traffic secrets. / Two new socket options, TLS_TX_TRAFFIC_SECRET and TLS_RX_TRAFFIC_SECRET, are used to register the application traffic secrets.
中文与角色 TLS 1.3 的密钥不是换出来的,是推出来的:握手产生 application traffic secret,之后每一代密钥都由它经 HKDF-Expand-Label 单向推导(与内核在审的 QUIC 系列同款做法)。kTLS 要自己能换密钥,就得先拿到这份原料——所以系列新增两个 socket 选项让 socket 注册秘密;不注册则一切照旧。顺序也有讲究:TX 秘密必须先设,因为 RX 秘密要应对「收到的 KeyUpdate 要求回一个」的场景。
分工边界 握手留在用户态,秘密通过 socket 选项传进来,推导与轮换在内核——这条「handshake stays in user space, secrets passed in, kernel derives」的分工是内核加密 offload 的通用范式,QUIC 系列是同一张图纸。
记忆钩子 secret 是原料,key 是产物:注册一次 secret,内核就能自己一代代推 key,不用每次回头找应用。

🏷️ 术语四:2^24 record limit —— 大限

/ column

★ 2^24 record limit(密钥用量上限)

RFC 9846 把它从建议升级成 MUST,长连接第一个撞线

原文定义 Implementations MUST either close the connection or do a key update as described in Section 4.7.3 prior to reaching these limits.(RFC 9846 section 5.5,作者在头封中引用)
中文与角色 同一把密钥能加密的记录数有上限——AES-GCM 类算法是 2^24.5,撞线前必须换密钥或断连。内核实现留了余量:发到 2^24 条就主动换,a margin below the 2^24.5 limit of RFC 9846 section 5.5。ChaCha20-Poly1305 没有记录数上限,是例外。
为什么这条新闻上了头条 旧标准 RFC 8446 里这只是建议,2026 年 7 月发布的 RFC 9846 把它写成 MUST——「能跑」和「合规」从此分家。而长连接小记录场景撞线极快:NVMe/TCP 每条命令至少一条记录,按负载与链路速度,the 2^24 limit can be reached in less than 10 minutes in many cases。NVMe/TCP 与 sunrpc 这类内核用户自己不会装新密钥,遇到合规对端发来的 KeyUpdate 只能卡住——这正是这个系列要补的课。
记忆钩子 记两个数:2^24.5 是 RFC 的线,2^24 是内核的余量。实现标准时永远给自己留 margin,别贴着线上跳舞。

把四张卡连起来:record layer 是唯一数得清记录的地方(层), 数到 2^24 就必须发 KeyUpdate(消息),新密钥从注册进来的 traffic secret 推导(材料),RFC 9846 把这条线写成 MUST(大限)。 一环扣一环——所以「换钥匙」这件事,只能住在盖记录的地方。

✨ 辅助彩蛋:guesstimate

/ section

★ 猜测不够,估算太慢——合成一个词

guess + estimate = guesstimate

原句 I counted send calls in an NVMe/TCP prototype trying to guesstimate the 2^24 limit. The count was correct with 4 KB I/O, but was 21 times too low with 1 MB I/O.
中文与用法 guesstimate 是 guess 与 estimate 的合成词:没有精确数据时拍一个「有依据的猜」。它自带一点自嘲——作者用它坦白「我当年只能蒙」,为后面「蒙错了 21 倍」的翻车数据做铺垫。口语和工程写作里都能用,语气比 estimate 随意,比 guess 认真。
仿写示范 We tried to guesstimate the interrupt rate from the log timestamps, but bursty traffic made every estimate land wide of the mark.(仿写示范)

✍️ 今日练习

/ column
✍️ 用英文回答三问,答案尽量落在原文的词上:① 作者给出哪两条理由,说明 KeyUpdate 必须在 record layer 处理?② RFC 9846 section 5.5 要求实现在撞限前做什么(用原文的 MUST 句作答)?③ 一个 socket 要注册什么、通过哪两个 socket 选项,kTLS 才能双向替它处理 KeyUpdate?
💡 显示答案
参考作答(仿写示范,非原文):① First, the 2^24 limit is a record count, and only the record layer can see the count precisely as it changes — counting send calls can be 21 times off. Second, the KeyUpdate must go at a precise place in the record stream: encrypted with the old key, with every record after it using the new key, and only the record layer controls that boundary. ② Implementations MUST either close the connection or do a key update as described in Section 4.7.3 prior to reaching these limits. ③ The socket must register its application traffic secrets, via the TLS_TX_TRAFFIC_SECRET and TLS_RX_TRAFFIC_SECRET socket options (TX first, because a received KeyUpdate may ask for a reply).
📖 原文:KeyUpdate must be handled where the records are built. The 2^24 limit is a record count, and only the record layer can see the count precisely as it changes. / The KeyUpdate must also go at a precise place in the record stream (section 4.7.3). It is encrypted with the old key, and every record after it with the new key. / Implementations MUST either close the connection or do a key update as described in Section 4.7.3 prior to reaching these limits. / Two new socket options, TLS_TX_TRAFFIC_SECRET and TLS_RX_TRAFFIC_SECRET, are used to register the application traffic secrets.
📎 原文引用

每日一句:A limit you cannot count is a limit you cannot enforce — put the mechanism where the records are built.

仿写示范