【IPSec】Linux xfrm:从策略查找到加解密

💡 原文中文,约3400字,阅读约需8分钟。
📝

内容提要

本文介绍Linux 6.6中IPsec数据面核心对象xfrm:策略库(policy)对应SPD,状态库(state)对应SAD。出站查策略找状态封装,入站按SPI解封装再校验策略。用户态IKE仅协商并安装对象。文章提供ip xfrm命令观测SAD/SPD,手工配置传输模式ESP示例,并说明netns隔离、路由与策略关系,最后通过双netns实验验证数据面流程。

🔎

延伸解读

策略与状态的区分是排障关键

文章强调,xfrm 中 policy 与 state 是两个独立对象,分别对应 SPD 和 SAD。出站时先查 policy 再找 state,入站则先按 SPI 找到 state 解封装,再用 policy 校验。排障时需区分“policy 有、state 无”和“state 有、policy 拒”两种情况,这有助于快速定位问题所在。

netns 隔离与路由的交互

每个 netns 拥有独立的 xfrm 库,SA 和 policy 不跨 netns 共享,因此 IKE 守护进程必须运行在正确的 netns 中。路由决定包的走向,而 xfrm 决定是否进行变换,policy 匹配的是流选择器而非出接口。这种设计增加了运维复杂度,与 WireGuard 的简化模型形成对比。

手工实验验证数据面流程

文章通过双 netns 手工配置传输模式 ESP 的实验,验证了 xfrm 数据面流程。删除出站 policy 后,ping 失败,说明对端仍要求 ESP 入站,明文包无法到达应用。实验使用 ip -s xfrm state 观察包计数递增,确认了数据面正常工作,但强调手工密钥仅用于实验,不适用于生产环境。

Q&A

Linux xfrm 中 policy 和 state 分别对应 IPsec 的什么概念?

在 Linux xfrm 中,policy(策略库)对应 IPsec 的 SPD(安全策略数据库),state(状态库)对应 SAD(安全关联数据库)。policy 定义哪些流量需要保护以及如何保护,state 则保存具体的加密参数和密钥等安全关联信息。

Linux 内核中 xfrm 的出站和入站处理流程是怎样的?

出站时,先根据流信息查找 policy,然后根据 policy 中的模板(tmpl)找到或请求对应的 state,最后进行封装(加解密)。入站时,先根据 SPI 等参数找到 state,进行解封装,然后再用 policy 校验内层报文是否被允许。

如何用 ip xfrm 命令查看和清空 SAD 和 SPD?

查看 SAD 用 `ip xfrm state`,查看 SPD 用 `ip xfrm policy`。带统计信息用 `ip -s xfrm state`。清空 SAD 用 `ip xfrm state flush`,清空 SPD 用 `ip xfrm policy flush`。注意 flush 命令会清空当前网络命名空间中的所有条目,操作危险。

如何手工配置一个传输模式的 ESP 安全关联和策略?

以源 192.0.2.1 到目的 192.0.2.2 为例,先添加状态:`ip xfrm state add src 192.0.2.1 dst 192.0.2.2 proto esp spi 0x2001 mode transport auth sha256 $KEY_A enc aes $KEY_E`,然后添加策略:`ip xfrm policy add src 192.0.2.1/32 dst 192.0.2.2/32 dir out tmpl src 192.0.2.1 dst 192.0.2.2 proto esp mode transport`。对端需要镜像安装反向 SPI 和策略。

网络命名空间(netns)对 xfrm 有什么影响?

每个网络命名空间有自己独立的 xfrm 库。在一个 netns 中安装的 SA 在另一个 netns 中不可见。因此 IKE 守护进程必须运行在正确的 netns 中,或者显式跨命名空间管理。

路由和 xfrm 策略在决定数据包处理时是什么关系?

路由决定数据包往哪里走,而 xfrm 决定数据包在走的时候是否进行变换(加解密)。xfrm 策略匹配的是流选择器(如源/目的地址、协议、端口),而不是出接口名。

在双 netns 实验中,删除出站策略后 ping 失败的原因是什么?

删除本端出站策略后,出站数据包不再进行 ESP 封装,以明文发送。但对端仍然要求 ESP 入站,因此明文或无法封装的包无法通过验证,导致 ping 失败。

🏷️

标签

➡️

继续阅读