在 strongSwan 配置中列出某个连接,只能证明定义被加载了。它不意味着对端被联络过、IKE SA 存在或任何流量受到保护。守护进程把定义与活动关联当作两个独立对象,二者之间的距离是刻意做出的设计取舍。知道自己正在检查哪个对象,就能把含糊的故障变成具体的下一条命令。

加载不等于连接

已加载的连接是一句声明:声明稍后可以协商什么——对端地址、凭据、提案和流量选择器。这句话并不要求守护进程已经向任何人拨号。网关可以等待对端、在启动时主动发起,或者等匹配的流量把它唤起。三种都成立,而且在读到启动策略之前,它们在配置文件里看起来完全一样。

运维人员栽跟头,往往是把定义列表当成状态列表来读。配置在,就认定隧道已建立,接下来一小时全花在为一条从未建立的关联调试路由上。

反过来的错误同样常见。配置缺失时,人们去找网络故障,其实配置从未加载。先把对象叫出名字,再执行观察它的命令。

三个对象,三种观察

strongSwan 维护着已加载的定义、IKE SA 和 CHILD SA。第一个是配置,第二个是经过认证的控制关系,第三个是为选定流量协商出的保护。它们甚至各有名字,所以名为 hq 的配置可以拥有一条名为 hq-lan 的 child。

下表把每一层对应到显示它的命令。先读表行,再读日志。

LayerWhat it containsCommand
DefinitionPeer addresses, credentials, proposals, and traffic selectorsswanctl --list-conns
IKE SAOne authenticated control channel to the peerswanctl --list-sas
CHILD SAKeys and selectors for the traffic being protectedChild 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 不是终点线。转发规则、路由和应用自身的授权仍然必须对齐。生命周期回答的是协商了什么;它无法决定谁可以使用该服务。

相关文章