在组织地址池中闲置不用的地址不是监听者,把它加进防火墙也不会凭空造出一个。必须有什么东西在该地址上终结 IKE,而机制取决于网关自己持有该地址,还是上游设备对它做转换。区分这两种情况的正是报文路径,而在任何人提交变更申请之前,需要哪项平台功能也由这条路径决定。先给路径建模,再做选择。

地址背后的报文路径

对端把 IKE 发到分配给它的地址,走 UDP 500,或者在涉及 NAT 穿透时走 UDP 4500。路径上持有该地址的设备,要么在本地接收该数据报并应答,要么把它转发到别处。只有这两种可能,本文其余内容都取决于哪一种成立。

本地接收意味着该设备上存在一个绑定到该地址的套接字。转发意味着数据报被改写并继续送往另一个端点,套接字随后由那个端点持有。一条放行 UDP 500 的防火墙规则,并不能告诉你发生的是哪一种。

动手之前先把记录写下来:对端联系的地址、上游网络如何交付它、接收它的本地接口或逻辑端点,以及应答 IKE 的进程。四行,每一行都可以核查。其中一项未知时,这项未知本身就是设计工作,而不是留待日后敲定的实现细节。等变更申请批准之后才去补这几行,正是转换规则被加到错误设备上的原因。

模式 A:网关持有该地址

在第一种模式里,网关自己持有地址,或者作为现有接口上的辅助地址,或者作为专用接口上的地址,或者作为平台支持的环回隧道端点。这是三种不同功能,配置路径也各不相同;支持其中一种的平台未必支持另外两种。

围绕它设计之前,先确认平台和版本支持这唯一的一种排布。路由块、接口附加地址和环回端点三者不能互换,一个版本的文档也不保证下个版本行为相同。

ip -br addr show
ss -lunp | grep -E ':500|:4500'
sudo tcpdump -ni eth0 'udp port 500 or udp port 4500'

处于监听状态的套接字就是证据。如果该地址上没有任何绑定,那么无论路由表怎么说,网关都不是终结者;抓包会显示数据报不断到达,却没有任何东西应答。

不要把第二个接口放进拓扑中别处已经存在的子网,也不要指望平台会自动理顺。接口子网重叠会造成源地址选择含糊,在很多平台上干脆拒绝配置。

模式 B:上游设备做转换

在第二种模式里,上游防火墙持有专用地址,并把流量转发到另一台 VPN 网关。这是一次带返回路径的目的地址转换;只要按这种方式记录在案,它就是完全成立的设计。

它不是上游设备获得了本地 VPN 套接字的证据。转换只转发报文,并不会把上游那台设备变成 IKE 应答者。一旦上游规则被删除或其返回路径中断,即使网关健康、自身监听完好,VPN 也会停摆。

两个地址都要记录:对端联系的地址,以及网关实际看到的地址。然后记录传输方式和返回路径,因为只对 UDP 500 生效、对封装 ESP 不生效的转换会连上却传不了流量,这种故障日后排查起来相当费解。

身份不是外部地址

IPsec 把隧道端点与它所保护的流量分开,架构把这些决定放在不同位置。改变对端联系的地址,并不会自动改变哪些内部前缀被允许、哪些路由被安装、会话能到达哪些资源。

经过认证的身份又是另一回事。IKEv2 携带的身份载荷与认证交换不必与外层报文地址一致,正因如此,做过转换的设计仍然能够正确认证。

这种独立性很有用,同时也是一个陷阱。两个解析到同一个普通监听者的 DNS 名称不会选中不同的 VPN 后端,而一份只写了一个身份的证书也无法满足期待另一个身份的对端。在假定仅凭地址就能决定之前,先确认对端到底在验证什么。

观察一条连接来验收设计

查清新获授权的连接究竟被投递到哪里、由哪个身份应答、随后允许哪条私有流量。三个观察、三个不同层面,而对地址做一次成功的公开查询一个都验证不了。

反面情形也要保留:不该被接受的对端,或不该可达的内部前缀,在变更之后同样验证一遍。开头写下的那份记录,正是让这项测试不必凭记忆重建设计的前提。

这一切的意义在于,让网络所有者去选择一种受支持的分配方式,而不是依赖「每台防火墙对附加地址都能做什么」这种笼统说法。这种说法恰恰是这些设计出错的地方,因为它在每个平台听起来都合理,总体却在任何一个平台上都不成立。四行记录能在十分钟内为你的平台定论。

相关文章