2.6. IKE SA 的 SPI 和 Cookie
2.6. IKE SA 的 SPI 和 Cookie
头部的头两个八字节字段称为 "IKE SPIs", 在 IKE 数据包的开头用作连接标识符. 每个端点选择两个 SPI 中的一个, 并且必须选择它们以作为 IKE SA 的唯一标识符. SPI 值为零是一种特殊情况: 它表示发送方尚不知道对端的 SPI 值.
传入的 IKE 数据包仅使用数据包的 SPI 映射到某个 IKE SA, 而不使用 (例如) 数据包的源 IP 地址.
与 ESP 和 AH 仅在消息头部出现接收方的 SPI 不同, 在 IKE 中发送方的 SPI 也在每个消息中被发送. 由于 IKE SA 的原始发起方所选择的 SPI 总是首先被发送, 一个打开了多个 IKE SA 的端点若想用它所分配的 SPI 找到合适的 IKE SA, 必须查看头部中的 Initiator (发起方) 标志, 以确定它分配的是前八个还是后八个八字节.
在初始 IKE 交换的第一条消息中, 发起方不知道响应方的 SPI 值, 因此将该字段设为零. 当 IKE_SA_INIT 交换由于 INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN 或 COOKIE (见第 2.6 节) 而未能创建 IKE SA 时, 响应方的 SPI 在响应消息中也将为零. 然而, 如果响应方发送了一个非零的响应方 SPI, 发起方不应仅以此为由拒绝该响应.
针对 IKE 的两类预期攻击是状态和 CPU 耗尽, 即目标被来自伪造 IP 地址的会话发起请求所淹没. 如果响应方在知道发起方确实能在它所声称的地址上接收数据包之前, 使用最少的 CPU 并且不为 SA 提交任何状态, 则这些攻击的效果会降低.
当响应方检测到大量半开 (half-open) 的 IKE SA 时, 它应当用包含 COOKIE 通知的响应来回复 IKE_SA_INIT 请求. 与此通知相关联的数据长度必须介于 1 到 64 个八字节之间 (含边界), 其生成方式在本节后面描述. 如果 IKE_SA_INIT 响应包含 COOKIE 通知, 发起方必须重试 IKE_SA_INIT 请求, 并将包含所收到数据的 COOKIE 通知作为第一个载荷包含在内, 而其他所有载荷保持不变. 初始交换将如下进行:
Initiator Responder
HDR(A,0), SAi1, KEi, Ni --> <-- HDR(A,0), N(COOKIE) HDR(A,0), N(COOKIE), SAi1, KEi, Ni --> <-- HDR(A,B), SAr1, KEr, Nr, [CERTREQ] HDR(A,B), SK {IDi, [CERT,] [CERTREQ,] [IDr,] AUTH, SAi2, TSi, TSr} --> <-- HDR(A,B), SK {IDr, [CERT,] AUTH, SAr2, TSi, TSr}
前两条消息不影响发起方或响应方的任何状态, 除了传递 cookie 之外. 具体而言, 前四条消息中的消息序列号都将为零, 而最后两条消息中的消息序列号将为一. 'A' 是发起方分配的 SPI, 而 'B' 是响应方分配的 SPI.
IKE 实现可以以这样一种方式实现其响应方 cookie 生成: 当第二条 IKE_SA_INIT 消息到达时, 无需任何已保存的状态即可识别其有效的 cookie. 用于生成 cookie 的确切算法和语法不影响互操作性, 因此在此不作规定. 以下是一个端点如何使用 cookie 来实现有限的 DoS 防护的示例.
一个好的做法是将响应方 cookie 设置为:
Cookie =
其中
如果在有连接正在初始化过程中选择了一个新的
当一方收到包含 cookie 的 IKE_SA_INIT 请求, 而该 cookie 的内容与期望值不符时, 该方必须忽略该 cookie, 并像未包含任何 cookie 那样处理消息; 通常这意味着发送一个包含新 cookie 的响应. 发起方应当限制在放弃之前尝试的 cookie 交换次数, 可能使用指数退避. 攻击者可以伪造对发起方 IKE_SA_INIT 消息的多个 cookie 响应, 而每一个伪造的 cookie 回复都会导致发送两个数据包: 一个是从发起方到响应方的数据包 (响应方将拒绝那些 cookie), 以及一个从响应方到发起方并包含正确 cookie 的响应.
关于术语的一点说明: "cookies" 一词起源于 Karn 和 Simpson 在 Photuris 中的工作 [PHOTURIS], Photuris 是一个早期的 IPsec 密钥管理提案, 并一直沿用至今. Internet 安全关联和密钥管理协议 (ISAKMP) [ISAKMP] 的固定消息头部包含两个称为 "cookies" 的八字节字段, 该语法被 IKEv1 和 IKEv2 所使用, 尽管在 IKEv2 中它们被称为 "IKE SPI", 并且在 Notify 载荷中有一个新的独立字段来保存 cookie.
2.6.1. COOKIE 与 INVALID_KE_PAYLOAD 的交互
发起方可能不得不重试 IKE_SA_INIT 交换有两个常见原因: 响应方请求一个 cookie, 或者想要一个不同于 KEi 载荷中所包含的 Diffie-Hellman 组. 如果发起方从响应方收到一个 cookie, 发起方需要决定是仅在下次重试 IKE_SA_INIT 请求时包含该 cookie, 还是在所有后续重试中也包含它.
如果发起方仅在下次重试时包含 cookie, 在某些情况下可能需要额外的一次往返. 如果发起方在所有重试中都包含 cookie, 但响应方不支持这种方式, 也需要额外的一次往返. 例如, 如果响应方将 KEi 载荷纳入 cookie 计算, 它将通过发送一个新 cookie 来拒绝该请求.
如果两端都支持在所有重试中包含 cookie, 则可以发生略短一些的交换.
Initiator Responder
HDR(A,0), SAi1, KEi, Ni --> <-- HDR(A,0), N(COOKIE) HDR(A,0), N(COOKIE), SAi1, KEi, Ni --> <-- HDR(A,0), N(INVALID_KE_PAYLOAD) HDR(A,0), N(COOKIE), SAi1, KEi', Ni --> <-- HDR(A,B), SAr1, KEr, Nr
实现应当支持这种较短的交换, 但如果其他实现不支持这种较短的交换, 则不得失败.