IPsec 与 IKEv2

本页目录

IPsec 在 IP 层按策略保护流量,IKEv2 负责认证对端、协商算法和维护安全关联。以总部 10.10.0.0/24 访问分部 10.20.0.0/24 为例:业务主机把包交给网关,网关判断是否需要保护,用已建立的出站 SA 封装;对端网关查找入站 SA、认证解密并核对策略,再转发到内网。

这里有三件独立的事:⁠系统路由把包送到哪里、策略要求怎样保护、SA 是否拥有可用的密钥和状态⁠。IKE 显示已连接,只证明其中一部分成立。

快速定位应看什么
IKE SA 与 Child SA控制消息状态与业务流量状态
ESP 和 AH是否加密、哪些字段被认证
Tunnel 与 Transport是否封装完整原始 IP 包
IKE_AUTH 能否看见头受保护载荷与外层头的边界
UDP 4500 为什么有两种格式IKE 的零标记与 ESP 的非零 SPI
换钥是否重新验证用户Rekey 与 Reauthentication
有 SA 却没有业务计数路由、选择器、转发与回程

策略与安全关联:为什么要分开保存

安全策略数据库 SPD 表达流量应丢弃、绕过还是使用 IPsec 保护;安全关联数据库 SAD 保存具体算法、密钥、SPI、序号和生命周期等状态。一个策略可以在不同时间指向不同代际的 SA,换钥时也可能短暂保留新旧 SA。IPsec 架构 RFC 4301

ESP SA 是单向的:A→B 与 B→A 使用各自的 SPI、密钥与序号。IKEv2 一次 Child SA 协商通常创建这样一对 SA,管理工具可能将其整体显示为一个 CHILD_SA。IKE SA 则保护双方后续控制消息,不能把它的 SPI 和 ESP 的 SPI 当成同一个编号空间。strongSwan IPsec 介绍

入站 ESP 使用接收侧认可的 SPI 查找安全关联;SPI 不是密码,也不是用户身份。即使报文找到 SA,还必须通过认证、重放检查与策略约束。不能只凭看到正确 SPI 就把包当成合法业务。

Traffic Selector 如何限制一条隧道

Traffic Selector 包括地址范围、协议与端口范围。发起方可以提议较宽范围,响应方依据策略接受更窄范围。例如总部提议整个 10.10.0.0/24 访问分部 10.20.0.0/24,最终只允许分部服务器 10.20.0.8 的 TCP 443,就不能把协商成功解释为整个分部网段任意端口可访问。

以下只演示一个方向上已经确定的选择器匹配,不模拟完整 IKE 协商或内核 SPD 优先级。

from ipaddress import ip_address, ip_network

def protected_flow(src, dst, protocol, dport):
    return (ip_address(src) in ip_network('10.10.0.0/24')
            and ip_address(dst) == ip_address('10.20.0.8')
            and protocol == 6 and dport == 443)

assert protected_flow('10.10.0.9', '10.20.0.8', 6, 443)
assert not protected_flow('10.10.0.9', '10.20.0.8', 6, 22)
assert not protected_flow('10.10.0.9', '10.20.0.9', 6, 443)
assert not protected_flow('10.11.0.9', '10.20.0.8', 6, 443)
print('地址、协议、端口共同匹配的局部模型通过')

找到SPI,就能把内层包交付吗?

把正确SPI换成出站SA的SPI,即使同一设备保存它,也不能当作本方向的入站状态。恢复后再改目标端口,密码学检查通过仍可能因选择器拒绝。SPI不是通行密码。

正在呈现知识画面
找到SPI,就能把内层包交付吗?

SPI定位单向密钥状态,选择器约束被保护的流量。查到SA、认证成功、策略允许是三个相继的判据。

ESP:可见字段、加密内容与认证

ESP 使用 IP 协议号 50,AH 使用 51;这里的数字是协议号,不是 TCP/UDP 端口。ESP 可提供机密性与完整性,具体由协商变换决定;AH 提供认证而不提供加密,并覆盖选定的 IP 头字段,对 NAT 地址改写更敏感。不能把所有 ESP 组合都描述为固定一种加密算法。

部分可见性与作用
SPI 4 B、Sequence Number 4 B明文头,帮助定位 SA 与重放检查
显式 IV算法相关,AES-GCM-ESP 为 8 B
Payload、Padding、Pad Length、Next Header在加密变换下被保护的内容
ICV / Tag完整性检查,长度由变换决定

Transport 模式通常保护原始 IP 头之后的上层内容;Tunnel 模式把完整原始 IP 包作为内层载荷,新增外层 IP 头。前者不意味着原始 IP 头完全不可修改,后者也不等于业务端到端加密:网关到网关隧道会在对端网关终止。ESP RFC 4303

AES-GCM 的三个长度不要混

AES-GCM-ESP 的 nonce 由 4 B salt 和 8 B 显式 IV 组成。salt 随密钥材料分配,不是每包再在 ESP 头里发送一个 4 B 字段;显式 IV 出现在包中,同一密钥下不得重复。SPI 与序号参与附加认证数据,因而不能任意改写。

Tag 支持长度由具体变换标识决定:RFC 4106 要求支持 16 B,并允许 8 B 或 12 B,不能一律写成“GCM 的 ICV 是 12 B”。下例选 16 B Tag、最少四字节对齐、IPv4 无选项与 UDP NAT-T;没有额外流量隐藏填充。AES-GCM-ESP RFC 4106

IPv4 隧道 + UDP 封装 + AES-GCM:1,000 B 内层包的账 外层 IP 20 B UDP 8 B ESP 头 8 B 显式 IV 8 B 加密内容 1004 B Tag 16 B 加密内容 = 内层包 1000 + padding 2 + 尾部 2 尾部是 Pad Length 与 Next Header;不含额外四字节 Non-ESP Marker 总长 1064 B;图中框宽不代表真实字节比例 固定使用 16 B Tag、最少四字节对齐、IPv4 无选项;实际预算取决于协商算法与封装。
def esp_tunnel_size(inner, outer_ip=20, udp=True):
    padding = (-(inner + 2)) % 4
    total = outer_ip + (8 if udp else 0) + 8 + 8 + inner + padding + 2 + 16
    return total, padding

assert esp_tunnel_size(1000) == (1064, 2)
assert esp_tunnel_size(1000, udp=False) == (1056, 2)
assert esp_tunnel_size(1000, outer_ip=40) == (1084, 2)
assert max(n for n in range(1501) if esp_tunnel_size(n)[0] <= 1500) == 1438
assert esp_tunnel_size(1438) == (1500, 0)
assert esp_tunnel_size(1439)[0] == 1504
print('明确算法与封装假设下的 ESP 长度预算通过')

1438 B 是该组假设下的最大完整内层 IP 包,不是 TCP 应用载荷。内层 IPv4/TCP 还要扣除自己的头部;算法、外层 IPv6、IP 选项和其他隧道变化后应重新计算。

序号与接收重放窗口允许一定程度的乱序,又拒绝重复包。ESN 使用扩展序号,但线上 ESP 序号字段仍为低 32 位,高位由状态推断并参与认证。重放窗口不是可靠传输窗口:丢失的 ESP 包不会因此被 ESP 自动重传。

IKEv2:先派生保护密钥,再完成身份认证

没有额外挑战、EAP 或扩展交换时,初始建立通常包含 IKE_SA_INIT 与 IKE_AUTH 两个请求—响应交换,即约两个网络 RTT,另加计算时间。Cookie、错误 DH 组重试、认证方法和丢包都可能增加时间,不能写成所有连接恒定四个包。IKEv2 初始交换

基本建立需要两个请求—响应交换;认证扩展可增加往返 发起方 响应方 IKE_SA_INIT:提案、DH 公钥、Ni IKE_SA_INIT:选择、DH 公钥、Nr IKE_AUTH:身份、AUTH、Child 提案与选择器 IKE_AUTH:身份、AUTH、接受的 Child 参数 已有保护密钥,但还没有完成对端身份认证 IKE_AUTH 的受保护载荷被加密,外层 IP/UDP 与 IKE 头仍可见;EAP 可继续交换。

IKE_SA_INIT 交换算法提案、临时 DH 公钥和 nonce。这时获得共同秘密,不代表已经证明对方身份:身份验证要绑定协商记录,防止只建立一个与攻击者共享的加密通道。

IKE_AUTH 的加密载荷包含身份、认证材料和第一条 Child SA 所需参数;外层 IP/UDP 以及 IKE 头仍可见。AUTH 可以基于签名或共享密钥等机制,不能限定为“用证书私钥给第一条消息签名”。基础签名认证的输入还包含对方 nonce 和用 SK_pi/SK_pr 处理的身份载荷,建立握手与身份之间的绑定。RFC 7296 §2.15

EAP 认证可能需要多个 IKE_AUTH 往返;声明 IDi 也不等于已经完成 EAP 身份验证。认证通过之后仍要检查该身份能否请求相应选择器。

密钥派生中的次序与用途

在基础 DH 流程中,记 g^ir 为双方各自使用“自己的私钥、对方的公钥”计算的共享秘密;不是对两个公开 KE 值直接做 DH。

阶段基础派生表达式
初始 IKE 种子SKEYSEED = prf(Ni | Nr, g^ir)
IKE 密钥展开prf+(SKEYSEED, Ni | Nr | SPIi | SPIr)
首个 Child / 无新 DH 的 ChildKEYMAT = prf+(SK_d, Ni | Nr)
有新 DH 的 CREATE_CHILD_SAKEYMAT = prf+(SK_d, g^ir_new | Ni | Nr)

prf+ 是 IKE 定义的迭代展开函数,不是把一个 HMAC 结果无限重复。展开出的 IKE 材料依次服务于 SK_d、两个方向的完整性/加密及身份认证辅助用途;AEAD 组合不另需传统完整性算法的密钥。SK_pi/SK_pr 不是证书私钥。RFC 7296 §2.13–2.17

首个 Child 使用 IKE_SA_INIT 的 nonce;后续创建使用对应新交换的 nonce。存在新的 DH 时,共享秘密在 Ni/Nr 之前⁠,不是可随意放到末尾的附加字段。基础首个 Child 没有自己的额外 KE 交换,不等于整个连接完全没有临时 DH。

NAT-T:UDP 4500 上如何区分 IKE 和 ESP

原生 ESP 没有 TCP/UDP 端口,不少 NAT 难以正确维护多客户端 ESP 映射。NAT-T 将 ESP 封装在 UDP 中,常用 4500;IKE 通常先从 UDP 500 建立,检测 NAT 或按功能条件切到 4500。仅看到 4500 不足以断言一定有 NAT,MOBIKE 等行为也会影响端口使用。strongSwan NAT Traversal

UDP 4500 的 payload判断方式
IKE 消息前置四个零字节 Non-ESP Marker,再接 IKE 头
UDP 封装 ESP直接从非零 SPI 开始,不额外加这四个零
NAT keepalive特定单字节 0xff,用于维持映射

因此前面的 ESP 长度预算只增加 8 B UDP 头,不再加 IKE 专用的 4 B 标记。NAT keepalive 维持映射,受保护的 IKE 活性检查确认 peer 响应,两者不能互相替代。UDP 封装 RFC 3948

换钥、重新认证与地址迁移

CREATE_CHILD_SA 可建立额外 Child、替换已有 Child,也可用于 IKE SA 换钥。基础交换是一个请求加一个响应,约一个 RTT;“小于 0.5 RTT 完成协商”没有对应的协议保证。

Rekey 更新密钥和关联,不等于重新验证证书当前状态或再次执行用户认证。Reauthentication 重走认证过程,影响的状态不同。实现通常让新旧 SA 短暂重叠,接收在途旧包;到期、字节/包计数、重放序号和双方同时发起换钥都需要处理。strongSwan SA Renewal

MOBIKE 是需双方支持并协商的 IKEv2 扩展,让隧道随外层地址变化更新路径;不能因为设备写着“IKEv2”就断言一定支持迁移。它并不替应用创建新的身份,也不保证切换期间零丢包。MOBIKE RFC 4555

证书链较大时,IKE 消息可能受 MTU 与分片限制。IKEv2 的加密消息分片扩展和 IP 层分片不同,也不等于 ESP 数据包可以忽略 PMTU。IKE Fragmentation RFC 7383

从 IKE 成功走到业务成功

Linux 的策略式 IPsec 根据策略捕获匹配流量;XFRM 接口等路由式方式让路由管理更直观,但仍依赖正确的策略、SA 与接口关联。创建接口或添加路由本身不会建立密码学会话。strongSwan Route-based VPN

现象应继续核对的证据
收不到 IKE_SA_INIT 响应外层可达性、UDP 端口、防火墙、对端监听
收到 NO_PROPOSAL_CHOSEN双方算法提案和匹配到的连接配置
AUTHENTICATION_FAILED实际身份、凭据、信任链及认证方法
IKE SA 存在但 Child 失败ESP 提案、TS、地址分配与授权
Child 成立但出站计数不增业务包是否到网关、路由和策略是否匹配
出站增长但入站不增对端计数、回程、过滤、NAT-T 与 SA 状态
小包可用、大传输卡住PMTU、封装预算、ICMP 反馈与分片

可以从 swanctl --list-sas 查看实际协商结果,再对照业务流和路由;Linux ip -s xfrm policy 能观察策略。需要导出 SA 状态时留意某些原始状态命令会包含密钥材料,诊断共享应优先选不输出密钥的摘要。判断性能也要依据实际流量和卸载是否生效,而不是用“企业级”或“内核实现”直接推导吞吐上限。