IKEv2 SA 已建立却没有子 SA:读一次交换
认证可以完成,而子 SA 协商却失败。先读创建子 SA 的交换,再读提案与选择器,然后才看路由或计数器。
IKE 说隧道已建立,子 SA 却不存在,这两种说法可以同时成立。已建立的控制关系不是数据关联,两个对象的生命周期、协商过程和失败方式都各自独立。把前者报成连通性,工单最后就会声称隧道已建立,而实际什么都不通。要看关联列表,而不是连接的摘要标签,因为只有那张列表能看到缺失的对象。下面就是让这张列表说得通的顺序。
两个关联,两项职责
IKE SA 承载控制通道:身份、密钥,以及控制交换本身的提案。子 SA 承载 ESP 保护,有自己的算法和自己的流量选择器。认证和子 SA 创建通常一起走,因为第一个子 SA 在 IKE_AUTH 内部协商,正是这种捆绑让分离显得意外。
这也解释了你会遇到的两种失败形态。初始交换中被拒绝的子 SA 通常把 IKE SA 一起带下去,所以你根本看不到已建立的控制通道。单独站着的 IKE SA 更常意味着第一个子 SA 成功了,而之后的创建子 SA 尝试失败,例如在密钥更新期间。时间戳比任何配置复核都更快地区分这些情况。
哪一层拒绝了
子 SA 被拒绝时,通知会点名是哪一层。提案被拒意味着双方无法就算法达成一致,常见原因是其中一方要求不同的完全前向保密组,或对方不能接受的加密算法。选择器被拒意味着流量集合被直接拒绝,这是覆盖范围的争论,而不是密码学的争论。
有时没有子 SA 本身就是设计。无子 SA 的 IKE SA 是一种已定义的扩展,用于需要按需创建数据关联的场合,所以缺失是正确的,匹配流量到达时子 SA 才出现。strongSwan 关于 IKEv2 的说明 既讲按需方式,也讲决定第一种情况的提案设置。
在诊断故障之前,先检查是否存在按需或陷阱配置。如果子 SA 是懒创建的,空闲时没有子 SA 就是预期状态,真正的测试是流量能否把它拉起来。这项测试也能把懒设计与静默失败区分开,因为创建失败会让触发器得不到回应,而不只是空闲。
然后问数据路径
一旦子 SA 存在,计数器回答下一个问题。ip -s xfrm state 报告每个关联的包数和字节数,而 生成流量时子 SA 什么都不承载,指向的是匹配或路由 而不是指向缺失的关联。swanctl --list-sas 会把子 SA 的选择器打印在那些计数器旁边,这正是确认数据包落在被接受集合内的依据。
把成功的认证和失败的子 SA 交换在报告里分开写。写认证失败的报告会把下一位工程师送到证书库,而准确的句子要短得多:IKE SA 起来了,这条流的子 SA 从未被接受。
把两端对起来
对于你自己运维的服务器,取同一次交换的客户端和网关日志,而不是比较相隔一小时的两轮重连。两端的通知应当一致;不一致的地方,就是配置错误的那一端。
修正子 SA 协商,然后用落在目标选择器内的流量重新测试。这是唯一能证明缺失对象已经存在的测试,因为空闲时刷新的关联列表在修正前后看起来可能完全一样。