IPsec 在 Linux 上的数据面主路径是
xfrm(transform):策略库近似
SPD,状态库近似 SAD,加解密在协议栈挂钩点完成。用户态
IKE(strongSwan 等)只负责协商并把对象装进
xfrm;本篇钉内核侧对象与查找,版本锚定 Linux
6.6(与本站 WireGuard 系列同代)。IKE 如何安装见 第 6
篇;可复现命令见 运维篇
与 reproduce/07-xfrm-transport.sh。
一、两个对象:policy 与 state
| RFC 4301 | Linux xfrm | ip 观测 |
|---|---|---|
| SPD 条目 | xfrm_policy |
ip xfrm policy |
| SA | xfrm_state |
ip xfrm state |
policy
带选择器(源/宿前缀、协议、端口等)与方向(in /
out / fwd),并挂
tmpl:要求的协议(esp/ah)、模式(transport/tunnel)、可选
reqid、隧道端点。
state 带 SPI、外层 src/dst、算法与密钥、模式、序列号 / anti-replay、生命周期计数。
出站:查 policy → 按 tmpl 找到或请求 state →
做封装。
入站:按 SPI 等找到 state → 解封装 → 再用 policy
校验内层是否允许。
二、源码地图(Linux 6.6)
树:net/xfrm/。与策略相关的入口在
xfrm_policy.c(本系列核对的是
v6.6 标签源码):
| 符号 | 作用 |
|---|---|
xfrm_policy_insert |
插入策略 |
xfrm_lookup /
xfrm_lookup_route |
出站路径上根据 flow 查找变换 |
__xfrm_policy_check |
入站(及部分转发)策略检查 |
__xfrm_decode_session |
从 skb 解码 flowi 选择器 |
IPv4 发送路径在路由之后会进入 xfrm 查找(站内 linux-net
路由篇 已点到 xfrm_lookup_route())。具体
ESP 输入/输出变换在 net/ipv4/esp4.c(及 IPv6
对应文件)与 xfrm_input / output
状态机中完成;排障时不必先读完所有文件,但应能把「policy
有、state 无」与「state 有、policy 拒」区分开。
用户态配置通道:xfrm_user
netlink(net/xfrm/xfrm_user.c),ip xfrm
与 strongSwan 的 kernel-netlink 插件都走这里。
三、ip xfrm
最小观测面
ip xfrm state # SAD
ip -s xfrm state # 带字节/包计数
ip xfrm policy # SPD
ip xfrm state flush # 危险:清空本 netns 全部 SA
ip xfrm policy flush手工安装(传输模式示意,密钥仅为实验):
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/policy。本机双 netns
实测见运维篇:ping 成功后 ip -s xfrm state 的
lifetime current 包计数递增。
四、与 netns、路由的交界
- 每个 netns 有自己的 xfrm 库。在 A netns 装的 SA,B 看不见——IKE 守护进程必须跑在正确的 netns,或显式跨 ns 管理。
- 路由仍决定包往哪走;xfrm 决定「走的时候是否变换」。policy 匹配的是(解码后的)流选择器,不是「随便某个出接口名」。
- WireGuard 把策略塌缩进
wg0+ AllowedIPs;xfrm 没有强制虚拟网卡——隧道模式靠外层 IP,传输模式靠原 socket/路由路径上的钩子。这是运维心智负担的来源之一。
五、本机实验摘要
环境:6.6.87.2-microsoft-standard-WSL2,iproute2-7.0.0。双
netns + veth(192.0.2.1/30 ↔︎
192.0.2.2/30),手工 transport ESP(AES-CBC +
HMAC-SHA256)。
- 策略与状态齐全时:
ping -c 3 192.0.2.2全成功;出站 state 显示3 packets/192 bytes(ICMP echo 载荷路径计数,随实现统计口径)。 - 删除本端
dir outpolicy 后:同命令 2 packets transmitted, 0 received——对端仍要求 ESP 入站,明文或无法封装的包到不了应用。
脚本:reproduce/07-xfrm-transport.sh。该实验故意不跑
IKE,只验证 xfrm 数据面;自动协商见第 6–7 篇。
六、本文边界
- 不展开 inexact policy hash、migrate、offload 全部分支。
- 不逐行注释
esp4.c。 - 不把手工密钥实验当成生产密钥管理。
参考资料
源码
- Linux
v6.6:
net/xfrm/xfrm_policy.c(xfrm_lookup、__xfrm_policy_check等)。 - Linux
v6.6:
net/xfrm/xfrm_user.c、net/ipv4/esp4.c。
规范 / 站内
- RFC 4301(策略模型)。
- 架构篇
- linux-net 路由
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
IPSec / IKEv2 深度系列:从正确分层到 Linux xfrm
作为 WireGuard 系列的对照续作:拆解 RFC 4301 的 SPD/SAD、IKEv2 握手与密钥树、ESP/NAT-T、Linux 6.6 xfrm 与 strongSwan 落盘,并以形式化分析与后量子混合 KE 收束选型边界。
【IPSec】架构:SPD、SAD 与「正确分层」
RFC 4301 把「要不要保护」与「用哪把密钥」拆成 SPD 与 SAD。本文钉住安全关联、选择器、传输/隧道模式,并与 WireGuard cryptokey routing 做公理对照——不复述选型口号。
【IPSec】ESP、AH 与 NAT-T
数据面几乎总是 ESP:拆开隧道模式封装、AEAD 与 EtM、anti-replay 窗口,以及 NAT 场景下 UDP/4500 封装如何改写外层五元组却保持 SPI 查找语义。
【IPSec】strongSwan:从 swanctl 到内核 SA
拆解 strongSwan 的 charon、VICI/swanctl 与 kernel-netlink:配置里的 connections/children/proposals 如何变成 Linux xfrm 的 policy 与 state,并与 VPN 对比文中的站点示例对齐。