已加载的 strongSwan 配置文件不是活动隧道
strongSwan 先加载定义,再协商 IKE 与 CHILD SA。配置文件已加载这一点,既不能说明隧道是否存在,也不能说明由谁发起。
在 strongSwan 配置中列出某个连接,只能证明定义被加载了。它不意味着对端被联络过、IKE SA 存在或任何流量受到保护。守护进程把定义与活动关联当作两个独立对象,二者之间的距离是刻意做出的设计取舍。知道自己正在检查哪个对象,就能把含糊的故障变成具体的下一条命令。
加载不等于连接
已加载的连接是一句声明:声明稍后可以协商什么——对端地址、凭据、提案和流量选择器。这句话并不要求守护进程已经向任何人拨号。网关可以等待对端、在启动时主动发起,或者等匹配的流量把它唤起。三种都成立,而且在读到启动策略之前,它们在配置文件里看起来完全一样。
运维人员栽跟头,往往是把定义列表当成状态列表来读。配置在,就认定隧道已建立,接下来一小时全花在为一条从未建立的关联调试路由上。
反过来的错误同样常见。配置缺失时,人们去找网络故障,其实配置从未加载。先把对象叫出名字,再执行观察它的命令。
三个对象,三种观察
strongSwan 维护着已加载的定义、IKE SA 和 CHILD SA。第一个是配置,第二个是经过认证的控制关系,第三个是为选定流量协商出的保护。它们甚至各有名字,所以名为 hq 的配置可以拥有一条名为 hq-lan 的 child。
下表把每一层对应到显示它的命令。先读表行,再读日志。
| Layer | What it contains | Command |
|---|---|---|
| Definition | Peer addresses, credentials, proposals, and traffic selectors | swanctl --list-conns |
| IKE SA | One authenticated control channel to the peer | swanctl --list-sas |
| CHILD SA | Keys and selectors for the traffic being protected | Child rows under the IKE SA |
请求 child 时,若不存在,会先建立它的父 IKE SA。只请求 IKE SA 是另一次调用。认证正常的控制通道,并不保证你请求的 child 已经建立。
这个区别在部分失败时很关键。IKE SA 可以健康,而 child 因选择器不匹配或对端不接受的提案而失败。两个对象失败的原因不同,因此值得分开观察。
有意选择启动动作
在 swanctl.conf 中,child 的 start_action 决定加载之后的行为。默认值 none 把定义留给手动发起或作为 responder 使用。start 会主动拨号,而 trap 留下一条策略:一旦出现匹配流量就进行协商。
所以「加载从不启动隧道」和「加载总会启动一条隧道」都不对。动作是配置的一部分,应与对端的角色相匹配。两个网关都等对方,结果只会是沉默,而不是隧道。
用 trap 时,流量必须与选择器匹配,无关的 ping 不会唤醒任何东西。用 start 时,对端地址必须可用,双方还必须在认证和提案上达成一致。两种动作都不能代替这些前提的检查。
恢复是另一套策略
启动不是保活。对端失效检测、对端显式关闭、密钥更新和进程重启,是各自拥有设置的不同生命周期事件。要逐项有意配置,而不是指望一次初始启动就能覆盖全部。
开机时建立、一小时后就死掉的隧道,属于恢复问题。启动策略已经完成了它的任务,之后就不再重要。先看 DPD 和密钥更新设置,再怪最初的协商。
替换已加载的定义是独立操作。非默认的启动策略有文档记载的逆操作,而重新加载是运维变更,不是假定每条关联都已原地更新。要在允许重连的时段分阶段重新加载。在新配置得到验证之前,保留旧配置。
在调试路由之前,先确认存在什么
按顺序做三种观察:已加载的定义、活动的 IKE SA、child 条目。每个答案都会收窄下一个问题。跳过一步,最终就会去调试一个从未建立的层面。
先看已加载的内容,再看真正建立的内容:
swanctl --list-conns
swanctl --list-sas
如果配置正确但 child 缺失,按名字发起它,并观察会发生什么。输出通常会说明父级是否先建立。
swanctl --initiate --child hq-lan
活动 CHILD SA 不是终点线。转发规则、路由和应用自身的授权仍然必须对齐。生命周期回答的是协商了什么;它无法决定谁可以使用该服务。