IKE 头出现在每条 IKE 消息的开头。两个 SPI 各占 8 字节。发起方 SPI 不得为 0。响应方 SPI 在初始交换的第一条消息里必须为 0。主版本是 2,次版本是 0。规范是 2014 年 10 月的 RFC 7296。端口 4500 上的四个 0 不算进这个头的长度。
两个 SPI 在长度之前
一个可独立引用的定义句:发起方 SPI 是 8 个八位组,由发起方选取,用来标识一条 IKE 安全关联,不得为 0。响应方 SPI 也是 8 个八位组,由响应方选取;在 IKE 初始交换的第一条消息里必须为 0,包括这条消息带 cookie 的重发(RFC 7296 第 3.1 节)。
多八位组的整数字段按大端序排列,也就是高字节在前。按图数,头是 7 行 32 位,共 28 个八位组。原文没有印出 28。长度字段是 4 字节无符号整数,计的是整条消息(头加上载荷)的八位组数,因此含这 28 字节,不含别的前缀。
| 字段 | 宽度 | 第 3.1 节写明的取值 |
|---|---|---|
| 发起方 SPI | 8 字节 | 不得为 0。第 1.5 节有一条例外 |
| 响应方 SPI | 8 字节 | 初始交换的第一条消息必须为 0 |
| 下一个载荷 | 1 字节 | 紧跟在头后面的载荷类型。0 表示后面没有载荷 |
| 主版本 / 次版本 | 各 4 位 | 按本文实现时必须是 2 和 0 |
| 交换类型 | 1 字节 | 表中印有 34 到 37。表本身写明可能不全 |
| 标志 | 1 字节 | 见下一节。原文没有印出位号 |
| 消息编号 | 4 字节 | 匹配请求、应答和重传 |
| 长度 | 4 字节 | 头加载荷的总八位组数 |
第 1.2 节把建立 IKE 安全关联的前两次交换叫做 IKE_SA_INIT 和 IKE_AUTH。第 3.1 节说的「初始交换的第一条消息」,对照起来落在 IKE_SA_INIT 的请求上。这是两节的对照,不是原文里的另一条定义。响应方的应答已经不是这第一条,因此不受「必须为 0」那一句约束。响应方 SPI 同时用来标识这一实例,所以同一套 IKE 可以复用到多个对端,包括与同一个对端的多个会话。
第 1.5 节是发起方 SPI 不得为 0 的例外:收到认不出 SPI 的 ESP 或认证头,又没有合适的 IKE 安全关联时,可以发出没有密码保护的通知。这时用 0 或用随机值都可以。发起方标志置 1,应答标志置 0。接收方不得回应,原文写明否则可能造成消息循环。这里接着用小写 should:接收方只应把它当成提示,因为它很容易伪造。本文不写如何构造它。另外两种情况(认不出的 IKE SPI,或主版本更高)也没有密码保护,但要沿用请求里的两个 SPI、消息编号和交换类型,并把应答标志置 1。
头后面可以有一个或多个载荷。下一个载荷为 0 表示不再跟随载荷。若出现加密载荷,它必须是包里的最后一个,并且不得再包含另一个加密载荷。解密之后,里面的内容再当作载荷来解析。分片用的是另一份载荷,片号不在这个 IKE 头里,见 IKE 分片。各片仍共用这里的消息编号。
标志从高位读,交换类型表不完整
一个可独立引用的定义句:标志占 1 字节。图从高位到低位是 X、X、R、V、I、X、X、X。标成 X 的位发送时必须清 0,接收时必须忽略。R 在请求中必须清 0,在应答中必须置 1。按本文实现时,V 发送必须清 0,接收必须忽略(RFC 7296 第 3.1 节)。
原文没有给这些位编号。从这张图的左端数,R 在第三格,这只是按图数出来的,不是原文里的位号。
| 图中的字母 | 谁置 1 | 第 3.1 节的约束 |
|---|---|---|
| R | 应答 | 不得对一条已经标成应答的消息再生成应答。例外指向第 2.21.2 节 |
| V | 表示发送方能说比主版本字段更高的主版本 | IKEv2 实现发送时必须清 0,收到时必须忽略 |
| I | 当前这条 IKE 安全关联的原始发起方 | 原始响应方必须清 0。最近一次重协商 IKE 安全关联之后,这一位改记新的原始发起方 |
I 位用来让接收方判断,两个 SPI 里的哪 8 字节是自己生成的。第 2.21.2 节的例外本文没有读,因此不描述那一种情况下应答之后还会发生什么。
交换类型约束这一次交换里可以出现哪些载荷。第 3.1 节印出的表是:
| 交换类型 | 值 |
|---|---|
| IKE_SA_INIT | 34 |
| IKE_AUTH | 35 |
| CREATE_CHILD_SA | 36 |
| INFORMATIONAL | 37 |
同一段写明:表中的值只截止到 RFC 4306 的发表日期。此后可能已经增加,或者会在 RFC 7296 发表之后增加。读者应查阅 IANA。2026 年 10 月 23 日没有打开那张登记表,因此不把 34 到 37 写成当天的完整清单。更新者包括 RFC 9370。Libreswan 一文写过 IKE_INTERMEDIATE 这个名字。本文没有重读 RFC 9370,不给它编一个交换类型号,也不把它补进上表。
主版本大于 2 时,必须拒绝或忽略,并按第 2.5 节发送 INVALID_MAJOR_VERSION。原文是「拒绝或忽略」,不是只剩拒绝。次版本收到之后必须忽略,不管对方填了多少。对主版本 1 如何处理,第 3.1 节没有另写一句。本文不补。旧的 IKE 和 ISAKMP 实现必须把主版本设为 1,那一句约束的是那些实现自己发出的头。
消息编号可以在四个报文里相同
一个可独立引用的定义句:消息编号是 32 位。IKE_SA_INIT 的消息是 0,包括因 COOKIE 或 INVALID_KE_PAYLOAD 而重试的那些消息。第一对 IKE_AUTH 的编号是 1。若使用 EAP,下一对是 2。重传必须使用原来的消息编号(RFC 7296 第 2.2 节、第 3.1 节)。
每一端保存两个「当前」编号:自己下一次要发出的请求用哪一个,以及预期对端下一次请求用哪一个。应答总是带与对应请求相同的编号。因此初始交换之后,同一个整数 n 可以出现在四条消息里:原始发起方的第 n 个请求、对应的应答、原始响应方的第 n 个请求、对应的应答。I 和 R 两个标志用来区分这四条。两边发出的请求数量可以差很多,编号因此可以差很多。编号放不下 32 位时,这条 IKE 安全关联必须关闭或重协商。重协商之后,新的 IKE 安全关联上编号回到 0。
消息编号有密码保护,并用来防止消息重放。它不是 ESP 或认证头上的那个序列号。两个计数器各管各的,见 重放保护。
在初始交换完成之前,窗口大小一直是 1。SET_WINDOW_SIZE 通知的数据必须是 4 个八位组,大端序,表示发送方承诺保留多少条消息的状态。除非收到对端的这条通知,否则一端必须等每条消息的应答之后,再发下一条。本文没有把第 2.3 节余下的吞吐句子读完,因此不引用一个具体的窗口上限。
四个 0 不算进这个长度
IKE 使用 UDP 端口 500 和/或 4500,每个 UDP 数据报里一条 IKE 消息。端口 500 上,消息紧跟 UDP 头。端口 4500 上,消息前面有四个 0。这四个 0 不是 IKE 消息的一部分,也不计入 IKE 定义的任何长度或校验和。长度字段因此不含它们。四个 0 怎样和 ESP 的 SPI 分开,见 非 ESP 标记。看见长度是 28,只说明头本身,不说明 UDP 载荷里还有没有这四个 0。
IP 头和 UDP 头里的信息基本被忽略,但返回包要使用对调后的 IP 地址和 UDP 端口。本文不把这句写成「地址可以任意更换仍能通过校验」。没有密码保护的通知,第 1.5 节已经把它限制成提示。
IKEv2 与 WireGuard 对比的是握手和数据平面各自由谁承担。本文只数 IKE 头上的字段,不比较两种协议哪一种更快。通用载荷头从第 3.2 节开始,每种载荷另有下一载荷和自己的长度。本文不展开那 4 字节。
文件头把它标成 Internet Standard,STD 79。2026 年 10 月 23 日的勘误页把更新者列为 RFC 7427、7670、8247、8983、9370 和 9827。已验证的 6940 改的是通知载荷里「字段必须为空」应指 SPI 字段,6667 把第 3.3 节的 AEC-CBC 改成 AES-CBC。两条都不改第 3.1 节的头。勘误页标着 Verified (2)。Held for Document Update 有 5 条,本文没有逐条读完。上述更新文件的正文也没有重读,因此不判断它们有没有改写 SPI、标志或长度。
现象对照
| 现象 | 更可能先看什么 |
|---|---|
| 发起方 SPI 为 0 | 与第 3.1 节不符,除非是第 1.5 节那种没有密码保护的通知 |
| IKE_SA_INIT 请求里响应方 SPI 不是 0 | 与「第一条消息必须为 0」不符。带 cookie 的重发仍算这一条 |
| 主版本是 2,次版本不是 0 | 发送方必须把次版本设为 0。接收方则必须忽略收到的次版本 |
| 同一消息编号出现四次 | 可以由 I 和 R 分成四条。重传必须仍用原编号 |
| 端口 4500 上长度不含最前面的四个 0 | 符合第 3.1 节。那四个 0 不是 IKE 头 |
| 表里没有的交换类型 | 第 3.1 节写明表可能不全。本文没有查 IANA,不给表外的号码起名字 |
核对清单
- 两个 SPI 各 8 字节:发起方不得为 0,第 1.5 节除外。响应方只在初始交换的第一条消息里必须为 0。按图头长 28 字节,原文没有印出;
- 主版本 2、次版本 0:大于 2 必须拒绝或忽略。次版本收到后必须忽略。主版本 1 这一节没有另写;
- 标志不要自己编号:图是 X X R V I X X X。R 区分请求和应答。I 标记原始发起方,重协商之后会变;
- 34 到 37 不是完整清单:表自己写明只截止到 RFC 4306。消息编号 0 是 IKE_SA_INIT,第一对 IKE_AUTH 是 1;
- 4500 上的四个 0 不进长度。已验证勘误不改这个头。六份更新文件和 Held 的 5 条没有读完。表以外的号码没有对上 IANA 的名字。