协议与内核对象弄清之后,事故多半出在三张表不一致:IKE
连接视图(swanctl)、策略(ip xfrm policy)、状态(ip xfrm state)。本文先给不依赖
IKE 守护进程的双 netns ESP 实测(直接验证 xfrm
数据面),再列 strongSwan 排障台账与典型故障模式。环境:
- OS /
内核:
6.6.87.2-microsoft-standard-WSL2 - 工具:
iproute2-7.0.0(ip xfrm) - 权限:创建 netns / xfrm 需要
CAP_NET_ADMIN
密钥为实验占位;ping RTT 与 xfrm 计数来自真实执行。自动化脚本:reproduce/07-xfrm-transport.sh。
本机写作时发行版源同步受阻,未能安装 strongSwan 包做 charon 端到端握手。IKE 配置方言仍以 第 6 篇 与 VPN 对比文 为准;装进内核后的对象形态与「缺 policy 即不通」与 IKE 路径相同。
一、拓扑
ipsec-a ipsec-b
veth-a 192.0.2.1/30 <----------> veth-b 192.0.2.2/30
ESP transport SPI 0x2001 → ← SPI 0x2002
policy out/in 匹配对端 /32
传输模式保护两主机间 IP 流量:无内网叠隧道地址,排障面更小,适合验证「policy + state」是否咬合。站点隧道(tunnel mode + TS 子网)在 charon 可用后用同一观测命令即可。
二、实测:ESP 下 ping
按脚本装齐两侧 state/policy 后:
ip netns exec ipsec-a ping -c 3 -W 1 192.0.2.2实测结果:
PING 192.0.2.2 (192.0.2.2) 56(84) bytes of data.
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.070 ms
64 bytes from 192.0.2.2: icmp_seq=3 ttl=64 time=0.071 ms
--- 192.0.2.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2040ms
rtt min/avg/max/mdev = 0.070/0.070/0.071/0.000 ms
同机 netns 的 RTT 不能外推公网延迟或吞吐。
出站 SA(ip -s xfrm state
片段,以下经删减):
src 192.0.2.1 dst 192.0.2.2
proto esp spi 0x00002001 mode transport
lifetime current:
192(bytes), 3(packets)
anti-replay context: seq 0x0, oseq 0x3, bitmap 0x00000000
包计数与三次 ping 一致;oseq
前进说明本端确在发送 ESP。
三、实测:删掉 out policy
ip netns exec ipsec-a ip xfrm policy del src 192.0.2.1/32 dst 192.0.2.2/32 dir out
ip netns exec ipsec-a ping -c 2 -W 1 192.0.2.2实测:
2 packets transmitted, 0 received, 100% packet loss
恢复 out policy 后单次 ping
立即成功(time=0.053 ms)。
解释:对端仍保留 dir in 的 ESP 要求;本端无 out
policy 时无法按 tmpl
封装(或走明文被对端策略拒绝)。这是「SA
还在、策略方向缺一条」的最小复现——对应生产里
swanctl 显示有 SA、但某方向 policy 未装上。
四、排障命令台账
| 目的 | 命令 |
|---|---|
| IKE / Child 视图 | swanctl --list-sas、--list-conns、--list-pols |
| 内核 SAD/SPD | ip xfrm state、ip xfrm policy、ip -s xfrm state |
| 抓外层 | tcpdump -n esp or udp port 500 or udp port 4500(需安装
tcpdump) |
| 触发协商 | swanctl --initiate --child …;或依赖
start_action = trap |
| 清空实验残留 | 每 netns 内
ip xfrm state flush;policy flush(生产慎用) |
核对清单:
- IKE 是否
ESTABLISHED?失败看 AUTH / proposal / ID。 - Child 是否
INSTALLED?对照ip xfrm state是否有成对 SPI。 policy的 src/dst 与业务五元组是否一致?方向是否 in/out 成对?- NAT 路径是否应看到 UDP/4500 而非裸 ESP?
- rekey 前后是否出现双 SPI、旧 SPI 是否按硬超时消失?
五、故障模式(按层)
| 现象 | 先查 |
|---|---|
| 无法 ESTABLISHED | proposal 交集、PSK/证书、时钟、防火墙 UDP/500·4500 |
| ESTABLISHED 但不通 | TS /
local_ts·remote_ts、policy
方向、路由、对端防火墙 |
| 单向通 | 单侧 policy/state 缺失、anti-replay、非对称 NAT |
| 通一会儿断 | DPD、NAT 映射超时、硬 lifetime、策略路由抖动 |
| 计数涨但业务错 | 错误 Child 抢走选择器、多 SA 重叠 |
与 WireGuard 对照:WG 事故常在 AllowedIPs ↔︎ FIB;IPsec 多一张 IKE 身份/证书 表。三张表任一脱节都够用一夜。
六、明确不适用 / 慎用场景
- 需要极简审计面、固定算法、无证书流程:优先评估 WireGuard。
- 需要 L2 扩展:IPsec alone 不是以太网桥;常与其他封装组合,复杂度另计。
- 本实验密钥写死在脚本:仅限实验室,禁止用于真实流量。
七、本文边界
- 未在本文环境跑通 charon PSK 全握手;不编造
swanctl --list-sas屏幕输出。 - 未测跨公网吞吐;无对比「比 WireGuard 慢 X%」。
- tcpdump 未预装,抓包步骤保留命令、不贴伪造 hex。
下一篇把选型放进 形式化、敏捷性与后量子 争论里收束。
参考资料
实验
- 本机 netns +
ip xfrm(上文输出)。 - reproduce/07-xfrm-transport.sh
站内
- Linux xfrm
- strongSwan
- WireGuard 运维篇(对照故障面)
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
IPSec / IKEv2 深度系列:从正确分层到 Linux xfrm
作为 WireGuard 系列的对照续作:拆解 RFC 4301 的 SPD/SAD、IKEv2 握手与密钥树、ESP/NAT-T、Linux 6.6 xfrm 与 strongSwan 落盘,并以形式化分析与后量子混合 KE 收束选型边界。
【IPSec】Linux xfrm:从策略查找到加解密
把 RFC 4301 的 SPD/SAD 映射到 Linux 6.6 的 xfrm policy/state:查看出站 xfrm_lookup、入站策略检查与 ip xfrm 观测面,并给出本机 netns 下手工安装 ESP 的对照实验入口。
【IPSec】strongSwan:从 swanctl 到内核 SA
拆解 strongSwan 的 charon、VICI/swanctl 与 kernel-netlink:配置里的 connections/children/proposals 如何变成 Linux xfrm 的 policy 与 state,并与 VPN 对比文中的站点示例对齐。
【WireGuard】使用与运维:netns 实测、AllowedIPs 与故障模式
在 WSL2 Linux 6.6 上用双 netns + veth 实测 WireGuard 握手与 ping;整理 wg/wg-quick 工作流、AllowedIPs 与 FIB 脱节、漫游、MTU 与明确不适用场景。