IPsec 流量选择器:覆盖什么,不覆盖什么
选择器是协商出来的策略,既不是路由,也不是权限。从两端读它,看响应方如何收窄,然后追踪一个目的地。
流量选择器为 IPsec 协议所保护的内层流量命名,而这一对选择器是协商出来的,不是假定的。两个端点可以完美地相互认证,却仍然对哪些报文属于隧道内部各执一词。这种分歧在连接状态里看不见,而状态通常报告隧道健康。从两端读选择器,再追踪一个目的地,比任何幅度的策略修改都能更快找到它。
从两端读它们
每个端点都把己方描述为本地、把对方描述为远端。于是同一对前缀在两份配置里看起来是交换过的,这是正确的,并不矛盾。当一份能工作的协议在纸面上看起来不对时,第一件事就是翻转视角。把两个文件并排比较却不做交换,会造出一个并不存在的不一致。
取值并不总是单个子网。IKEv2 选择器可以携带地址范围、协议号和端口范围,策略正是靠这个来保护单个服务而不是整个网络。比预期流量更窄的选择器,会造出一条只承载部分目的地、悄悄排除其他目的地的隧道。
在改动任何东西之前,先把两端写进一张表。这项练习通常不用碰配置文件就能把问题定下来。
收窄是响应方的决定
发起方提出建议,响应方可以只接受其中一部分。IKEv2 允许响应方收窄所提议的流量选择器,而真正安装下去的是收窄后的结果。所以读发起方的配置,描述的是一个提议,而不是协议本身。
正因如此,给客户端加上一个子网,可能得到一条能工作、却仍然拒绝新目的地的隧道。服务器把提议收窄到策略允许的范围,而客户端文件里仍列着更宽的网段。只有协商后的状态才说出真相:在 Linux 上,ip xfrm policy 和 strongSwan 的 IKEv2 文档里的 child SA 列表报告的是实际安装了什么,而不是请求了什么。两者不一致时,要改的是响应方的策略。
被拒绝的提议和收窄的提议是两种症状。拒绝会出现在协商日志里,并且根本不会留下 child 关联。
端到端追踪一个目的地
选一个真实的目的地,连同客户端会为它使用的源地址,然后让这对地址走完三个相互独立的决定。路由选择路径,选择器决定这条路径是否受保护,防火墙决定报文是否被允许。三者都可以各自失败,而宽泛的选择器一个都修不好。
ip route get 10.20.30.41
ip xfrm policy list
swanctl --list-sas
路由查询会给出承载该报文的接口和源地址。策略列表显示这对地址是否存在匹配的隧道策略,包括方向和级别。SA 列表连同计数器一起显示协商后的 child 选择器,所以尝试过流量之后 child 关联的计数为零,就是选择器把发出的内容排除在外的特征。三条命令,三个不同的答案,而只有一个解释了无声丢弃。
如果 child 计数器在动而应用仍然失败,问题就在隧道之外。这把排查移向远端主机的监听程序或防火墙,而不是选择器。
把两个目标分开
保护办公子网和把全部浏览经远端出口发出,是两种不同的需求,对应不同的选择器。为其中一个构建的配置很少适合另一个,混在一起就会造成泄漏或断裂的分流。扩大受保护网段意味着两端和它们的转发策略都要改,因为单边修改会变成被拒绝的提议。这是小改动之后一条本来工作的隧道停止工作的最常见原因。
选择器描述密码学覆盖范围,路由选择路径,应用执行自己的权限。覆盖一切的隧道仍然到不了绑定在 loopback 上的服务,进入隧道的路由也仍然需要包含目的地的选择器。用同一个测试请求去检查这三者,矛盾自己会报出名字。