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 取参数执行加解密。
发出去的时候,大致四步:
- 查规矩:包一到 IPSec 处理点,先按选择符去 SPD 里问一句"这个包该怎么办"。
- 拿钥匙:如果答案是"要保护",就去 SAD 找对应的出方向通道;找不到就先让 IKE 去谈一条出来。
- 打包封箱:按通道约定的模式和算法把包封好,序列号加 1。
- 发出去。
收进来的时候,也是几步,但顺序反过来且多一道复核:
- 认领:按包上的 SPI 去 SAD 找到是哪条通道。
- 验新鲜:序列号有没有落在抗重放窗口内、是不是重复的。
- 验完整 + 解密:ICV 对不上直接丢,对得上就解密剥壳。
- 复核:再查一次 SPD,确认解出来的内层包确实在这条通道被允许的范围内,才交给上层。
展开细节(原理原文)
出方向(Outbound)处理
- IP 包到达 IPSec 处理点,用选择符(Selector:源/目的 IP、协议号、源/目的端口)查询 SPD。
- SPD 返回三种动作之一:
DISCARD(丢弃)、BYPASS(明文放行)、PROTECT(IPSec 保护)。 - 若为
PROTECT,查 SAD 找对应的出方向 SA;找不到则触发 IKE 协商建立新 SA(此过程中数据包通常被暂存或丢弃)。 - 按 SA 中的模式(传输/隧道)、协议(AH/ESP)、算法与密钥封装数据包,序列号加 1。
- 发送。
入方向(Inbound)处理
- 收到 IP 包,识别协议号为 50/51(或 UDP 4500 的 NAT-T 封装)。
- 用
<SPI, 目的 IP, 协议>查 SAD 定位 SA;查不到则丢弃。 - 抗重放检查:序列号是否落在滑动窗口内且未被使用过。
- 校验 ICV(完整性),失败则丢弃。
- 解密,剥掉 IPSec 头。
- 反查 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 bit | AH 头长度,以 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 问题的根源。
| |
关键差别一句话:传输模式给包"换内衣",隧道模式给包"套外套"。隧道模式因为多了 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 bit | 34=IKE_SA_INIT,35=IKE_AUTH,36=CREATE_CHILD_SA,37=INFORMATIONAL |
| Flags(标志位) | 8 bit | I(发起者)、V(版本)、R(响应) |
| Message ID(消息序号) | 32 bit | 消息序号,用于匹配请求/响应与防重放 |
| Length(总长度) | 32 bit | 整个 IKE 消息总长 |
交互时序
IKEv2 建立隧道(标准 2 次往返)
一句话看懂这张图:前两条消息明文谈算法、换 DH 公钥(把信道本身加密起来),后两条消息在加密信道里验身份、定子网,隧道就通了;再往后的 CREATE_CHILD_SA 和 INFORMATIONAL 都属于日常维护(换钥匙、探活、拆隧道)。
| |
对比 IKEv1:IKEv1 需要主模式 6 条消息(或野蛮模式 3 条)+ 快速模式 3 条,共 9 条;IKEv2 只需 4 条消息即可完成认证并建立第一对数据 SA,且原生支持 NAT-T、DPD、EAP 与 MOBIKE(地址漫游)。
关键机制 / 变体
1. 三个数据库的分工
这是干什么的:把"该不该保护"“用什么参数保护"“谁有资格来跟我建隧道"这三个问题拆成三张独立的表,各管一摊。
| 数据库 | 全称 | 作用 | 类比 |
|---|---|---|---|
| SPD | Security Policy Database | 按选择符规定对流量执行 DISCARD / BYPASS / PROTECT | “防火墙规则表” |
| SAD | Security Association Database | 存放每个 SA 的 SPI、密钥、算法、序列号、生存期、模式、隧道端点 | “已建立的加密会话表” |
| PAD | Peer 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 流。
- IKE_SA_INIT 中双方交换
NAT_DETECTION_SOURCE_IP/NAT_DETECTION_DESTINATION_IP载荷(内含 SPI+IP+Port 的哈希)。 - 若收到的哈希与本地计算不符,说明路径上存在 NAT。
- 双方把 IKE 通信从 UDP 500 切换到 UDP 4500,并将后续 ESP 包封装为
UDP(4500) + ESP(非 ESP 的 IKE 消息前加 4 字节全 0 的 Non-ESP Marker 以区分)。 - 位于 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 走天下。
知识框架
| |