IPSec 实战与排错 — ip xfrm、strongSwan 与隧道故障定位
Wireshark 抓 ESP/IKE、ip xfrm 与 swanctl 命令、隧道不通与 MTU/NAT 故障排查 / 网络层安全 / 协议号 50/51 / RFC 4301
这篇你能学到
- 抓包时先看 IKE 还是先看 ESP、每个 NOTIFY 通知(
NO_PROPOSAL_CHOSEN、TS_UNACCEPTABLE等)分别指向什么配置错误。 - 用
ip xfrm、swanctl、ipsec statusall查隧道状态与内核计数器,判断问题出在控制平面还是数据平面。 - 处理三类最典型的 IPSec 故障:隧道建不起来、隧道 UP 却 ping 不通、小包通大包卡——以及它们各自的固定套路。
抓包观察
Wireshark 显示过滤式
这些过滤式能干什么:把"谈判过程"(IKE)和"实际数据"(ESP)分开看。建隧道失败就盯
isakmp系列,隧道建好了但流量不通就盯esp系列。
| 目的 | 过滤表达式 |
|---|---|
| 所有 IKE 协商流量 | isakmp |
| 只看 IKEv2 | isakmp.version == 0x20 |
| IKE_SA_INIT 交换 | isakmp.exchangetype == 34 |
| IKE_AUTH 交换 | isakmp.exchangetype == 35 |
| CREATE_CHILD_SA | isakmp.exchangetype == 36 |
| INFORMATIONAL(含 DPD/删除) | isakmp.exchangetype == 37 |
| 所有 ESP 包 | esp |
| 按 SPI 过滤某条 SA | esp.spi == 0xc0a80101 |
| 看 ESP 序列号(查重放) | esp.sequence |
| AH 包 | ah |
| 原始协议号方式过滤 | ip.proto == 50(ESP)、ip.proto == 51(AH) |
| NAT-T 封装的 ESP | udp.port == 4500 |
| IKE 与 NAT-T 一起看 | udp.port == 500 || udp.port == 4500 |
| ICMP 需要分片(MTU 问题) | icmp.type == 3 && icmp.code == 4 |
典型字段说明
排查隧道建立失败时,只看 IKE,不看 ESP。 顺序如下:
isakmp.exchangetype == 34:是否有 IKE_SA_INIT 响应?- 无响应 → UDP 500 被防火墙拦、对端地址错、对端服务未起。
- 响应中带
NOTIFY: NO_PROPOSAL_CHOSEN→ 阶段 1 算法提议无交集(加密/完整性/PRF/DH 组)。 - 响应中带
NOTIFY: INVALID_KE_PAYLOAD→ DH 组不匹配,响应方会提示它期望的组号。 - 出现
NAT_DETECTION_*载荷 → 路径上有 NAT,后续应切到 UDP 4500。
isakmp.exchangetype == 35:IKE_AUTH 阶段AUTHENTICATION_FAILED→ 预共享密钥不一致,或证书/ID 不匹配。TS_UNACCEPTABLE→ 流量选择符(Traffic Selector)不匹配,即两端配置的本端/对端子网对不上。NO_PROPOSAL_CHOSEN出现在此阶段 → 阶段 2(ESP)算法提议无交集。
- 数据不通时看
esp:- 只见发出、不见回包 → 对端未建 SA、回程路由缺失,或中间设备丢弃协议号 50。
esp.sequence一直是 1、2、3 且不增长 → 出方向没流量命中策略,检查 SPD/路由。
常用命令 / 配置
Linux 内核 XFRM 框架(发行版通用,最直接)
这组命令能干什么:绕开所有 VPN 软件,直接问内核"你现在到底建了哪几条加密通道、跑了多少包、丢包丢在哪一步"。这是判断"问题在配置还是在网络"的最快路径。
| |
/proc/net/xfrm_stat 关键计数含义:
| 计数器 | 含义 |
|---|---|
XfrmInNoStates | 收到 ESP 包但找不到对应 SA(对端已 rekey、本端 SA 已删) |
XfrmInStateSeqError | 抗重放检查失败(乱序超窗口或真重放) |
XfrmInStateProtoError | 协议解析或 ICV 校验失败 |
XfrmOutNoStates | 出方向命中策略但无 SA(IKE 未协商成功) |
XfrmOutPolBlock | 被 SPD 的 DISCARD 策略丢弃 |
XfrmInTmplMismatch | 入方向包与策略模板不匹配(选择符对不上) |
strongSwan(主流开源实现)
这组命令能干什么:从 VPN 守护进程的视角看隧道——加载了哪些连接配置、当前有几条 SA 活着、手动把某条隧道拉起来或拆掉、以及把日志级别调高看协商细节。
| |
strongSwan swanctl.conf 站点到站点示例
这段配置能干什么:把两个分公司的内网(10.1.0.0/16 与 10.2.0.0/16)用一条 IKEv2 隧道打通。重点看三处——
proposals(阶段 1 算法,两端必须有交集)、local_ts/remote_ts(子网定义,A 的 local 必须等于 B 的 remote)、esp_proposals(阶段 2 算法,带modp即启用 PFS)。
| |
连通性与路径验证
这组命令能干什么:验证"数据平面"这一半——用内网源地址发包看能不能命中策略、二分法找出隧道真正能扛多大的包、确认防火墙放行了 UDP 500/4500 和协议号 50/51、以及用 MSS 钳制这剂"大包不通万能药"。
| |
Wireshark 解密 ESP
这一步能干什么:把抓到的密文 ESP 包还原成隧道内的明文 IP 包,用来确认"内层到底跑的是什么流量、源目地址对不对"。
在 编辑 → 首选项 → Protocols → ESP 中勾选 Attempt to detect/decode encrypted ESP payloads,并在 ESP SAs 表中填入 ip xfrm state 输出的加密密钥与认证密钥(十六进制,带 0x 前缀),即可看到隧道内的明文包。
常见故障与排错
结论先行:一眼看懂每个现象在说什么
- IKE_SA_INIT 无响应 —— 先记住结论:包根本没到对端,或对端没在听,属于网络可达性问题,先别查算法配置。
NO_PROPOSAL_CHOSEN(阶段 1) —— 先记住结论:两端算法列表没有交集,谈判在第一步就崩了。INVALID_KE_PAYLOAD—— 先记住结论:DH 组选错了,而且响应方会明确告诉你它想要哪个组号。AUTHENTICATION_FAILED—— 先记住结论:身份没验过,密钥/证书/ID 三者之一对不上。TS_UNACCEPTABLE—— 先记住结论:两端画的子网范围对不上,这是最常见的配置错误。- 隧道 UP 但 ping 不通 —— 先记住结论:控制平面成功不代表数据平面通,问题在路由、转发开关或 NAT 抢跑。
- 小包通、大包/HTTP 卡住 —— 先记住结论:这是 MTU 问题,不是加密问题,加壳后包超了路径 MTU 而 PMTUD 又失效了。
- NAT 后隧道建不起来或几分钟后断 —— 先记住结论:NAT-T 没生效或映射被回收了。
- 用 AH 完全不通 —— 先记住结论:AH 和 NAT 天生互斥,不是配置问题,是协议设计使然。
- 隧道每隔固定时间断一次 —— 先记住结论:断在 rekey 那一刻,两端生存期或 PFS 组不一致。
XfrmInStateSeqError持续增长 —— 先记住结论:抗重放窗口把正常的乱序包误杀了(也可能是真重放)。XfrmInNoStates增长 —— 先记住结论:收到的包属于一条本端已经不存在的 SA,两端换钥匙没同步。- 对端重启后隧道半死(单向通) —— 先记住结论:一端的 SA 还留着、另一端已经清空,缺少探活机制。
详细排查表(现象 / 可能原因 / 排查方法)
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| IKE_SA_INIT 无响应 | UDP 500 被中间防火墙/云安全组拦截;对端 IP 写错;对端 charon 未运行 | nmap -sU -p 500 对端;两端同时抓 udp.port==500 看包有没有出去/进来 |
NO_PROPOSAL_CHOSEN(阶段 1) | IKE 算法提议无交集(加密/完整性/PRF/DH 组) | 对齐 proposals;日志里响应方会列出自己支持的提议 |
INVALID_KE_PAYLOAD | DH 组不一致 | 响应方 NOTIFY 中会给出期望的组号,按其修改 |
AUTHENTICATION_FAILED | PSK 不一致;证书过期/CA 不信任;ID 类型与配置的 leftid/rightid 不符 | 核对 secrets;ipsec listcerts;确认 NAT 后一端应使用 FQDN 而非 IP 作 ID |
TS_UNACCEPTABLE | 两端 local_ts / remote_ts 子网定义对不上(最常见配置错误) | A 的 local 必须等于 B 的 remote,反之亦然;注意掩码位数与 0.0.0.0/0 的处理 |
| 隧道 UP 但 ping 不通 | ① 路由未指向隧道 ② 未开 ip_forward ③ NAT 规则把内网流量先 SNAT 了导致不命中 SPD ④ 回程路由缺失 | ip route get 10.2.0.1;ip -s xfrm state 看出方向计数是否增长;在 nat POSTROUTING 中为隧道流量加 -j ACCEPT 例外 |
| 小包通、大包/HTTP 卡住 | MTU 问题:加了 ESP 头后超出路径 MTU,且 ICMP “需要分片” 被拦 | ping -M do -s N 二分找上限;配 TCPMSS --clamp-mss-to-pmtu;隧道口设 mtu 1400 |
| NAT 后隧道建不起来或几分钟后断 | 未启用 NAT-T;NAT 映射超时 | 抓包确认是否切到 UDP 4500;检查 NAT_DETECTION 载荷;开启 keepalive(strongSwan keep_alive) |
| 用 AH 完全不通 | AH 的 ICV 覆盖 IP 头,NAT 改地址后校验必然失败 | NAT 环境改用 ESP(生产环境本就应优先 ESP) |
| 隧道每隔固定时间断一次 | rekey 失败:两端 lifetime/PFS 组不一致;一端不支持 CREATE_CHILD_SA | 日志搜 rekey;对齐 rekey_time 与 esp_proposals 中的 DH 组 |
XfrmInStateSeqError 持续增长 | 抗重放窗口过小 + 网络乱序(多路径/QoS) | 增大 replay_window(strongSwan replay_window = 128)或排查底层乱序 |
XfrmInNoStates 增长 | 对端已 rekey 生成新 SPI,本端旧 SA 已删 | 检查两端 lifetime 差距;缩小差异并设置 rekey 提前量 |
| 对端重启后隧道半死(单向通) | 一端 SA 还在,另一端已清空 | 开启 DPD(dpd_delay + dpd_action = restart)自动检测并重建 |
通用排查顺序:两端能否 IP 可达 → UDP 500/4500 是否放行 → IKE_SA_INIT 有无响应 → IKE_AUTH 是否通过认证 → TS 是否匹配 → ip xfrm state 是否成对存在 → 出方向计数是否增长 → 路由/NAT/forward → MTU。
与其他协议对比
| 维度 | IPSec | TLS | WireGuard | GRE(裸) | L2TP(裸) |
|---|---|---|---|---|---|
| 工作层次 | 网络层(IP) | 传输层之上 | 网络层(UDP 承载) | 网络层封装 | 二层隧道 |
| 加密 | ✅ ESP | ✅ | ✅ 固定 ChaCha20-Poly1305 | ❌ 无 | ❌ 无 |
| 认证方式 | PSK / X.509 证书 / EAP | X.509 证书(PKI) | 静态公钥(类 SSH) | 无 | PPP 用户认证 |
| 对应用透明 | ✅ 完全透明 | ❌ 需应用支持 | ✅ 透明 | ✅ | ✅ |
| 承载 | IP 协议号 50/51 | TCP | UDP(可自定义端口) | IP 协议号 47 | UDP 1701 |
| NAT 穿越 | 需 NAT-T(AH 不可) | 天然支持 | 天然支持 | 需额外处理 | 需配合 IPSec |
| 组播/动态路由 | 隧道模式默认不支持组播 | 不适用 | 不支持 | ✅ 支持 | ✅ |
| 配置复杂度 | 高(参数众多) | 中 | 低 | 低 | 中 |
| 典型场景 | 企业站点互联、云 VPC 互联 | Web/API 加密 | 个人与轻量组网 | 多协议封装 | 拨号接入 |
生产常见组合:GRE over IPSec(GRE 提供组播与动态路由能力,IPSec 提供加密),或 VTI/route-based IPSec(把隧道抽象成一个虚拟接口,路由更自然)。
速查表 / 常见面试题
核心数字速查
| 项目 | 值 |
|---|---|
| ESP 协议号 | 50 |
| AH 协议号 | 51 |
| IKE 端口 | UDP 500 |
| NAT-T 端口 | UDP 4500 |
| IKEv2 交换类型 | 34=IKE_SA_INIT,35=IKE_AUTH,36=CREATE_CHILD_SA,37=INFORMATIONAL |
| IKEv2 建隧道消息数 | 4 条(2 次往返) |
| IKEv1 主模式 + 快速模式 | 6 + 3 = 9 条 |
| 抗重放窗口默认 | 64 位(可配 128/1024) |
| ESP 隧道模式典型开销 | 约 50–73 字节 |
| 常见隧道口 MTU 设置 | 1400(以太网 1500 环境下的保守值) |
常见面试题
AH 与 ESP 的区别?为什么生产上几乎只用 ESP? AH 只提供完整性与数据源认证,不加密;ESP 同时提供加密与认证。AH 的 ICV 覆盖 IP 头,与 NAT 天然冲突;ESP 的 ICV 不覆盖外层 IP 头,配合 NAT-T 可穿越 NAT。ESP 的能力是 AH 的超集,所以 AH 已基本退役。
传输模式与隧道模式怎么选? 主机到主机直连(如两台服务器间加密)用传输模式,开销小;网关到网关、需要隐藏内网拓扑、需要为整个子网提供保护时用隧道模式——这也是 VPN 的标准做法。
SA 为什么是单向的? 因为加解密的密钥、序列号、算法在两个方向上可以不同,且单向建模让状态机更简单、更易做抗重放。因此一条双向隧道至少有 2 个 IPSec SA。
SPI 由谁分配? 由接收方分配。A 告诉 B “你发给我的包请打上 SPI=X”,B 在发包时填入该 SPI,A 收到后据此查表定位 SA。
IKEv2 相比 IKEv1 的改进? 消息数从 9 条降到 4 条;原生集成 NAT-T、DPD、EAP;支持 MOBIKE 地址漫游;请求/响应严格配对且带 Message ID,状态机更健壮;抗 DoS 的 Cookie 机制标准化。
为什么 IPSec 隧道 UP 了却 ping 不通? 最常见四类:路由没指过去、
ip_forward未开、NAT 规则抢先把内网流量 SNAT 导致不命中 SPD、两端 TS(流量选择符)虽协商成功但实际发包的源 IP 不在保护子网内。为什么 IPSec 隧道里大包会卡住? 加了 ESP 头后包超出路径 MTU,需要分片;若路径上 ICMP “Fragmentation Needed” 被防火墙拦截,PMTUD 失效形成黑洞。解法:TCP MSS 钳制 + 调低隧道接口 MTU。
PFS 在 IPSec 里指什么? Child SA rekey 时是否重新做一次 DH 交换。开启后每对 SA 的密钥彼此独立,单个密钥泄露不波及其他;代价是每次 rekey 多一次 DH 运算。两端 PFS 组必须一致。
IPSec 和 TLS 该选哪个? 需要保护"整个网络之间的全部流量、且不能改应用"选 IPSec(企业组网);需要保护"某个具体服务的连接、要穿公网和 NAT、要用 PKI 生态"选 TLS(互联网服务)。二者不互斥,可叠加。