两种设计用同一套 IPsec 机制保护同样的流量,区别在于由什么决定哪个数据包进入隧道。基于策略的连接里,由协商出的流量选择器来决定;基于路由的连接里,由指向隧道接口的路由来决定。把两者混淆,就会出现那种熟悉的技术支持对话:隧道报告已建立,应用却什么也到不了。当你新增网段、运行路由协议,或排查一条悄悄从错误出口离开的路径时,这个区别最要紧。

决定什么进入隧道的两种方式

基于策略的 VPN 会建立一条匹配源和目的前缀的安全策略,然后加密所有符合的流量。对端必须协商出兼容的选择器,因此有效范围最终是双方提案的交集。交集之外的一切都不受保护,无论路由表怎么说。

基于路由的 VPN 创建一个代表隧道的接口,并让路由表把流量送进去。IKE 守护进程仍会安装状态和每接口策略,而人们在断定路由已经取代加密时,往往会跳过这个细节。两种设计都用 IPsec 加密;只有选择机制不同。

把下面的比较看作一组故障特征,而不是评分表,因为两列在抽象层面都不占优。

AspectPolicy-basedRoute-based
What selects trafficNegotiated selectorsA route into the tunnel interface
Adding a networkEdit selectors on both peersAdd a route, widen the selector once
Dynamic routingAwkward to run over the tunnelRuns over the interface directly
Typical failureTunnel up, host outside the selectorTunnel up, no route or wrong source

基于策略:选择器就是契约

选择器是协商出来的,而不只是配置出来的。在一侧提议 10.10.0.0/16、另一侧提议 10.10.1.0/24,关联就只覆盖协商落定的范围,其他主机都留在外面。

要读已安装的状态,而不是配置文件。在 Linux 对端上,内核自己的表才是基本事实,它们显示协商后留下了什么。策略写明了正确的前缀却没有对应状态,说明关联从未建立。状态与错误前缀的策略配在一起则是相反的问题,它会造出一条看起来健康、但某个子网什么也到不了的隧道。

sudo ip xfrm state
sudo ip xfrm policy
sudo swanctl --list-sas

把两份输出与你认为受保护的前缀逐一比较。这一次比较就能解决大多数“隧道正常、服务器不可达”的报告。它还会指出该改哪一端,因为不匹配通常只在一个方向上可见。

基于路由:接口就是契约

XFRM 接口给隧道一个名字和身份,流量之所以到达它,是因为路由表这么指示。于是多个远端前缀变成路由问题而不是选择器问题,路由协议也可以通告它们。这才是真正的收益,而不是加密。

接口并不消除对策略的需要。守护进程会安装绑定到接口身份的每接口规则,因此到达错误接口的数据包仍然失败。对端不接受源地址时,即使路由完美也会失败。基于路由是指路由决定入口,而不是策略消失了。

sudo ip link add xfrm0 type xfrm dev eth0 if_id 42
sudo ip route add 10.20.0.0/16 dev xfrm0
ip -s link show xfrm0
ip route get 10.20.5.10

路由就位后要盯住接口计数器。路由存在而计数器停在零,说明没有任何流量被匹配进隧道,这通常指向缺少状态而不是缺少路由。

两种设计真正分歧之处

新增网段是检验哪种模型适合你的最干净的办法。基于路由的设计增加一条路由,最多把选择器放宽一次;基于策略的设计则要在两端改前缀对并重新协商。两个稳定子网让这种修改微不足道,二十个就变成了项目。

两种模型都不能替代防火墙,比较通常到此为止。宽泛的选择器或宽路由决定的是加密什么,而不是允许什么。

MTU 行为在实践中也不同。封装会减少可用载荷,而基于路由的接口自带 MTU,因此在两端网关钳制 MSS 可以避免“小包能回、大包消失”的黑洞症状。基于策略的隧道从另一侧撞上同一堵墙,因为选择器并不涉及包大小。要有意设置钳制,而不是怪对端。

迁移时不丢失回程路径

动手前先记录现有的前缀对,然后移动一条应用路径并端到端观察。能建立不等于能转发,差别会出现在回程方向上。

当隧道两端连上而局域网主机不通时,检查回程路由和远端主机将使用的源地址。双网卡主机可能从错误的那张网卡回应,任何选择器改动都修不好。改算法之前先在两端抓包。

ip route get 10.20.5.10
sudo tcpdump -ni any host 10.20.5.10 and icmp
sudo swanctl --list-conns

工作时保留一条不依赖隧道的管理路径。当网关自身的访问不搭在你正在调试的连接上时,回滚会更容易。

相关文章