跳到主要内容

2.6. IKE SA SPIs and Cookies (IKE SA 的 SPI 与 cookie)

头中最初的两个八字节字段称为 "IKE SPI", 用作 IKE 分组开头的连接标识. 每个端点选择两个 SPI 之一, 且必须使它们成为 IKE SA 的唯一标识. SPI 值为零是特殊的: 表示发送方尚不知道远端 SPI 值.

入站 IKE 分组仅根据分组的 SPI 映射到 IKE SA, 而不使用 (例如) 分组的源 IP 地址.

与 ESP 和 AH 中只有接收方 SPI 出现在消息头中不同, IKE 每条消息也发送发送方 SPI. 由于 IKE SA 的原始发起方所选的 SPI 总是先发送, 若某端点打开了多个 IKE SA 并希望用其分配的 SPI 找到对应 SA, 必须查看头中的 Initiator 标志以判定它分配的是前八字节还是后八字节.

在初始 IKE 交换的第一条消息中, 发起方尚不知道响应方 SPI 值, 因此将该字段置零. 当 IKE_SA_INIT 交换因 INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN 或 COOKIE 而未导致创建 IKE SA 时, 响应消息中响应方 SPI 也可能为零. 但是, 若响应方发送非零的响应方 SPI, 发起方不应仅因此理由拒绝响应.

针对 IKE 的两类预期攻击是状态与 CPU 耗尽, 即目标被来自伪造 IP 地址的会话建立请求淹没. 若响应方在确认发起方能够接收其声称来源地址的分组之前, 对 SA 投入最少 CPU 且不提交状态, 则可削弱此类攻击.

当响应方检测到大量半开 IKE SA 时, 应该对 IKE_SA_INIT 请求回复包含 COOKIE 通知的响应. 与此通知关联的数据长度必须在 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 实现可以以在第二次 IKE_SA_INIT 消息到达时无需保存状态即可识别其合法 cookie 的方式实现响应方 cookie 生成. 用于生成 cookie 的确切算法与语法不影响互操作性, 故本文不规定. 以下示例说明端点如何用 cookie 实现有限的 DoS 防护.

一种可行做法是将响应方 cookie 设为:

Cookie = <VersionIDofSecret> | Hash(Ni | IPi | SPIi | <secret>)

其中 <secret> 为仅响应方知晓的随机生成密钥, 定期更换, | 表示拼接. 每当 <secret> 重新生成时应更改 <VersionIDofSecret>. 当 IKE_SA_INIT 第二次到达时可重新计算 cookie 并与消息中的 cookie 比较. 若匹配, 响应方知道该 cookie 自上次更改 <secret> 以来生成, 且 IPi 必须与首次所见源地址相同. 将 SPIi 纳入计算可确保并行建立多个 IKE SA 时各得不同 cookie (假定发起方为 SPIi 选择唯一值). 将 Ni 纳入散列可确保仅看到消息 2 的攻击者无法成功伪造消息 3. 将 SPIi 纳入散列还可防止攻击者从对端取一个 cookie 后, 用许多不同发起方 SPI (及可能不同端口) 发起大量 IKE_SA_INIT, 使响应方误以为 NAT 后有许多主机在同时连接.

若在连接仍处于初始化过程中时为 <secret> 选择了新值, 返回的 IKE_SA_INIT 可能带有非当前 <VersionIDofSecret>. 此时响应方可以发送带新 cookie 的另一响应来拒绝该消息, 也可以短时间保留旧 <secret> 并同时接受由二者计算的 cookie. 响应方在更改 <secret> 后不应无限期接受旧 cookie, 否则会削弱部分 DoS 防护. 响应方应频繁更改 <secret>, 尤其在遭受攻击时.

当一方收到 IKE_SA_INIT 请求中的 cookie 内容与期望值不符时, 必须忽略该 cookie, 并按未包含 cookie 的方式处理消息; 通常意味着发送带新 cookie 的响应. 发起方应限制在放弃前尝试的 cookie 交换次数, 可使用指数退避. 攻击者可伪造对发起方 IKE_SA_INIT 的多个 cookie 响应, 每个伪造 cookie 回复都会导致两个分组被发送: 发起方到响应方的一个分组 (响应方会拒绝那些 cookie), 以及响应方到发起方且含正确 cookie 的一个响应.

术语说明: "cookie" 一词源自 Karn 与 Simpson 在 Photuris ([PHOTURIS]) 中的用法, Photuris 是 IPsec 密钥管理的早期提案, 该称呼沿用至今. Internet Security Association and Key Management Protocol (ISAKMP, 互联网安全关联与密钥管理协议) [ISAKMP] 的固定消息头包含两个八字节字段称为 "cookie", IKEv1 与 IKEv2 均使用该语法, 不过在 IKEv2 中它们称为 "IKE SPI", 且在 Notify 载荷中有单独字段存放 cookie.

发起方重试 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

实现应该支持这种更短的交换, 但若其他实现不支持, 也绝对不能失败.