每种 IKE 载荷前面有四字节的通用载荷头。载荷长度把这四字节算进去。临界位管的是当前载荷,不是本头第一字节里写下的下一载荷。规范是 2014 年 10 月的 RFC 7296 第 3.2 节。IKE 头里那个长度是整条消息。
长度把这四字节算进去
一个可独立引用的定义句:载荷长度是 2 个八位组的无符号整数,表示当前载荷的八位组数,包括通用载荷头(RFC 7296 第 3.2 节)。
图 5 是一行 32 位。按图数是 4 个八位组。原文没有印出 4。第 3.3 节到第 3.16 节定义的每种载荷都以这个头开始。下文的图为了省事会再画这四字节,字段说明则不再重复。
| 字段 | 第 3.2 节写明的宽度 | 约束 |
|---|---|---|
| 下一载荷 | 1 字节 | 后面那个载荷的类型。当前已是最后一个时为 0 |
| 临界位 | 1 位 | 管当前载荷。RFC 7296 定义的类型必须置 0 |
| 保留 | 7 位 | 发送必须为 0,收到必须忽略 |
| 载荷长度 | 2 字节 | 当前载荷的八位组数,含这四字节 |
关键词按 RFC 2119。下文的「必须」和「不得」对应原文的大写词。第 3.2 节里仍有小写 must,见加密载荷那一句,本文不把它升成大写。
下一载荷把载荷串起来:把新载荷接在消息末尾,并让前一个载荷的下一载荷字段标出新载荷的类型。当前载荷已是最后一个时,这个字段为 0。第 3.1 节写的是同一条链的起点:先看 IKE 头里的下一载荷,再看每个载荷自己的下一载荷,直到 0。两个「下一载荷」不是同一个字段。IKE 头 只数头上那 28 字节的按图长度,原文同样没有印出 28。本文不把载荷长度当成那一个总数。
加密载荷是例外。第 3.1 节用大写写明:它必须是包里的最后一个载荷,并且不得再包含另一个加密载荷。第 3.2 节接着用小写 must 说它必须总是最后一个,然后写明头里的下一载荷不填 0,而填它所包含的第一个载荷的类型;被包含的最后一个载荷的下一载荷才填 0。第 3.14 节把理由写成:内容是嵌进去的载荷,第一个的类型没有别的自然位置。
第 1.2 节的初始交换写成 HDR, SAi1, KEi, Ni。把第 3.2 节的链接用到这个顺序上,是两节的对照,不是第 1.2 节里另印的类型号:IKE 头的下一载荷指向 SA,SA 的下一载荷指向 KE,KE 的指向 Ni,Ni 的为 0。SA、KE 和 Nonce 在表里是 33、34 和 40。
临界位管的是当前载荷
一个可独立引用的定义句:临界位占 1 位。发送方希望对方在不认识前一个载荷的下一载荷字段里的类型时跳过当前载荷,就必须把这一位置 0。希望对方在不认识该类型时拒绝整条消息,就必须置 1。接收方认识这个类型时,必须忽略这一位。RFC 7296 定义的载荷类型必须置 0(第 3.2 节)。
第 3.2 节把这个类型写成「前一个载荷的下一载荷字段」。第一个载荷的类型写在 IKE 头里,而头不是载荷。这一节没有另写第一个载荷怎样套用「前一个载荷」。第 2.5 节只说载荷类型认不出。本文不把 IKE 头补成「前一个载荷」。
同一段写明:临界位适用于当前载荷,不适用于第一字节里那个「下一个」类型。不给 RFC 7296 这些类型置 1 的理由是,实现必须认识该文定义的全部类型,因此必须忽略这一位的取值。被跳过的载荷仍要有合法的下一载荷和载荷长度。
第 2.5 节把同一位的处理写成:临界标志置 1 且载荷类型认不出时,必须拒绝这条消息;对含有该载荷的 IKE 请求,应答必须带上通知 UNSUPPORTED_CRITICAL_PAYLOAD,通知数据是那一个八位组的载荷类型。临界标志没有置 1 且类型不受支持时,必须忽略该载荷。IKE 应答消息里的载荷不得把临界标志置 1。这一标志只约束载荷类型,不约束内容。类型认得出、内容却不认识时,临界标志被忽略。原文的例子是 SA 载荷里未知的变换,以及通知载荷里未知的通知消息类型。
第 3.10.1 节的错误类型表里,UNSUPPORTED_CRITICAL_PAYLOAD 的值是 1,并指向第 2.5 节。这张表写明只截止到 RFC 4306 的发表日期,再加上 RFC 7296 新增的两种错误。2026 年 10 月 24 日没有打开 IANA 的登记表,因此不把 1 写成当天的完整核对,只保留表里印出的这一行。
第 2.21.2 节还有一句范围更窄的必须:在 IKE_AUTH 里,含有不受支持的临界载荷的请求,或者整条消息畸形而不是仅仅内容不对,必须整条拒绝,并且只能引出 UNSUPPORTED_CRITICAL_PAYLOAD 或 INVALID_SYNTAX 作为应答。接收方这时不应当去核验与认证有关的载荷。这里的「不应当」对应原文的小写 should。本文不写如何构造这种请求。第 2.21 节其余的错误处理没有读完。
保留的 7 位必须发送为 0,收到必须忽略。第 2.5 节把所有标成 RESERVED 的字段都写成:跑 2.0 的实现必须置 0,也必须忽略其内容。许多载荷含有这样的字段。第 3.2 节接着写,IKEv2 里有些载荷,历史上 IKEv1 里也有,并不对齐到 4 八位组边界。通用载荷头自身按图是 4 字节,并不因此让每种载荷都对齐。
类型表只截止到 RFC 4306
第 3.2 节印出的载荷类型是:
| 下一载荷类型 | 记号 | 值 |
|---|---|---|
| 没有下一载荷 | 0 | |
| 安全关联 | SA | 33 |
| 密钥交换 | KE | 34 |
| 标识,发起方 | IDi | 35 |
| 标识,响应方 | IDr | 36 |
| 证书 | CERT | 37 |
| 证书请求 | CERTREQ | 38 |
| 认证 | AUTH | 39 |
| 现时值 | Ni、Nr | 40 |
| 通知 | N | 41 |
| 删除 | D | 42 |
| 厂商编号 | V | 43 |
| 流量选择符,发起方 | TSi | 44 |
| 流量选择符,响应方 | TSr | 45 |
| 加密且已认证 | SK | 46 |
| 配置 | CP | 47 |
| 可扩展认证 | EAP | 48 |
同一段写明:表中的值只截止到 RFC 4306 的发表日期。此后可能已经增加,或者会在 RFC 7296 发表之后增加。读者应查阅 IANA。括注用小写 should not 写:1 到 32 以后不应当分配,以免和 IKEv1 的编号重叠。本文不把这句升成大写不得。2026 年 10 月 24 日没有打开登记表,因此不把 0 和 33 到 48 写成当天的完整清单。
IKE 分片 用的加密分片载荷不在这张表里。那一篇写类型是 53,并写明图里的 C 位属于通用载荷头,RFC 7383 第 2.5 节没有给它另写一个取值。本文今天没有重读 RFC 7383,因此不把 53 再写成一次新的原文核对,也不判断分片实现把临界位填成 0 还是 1。按第 3.2 节,这一位的含义仍是上面那一条。
安全关联载荷可以嵌着提议、变换和属性。第 3.3 节要求解析时必须检查载荷总长度与内部的长度、计数一致。SA 的载荷长度包括 SA、提议、变换和属性合在一起的内容。提议的长度包括其中全部变换和属性。变换的长度包括其中全部属性。本文不展开这三层各自的头部。
加密载荷在第 3.14 节有自己的长度句。这一节先写明,使用认证加密时,构造与这里描述的不同,并指向另一份文件。下面这句只按这一节已经印出的、非认证加密的那张图来引用:载荷长度包括头、初始化向量、加密的 IKE 载荷、填充、填充长度和完整性校验数据。图里填充是 0 到 255 个八位组。填充长度是填充字段的长度。接收方必须接受任何能得到正确对齐的长度。填充长度这一字段占几个八位组,条目里没有印出。本文不补,也不把这句挪到还没有重读的认证加密构造上。它不是 ESP 尾部那个填充长度。
EAP 载荷的类型是 48。第 3.16 节写,EAP 消息自己的长度必须比外层载荷的载荷长度少 4。这和「通用载荷头按图是 4 字节、EAP 消息紧跟在后面」对得上。原文没有把这个 4 再解释一遍。EAP 方法怎样选择,本文没有往下读。
现象对照
| 现象 | 更可能先看什么 |
|---|---|
| 载荷长度等于后面数据的字节数 | 与第 3.2 节不符。这四字节要算进去 |
| 把 IKE 头的长度当成某一个载荷的长度 | 头上那个字段是整条消息。载荷长度只计当前载荷 |
| 最后一个普通载荷的下一载荷不是 0 | 与「当前已是最后一个则为 0」不符。加密载荷本身是例外 |
| 加密载荷的下一载荷是 0 | 第 3.2 节要求它填所含第一个载荷的类型,不是 0 |
| 应答里临界位为 1 | 与第 2.5 节不符。应答不得把这一位置 1 |
| 类型认得出,临界位却导致整条被拒绝 | 认识类型时必须忽略这一位。未知的变换或通知类型也不靠这一位 |
| 表里没有的类型号 | 第 3.2 节写明表可能不全。本文没有查 IANA |
核对清单
- 载荷长度含这四字节:按图头是 4 字节,原文没有印出。IKE 头的长度是整条消息,见另一篇;
- 两个下一载荷不是同一个字段:IKE 头指向第一个载荷。每个载荷的下一载荷指向再下一个。0 表示后面没有。加密载荷的头不填 0;
- 临界位管当前载荷:置 1 且类型认不出,必须拒绝整条消息。应答不得置 1。认识类型时必须忽略。通知类型表里的值 1 只按 2014 年印出的那一行引用;
- 0 和 33 到 48 不是完整清单:表自己写明只截止到 RFC 4306。1 到 32 的「不应当分配」是小写。分片用的类型不在表里;
- 加密载荷的长度句不自动套到认证加密。EAP 消息的长度必须比外层载荷长度少 4。已验证勘误不改第 3.2 节。六份更新文件的正文没有重读。
2026 年 10 月 24 日的元数据把 RFC 7296 标成 Internet Standard,STD 79,没有把它标成已被取代。更新者是 RFC 7427、7670、8247、8983、9370 和 9827。这六份正文没有重读,因此不判断它们有没有改写第 3.2 节。已验证勘误 6940 改的是通知载荷里「字段必须为空」应指 SPI 字段,6667 把第 3.3 节的 AEC-CBC 改成 AES-CBC。两条都不改通用载荷头。勘误页上没有指向第 3.2 节的条目。Held for Document Update 有 5 条,节号分别是 1.7、2.21.1、3.7、3.10 和 1.1.1,替换文本没有读完。Rejected 的 8407 和 4930 不采用,也没有读成对第 3.2 节的改写。