IPSec 原理与报文 — AH/ESP 头部与 IKEv2 协商

AH/ESP 头部字段、传输与隧道模式封装、IKEv2 交换时序、SA/SPD/SAD 协作 / 网络层安全 / IP 协议号 50/51 / RFC 4301

先建立直觉

两家公司要互通内部办公网,又不想让中间经过的运营商看见任何内容。于是他们在各自门口放了一台"保安":所有出门的包裹,保安先查一张清单——这个包裹该不该保护?该保护的就装进保险箱、封好、送出去;对面的保安收到后拆箱、验封条,确认没问题再送进内网。

关键在于:这套动作发生在"寄件人"完全不知情的地方。员工照常寄件,业务系统一行代码都不用改,保护是在更底层由网络本身完成的。IPSec 就是这台保安,它的规矩、钥匙和封条样式,都由两家公司事先谈好并存在几张表里。

它解决什么问题

如果没有 IPSec,一个 IP 包从出门到到达对端,中间任何一跳都可以:读走里面的内容、悄悄改掉几个字节、把老包录下来过一会儿再重放一遍、甚至伪造一个包冒充你发的。

IPSec 用几件事把这些漏洞堵上:

  • 该不该保护,得有统一说法。所以有一张策略表(SPD),按源/目的 IP、协议、端口这些"选择符"决定:丢弃、明文放行,还是加密保护。
  • 用什么钥匙保护,得先谈好。所以有密钥协商(IKE)和一张已建会话表(SAD),记着每条通道的密钥、算法、序列号、生存期。
  • 收到的包得能确认是真的、是新的。所以每个包带序列号做抗重放检查,带 ICV 做完整性校验,两关都过才解密。
  • 解出来的内层包也不能乱来。所以解密后还要反查一次策略,确认对端没有借一条合法通道往你网里塞别的网段流量。

工作流程(简化版)

一句话概括:每个进出的 IP 包都要先查 SPD 决定"怎么办",命中保护策略后再查 SAD 取参数执行加解密。

发出去的时候,大致四步:

  1. 查规矩:包一到 IPSec 处理点,先按选择符去 SPD 里问一句"这个包该怎么办"。
  2. 拿钥匙:如果答案是"要保护",就去 SAD 找对应的出方向通道;找不到就先让 IKE 去谈一条出来。
  3. 打包封箱:按通道约定的模式和算法把包封好,序列号加 1。
  4. 发出去

收进来的时候,也是几步,但顺序反过来且多一道复核:

  1. 认领:按包上的 SPI 去 SAD 找到是哪条通道。
  2. 验新鲜:序列号有没有落在抗重放窗口内、是不是重复的。
  3. 验完整 + 解密:ICV 对不上直接丢,对得上就解密剥壳。
  4. 复核:再查一次 SPD,确认解出来的内层包确实在这条通道被允许的范围内,才交给上层。

展开细节(原理原文)

出方向(Outbound)处理

  1. IP 包到达 IPSec 处理点,用选择符(Selector:源/目的 IP、协议号、源/目的端口)查询 SPD
  2. SPD 返回三种动作之一:DISCARD(丢弃)、BYPASS(明文放行)、PROTECT(IPSec 保护)。
  3. 若为 PROTECT,查 SAD 找对应的出方向 SA;找不到则触发 IKE 协商建立新 SA(此过程中数据包通常被暂存或丢弃)。
  4. 按 SA 中的模式(传输/隧道)、协议(AH/ESP)、算法与密钥封装数据包,序列号加 1。
  5. 发送。

入方向(Inbound)处理

  1. 收到 IP 包,识别协议号为 50/51(或 UDP 4500 的 NAT-T 封装)。
  2. <SPI, 目的 IP, 协议>SAD 定位 SA;查不到则丢弃。
  3. 抗重放检查:序列号是否落在滑动窗口内且未被使用过。
  4. 校验 ICV(完整性),失败则丢弃。
  5. 解密,剥掉 IPSec 头。
  6. 反查 SPD:确认解出来的内层包确实符合该 SA 允许的选择符范围(防止对端用一个合法 SA 注入其他网段流量),通过后交上层。

报文 / 头部长什么样

ESP 头部(Encapsulating Security Payload,封装安全载荷,RFC 4303)

看这张表前先记住:ESP 是"前有头、后有尾"的三明治结构——前面的头告诉接收方"用哪把钥匙、这是第几个包",中间是加密后的内容,后面的尾巴放填充和校验值。

ESP 是实际生产中的主力(提供加密),格式为"前有头、后有尾":

字段长度含义
SPI(Security Parameters Index,安全参数索引)32 bit安全参数索引,接收方据此定位使用哪个 SA。1~255 保留,0 表示无 SA
Sequence Number(序列号)32 bit单调递增序列号,从 1 开始,用于抗重放;配合 ESN 扩展可扩到 64 bit
Payload Data(载荷数据)可变加密后的载荷;若算法需要 IV,IV 置于此字段开头(明文传输)
Padding(填充)0–255 字节填充至分组算法块长的整数倍,同时可用于 TFC 掩盖真实长度
Pad Length(填充长度)8 bit填充字节数
Next Header(下一头部类型)8 bit载荷类型:传输模式下为 6(TCP)/17(UDP);隧道模式下为 4(IPv4)/41(IPv6)
ICV(Integrity Check Value,完整性校验值)可变(通常 12/16 字节)完整性校验值,覆盖 ESP 头 + 载荷 + ESP 尾,不覆盖外层 IP 头(这正是 ESP 能穿 NAT 的原因)

AH 头部(Authentication Header,认证头,RFC 4302)

看这张表前先记住:AH 只贴封条、不装保险箱——它证明"这个包没被改过、确实是你发的",但内容仍然是明文;而且它的封条把外面的地址也一起封住了,所以一遇到 NAT 就破功。

AH 只认证不加密,实际部署已很少见:

字段长度含义
Next Header(下一头部类型)8 bit被保护载荷的协议类型
Payload Len(载荷长度)8 bitAH 头长度,以 32 bit 为单位再减 2
Reserved(保留字段)16 bit保留,置 0
SPI(安全参数索引)32 bit安全参数索引
Sequence Number(序列号)32 bit抗重放序列号
ICV(完整性校验值)可变完整性校验值,覆盖整个 IP 包(含 IP 头中的不可变字段)

AH 的 ICV 覆盖 IP 头中的源/目的地址等"不可变字段",因此 AH 无法穿越 NAT。可变字段(TTL、TOS、Header Checksum、Fragment Offset)在计算时按 0 处理。

两种模式的封装对比

看这张图前先记住:从上往下,包一层比一层"胖"。传输模式只在原包中间插了 ESP 头尾;隧道模式把整个原包塞进去再套一个新 IP 头;NAT-T 又在最外面加一层 UDP。每多一层,可用的载荷空间就少一点——这就是 MTU 问题的根源。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
【原始 IPv4 包】
+---------+---------+--------+
| IP 头 | TCP 头 | 数据 |
+---------+---------+--------+

【ESP 传输模式】 —— 保留原 IP 头,只加密载荷
+---------+--------+---------+--------+---------+-----+
| 原IP头 | ESP头 | TCP头 | 数据 | ESP尾 | ICV |
+---------+--------+<------ 加密范围 ------>+
          +<-------- 完整性校验范围 --------------->+

【ESP 隧道模式】 —— 整个原包被加密,外套新 IP 头
+---------+--------+---------+--------+--------+---------+-----+
| 新IP头 | ESP头 | 原IP头 | TCP头 | 数据 | ESP尾 | ICV |
+---------+--------+<--------- 加密范围 ---------->+
          +<---------- 完整性校验范围 ------------------->+

【NAT-T 封装】 —— 再套一层 UDP 4500
+---------+-----------+--------+---------------+--------+-----+
| 新IP头 | UDP(4500) | ESP头 | 原IP头+TCP+数据| ESP尾 | ICV |
+---------+-----------+--------+---------------+--------+-----+

关键差别一句话:传输模式给包"换内衣",隧道模式给包"套外套"。隧道模式因为多了 20 字节新 IP 头,MTU 开销更大(ESP 隧道模式总开销约 50–73 字节)。

IKEv2 头部(RFC 7296)

看这张表前先记住:这是"谈判信件"的信封,不是数据包的头。IKE 只负责在 UDP 500/4500 上谈条件、换钥匙,谈完之后真正跑业务数据的是 ESP。Exchange Type 是最值得记的一栏,抓包排错时靠它判断谈到第几步。

字段长度含义
IKE SA Initiator’s SPI(发起方 SPI)64 bit发起方 SPI
IKE SA Responder’s SPI(响应方 SPI)64 bit响应方 SPI(IKE_SA_INIT 请求中为 0)
Next Payload(下一载荷类型)8 bit后续第一个载荷类型(SA=33, KE=34, Nonce=40, AUTH=39, TSi=44, TSr=45, SK=46…)
Version(版本号)8 bit主版本 2 + 次版本 0
Exchange Type(交换类型)8 bit34=IKE_SA_INIT,35=IKE_AUTH,36=CREATE_CHILD_SA,37=INFORMATIONAL
Flags(标志位)8 bitI(发起者)、V(版本)、R(响应)
Message ID(消息序号)32 bit消息序号,用于匹配请求/响应与防重放
Length(总长度)32 bit整个 IKE 消息总长

交互时序

IKEv2 建立隧道(标准 2 次往返)

一句话看懂这张图:前两条消息明文谈算法、换 DH 公钥(把信道本身加密起来),后两条消息在加密信道里验身份、定子网,隧道就通了;再往后的 CREATE_CHILD_SA 和 INFORMATIONAL 都属于日常维护(换钥匙、探活、拆隧道)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
sequenceDiagram
    participant I as 发起方 Initiator<br/>(分支网关 A)
    participant R as 响应方 Responder<br/>(总部网关 B)

    Note over I,R: ── 阶段 1:IKE_SA_INIT(明文,协商 IKE SA)──
    I->>R: HDR, SAi1(算法提议), KEi(DH 公钥), Ni(随机数)
    R->>I: HDR, SAr1(选定算法), KEr(DH 公钥), Nr,<br/>[CERTREQ]
    Note over I,R: 双方各自用 DH 算出 SKEYSEED<br/>派生 SK_d / SK_ai,ar / SK_ei,er / SK_pi,pr

    Note over I,R: ── 阶段 2:IKE_AUTH(已加密,认证 + 建首个 Child SA)──
    I->>R: HDR, SK{ IDi, [CERT], [CERTREQ], AUTH,<br/>SAi2, TSi, TSr }
    Note right of R: 校验 AUTH(预共享密钥/证书签名)<br/>核对流量选择符 TS 与本地 SPD
    R->>I: HDR, SK{ IDr, [CERT], AUTH,<br/>SAr2, TSi, TSr }
    Note over I,R: ✅ IKE SA + 第一对 Child SA(ESP) 建立完成

    Note over I,R: ── 数据平面:ESP 加密传输 ──
    I->>R: IP(proto=50) ESP{ 加密的内网 IP 包 }
    R->>I: IP(proto=50) ESP{ 加密的内网 IP 包 }

    Note over I,R: ── 维护:按需增建 / 重协商 / 探活 ──
    I->>R: CREATE_CHILD_SA(新增 SA 或 rekey)
    R->>I: CREATE_CHILD_SA 响应
    I->>R: INFORMATIONAL(空消息 = DPD 探活)
    R->>I: INFORMATIONAL 响应
    I->>R: INFORMATIONAL{ DELETE }(拆除隧道)

对比 IKEv1:IKEv1 需要主模式 6 条消息(或野蛮模式 3 条)+ 快速模式 3 条,共 9 条;IKEv2 只需 4 条消息即可完成认证并建立第一对数据 SA,且原生支持 NAT-T、DPD、EAP 与 MOBIKE(地址漫游)。

关键机制 / 变体

1. 三个数据库的分工

这是干什么的:把"该不该保护"“用什么参数保护"“谁有资格来跟我建隧道"这三个问题拆成三张独立的表,各管一摊。

数据库全称作用类比
SPDSecurity Policy Database按选择符规定对流量执行 DISCARD / BYPASS / PROTECT“防火墙规则表”
SADSecurity Association Database存放每个 SA 的 SPI、密钥、算法、序列号、生存期、模式、隧道端点“已建立的加密会话表”
PADPeer Authorization Database定义对端身份(ID 类型/值)与允许的认证方式,桥接 IKE 与 SPD“谁有资格跟我建隧道”

2. SA 的单向性与 SPI

这是干什么的:解释为什么你 ip xfrm state 一敲总是看到成双成对的条目,以及那个 SPI 到底是谁说了算。

一条 SA 只保护一个方向的流量。网关 A ↔ B 的双向通信至少需要 2 个 IPSec SA(A→B 与 B→A),SPI 由接收方分配并告知对端。ip xfrm state 中看到成对出现的条目正是这个原因。

3. 抗重放滑动窗口

这是干什么的:拦住"把旧包录下来重发一遍"的攻击,同时又要容忍网络本身的正常乱序——窗口大小就是这两者之间的平衡点。

接收方维护一个默认 64 位(可配至 128/1024)的位图窗口:

  • 序列号 大于窗口右边界 → 接受,窗口右移。
  • 序列号 落在窗口内且对应位为 0 → 接受,置位为 1。
  • 序列号 落在窗口内但已置位,或 小于窗口左边界 → 判定为重放,丢弃。

序列号回绕(32 bit 用尽)时必须重建 SA,除非启用 ESN(Extended Sequence Number) 扩展到 64 bit。QoS 导致的乱序若超出窗口宽度会被误判为重放,是高带宽场景丢包的常见暗坑。

4. NAT 穿越(NAT-T,RFC 3947 / 3948)

这是干什么的:ESP 不是 TCP 也不是 UDP,NAT 设备没有端口可改、常常直接丢弃;NAT-T 就是给 ESP 套一层 UDP 外衣,让它在 NAT 眼里变成一个普通 UDP 流。

  1. IKE_SA_INIT 中双方交换 NAT_DETECTION_SOURCE_IP / NAT_DETECTION_DESTINATION_IP 载荷(内含 SPI+IP+Port 的哈希)。
  2. 若收到的哈希与本地计算不符,说明路径上存在 NAT。
  3. 双方把 IKE 通信从 UDP 500 切换到 UDP 4500,并将后续 ESP 包封装为 UDP(4500) + ESP(非 ESP 的 IKE 消息前加 4 字节全 0 的 Non-ESP Marker 以区分)。
  4. 位于 NAT 后的一方定期发送 NAT-Keepalive(1 字节 0xFF 的 UDP 包,默认 20 秒)维持映射表项。

5. 完美前向保密(PFS)

这是干什么的:让每次换钥匙都从零开始重新算,而不是从老钥匙推导,代价是多一次运算,收益是一把钥匙泄露不牵连其他。

Child SA 的 rekey 默认可以直接从 IKE SA 的 SK_d 派生新密钥(快但无 PFS)。启用 PFS 后,每次 CREATE_CHILD_SA 都重新做一次 DH 交换,代价是 CPU 开销,收益是单个密钥泄露不影响其他 SA。两端 PFS 组(DH Group)必须一致,否则 rekey 时隧道会断——这是"隧道跑一段时间就掉"的高频原因。

6. 生存期(Lifetime)与 Rekey

这是干什么的:规定一把钥匙最多用多久、最多加密多少数据,到点就换,限制单把钥匙一旦泄露的影响面。

SA 有两个维度的生存期:时间(如 IKE SA 24h、Child SA 1h)与流量(如 4 GB)。任一先到即触发 rekey。两端配置不必完全相同(取较小值生效),但差距过大容易出现"一端已删、一端还在发"的黑洞期,建议设置 rekey 提前量(margintime + 随机抖动)。

常见误区

  • 误区一:一条隧道就是一个 SA。 SA 是单向的,A↔B 的双向通信至少需要 2 个 IPSec SA。看到 ip xfrm state 里成对出现的条目不要以为是配重了。
  • 误区二:SPI 是发送方定的。 恰恰相反,SPI 由接收方分配并告知对端——“你发给我的包请打上这个号”,接收方才好按号查表。
  • 误区三:ESP 的 ICV 保护了整个包。 ESP 的 ICV 覆盖 ESP 头 + 载荷 + ESP 尾,不覆盖外层 IP 头;正因为不覆盖,NAT 改地址才不会破坏校验,ESP 才能配合 NAT-T 穿越 NAT。而 AH 的 ICV 覆盖整个 IP 包(含 IP 头不可变字段),所以 AH 穿不了 NAT。
  • 误区四:抗重放窗口只会挡住攻击者。 网络本身的乱序(多路径、QoS)如果超出窗口宽度,正常包也会被误判为重放丢掉,表现为高带宽场景莫名丢包。

速记口诀

SA 单向要成对,SPI 收方来指派;SPD 管"要不要”,SAD 管"怎么办”。

传输模式换内衣,隧道模式套外套;ESP 五十 AH 五十一,IKE 五百 NAT-T 四千五。

AH 封住 IP 头,一见 NAT 就摇头;ESP 不管外层皮,套上 UDP 走天下。

知识框架

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
mindmap
  root((IPSec))
    体系结构 RFC4301
      SPD 安全策略库
        DISCARD
        BYPASS
        PROTECT
      SAD 安全关联库
      PAD 对端授权库
    安全协议
      AH RFC4302 协议号51
        仅认证不加密
        覆盖IP头 不可穿NAT
      ESP RFC4303 协议号50
        加密加认证
        不覆盖外层IP头
        支持TFC填充
    封装模式
      传输模式 主机到主机
      隧道模式 网关到网关
    密钥管理 IKEv2 RFC7296
      IKE_SA_INIT 协商与DH
      IKE_AUTH 认证与首个ChildSA
      CREATE_CHILD_SA 增建与rekey
      INFORMATIONAL DPD与删除
      认证方式 PSK 证书 EAP
    核心机制
      SA单向性 SPI标识
      抗重放滑动窗口 ESN
      NAT-T UDP4500
      PFS 每次重做DH
      生存期与Rekey
      DPD 死对等体检测
      MOBIKE 地址漫游
    典型算法
      加密 AES-GCM AES-CBC ChaCha20
      完整性 HMAC-SHA256 AES-XCBC
      DH组 14/19/20/21 及PQ混合
    应用形态
      站点到站点VPN
      远程接入VPN
      GRE over IPSec
      L2TP over IPSec
      云VPC互联