一台 Azure VPN VM 上放两个公网 IP,往往会产生一种很少成立的预期:客户端连接的地址,也会是网站看到的地址。这个结果由三个彼此独立的决定共同产生,只有第一个与隧道监听有关。第二个是转发客户端流量时使用的来宾源地址,第三个是作用于该源地址的 Azure 出站方式。改动其中一个,另外两个不会跟着变,因此必须逐项明确决定。

决定 1:隧道在哪里终止

Azure 公网 IP 关联的是 NIC 上的一个专用 IP 配置,而不是你在来宾操作系统内部添加的地址。不要靠猜,直接读出映射关系:az network nic show --ids /subscriptions/.../networkInterfaces/vpn-nic --query 'ipConfigurations[].{private:privateIPAddress,public:publicIPAddress.id}'。该查询返回哪个专用地址,来宾实际就必须持有那个地址。

一块 NIC 可以承载多个 IP 配置,所以两个公网地址并不需要两块 NIC。如果设计确实使用两块 NIC,每块都会带来自己的来宾路由和下一跳,你等于增加了一个路由决策,而不是简化了一个。

对于显式绑定本地地址的服务,应绑定来宾真实的专用地址,绝不要绑定公网占位地址。通配监听会通过每一条能够到达它的 IP 配置接收流量,因此应当用网络安全组和主机防火墙来限制入口,而不是指望绑定顺序替你做决定。

决定 2:转发后的客户端使用哪个源地址

网关解密客户端请求之后,它转发的报文与到达 VPN 监听的那个报文并不是同一个。来宾需要开启转发、需要允许该流的防火墙策略,还需要云端设计所允许的源地址。如果你翻译了客户端的内网地址,Azure 评估的就是这个转换后的源地址,而不是客户端的内网地址。

一条范围很窄的 SNAT 规则可以选定来宾的专用源地址,但它无法覆盖下游的 Azure 转换。当需要在 VM 内部按客户端追责时应选择 SNAT;当子网的出站设计已经提供稳定的公网源地址、再做一次转换只会增加状态时,就应放弃它。

决定 3:哪种 Azure 出站方式优先

Microsoft 记录了出站优先级顺序:指向设备或网关的可用路由优先,而在相关路径上,子网的 NAT Gateway 连接优先于实例级公网 IP。正因如此,转换到 10.20.0.5 并不能证明网站会看到 198.51.100.20。在接受出站设计之前,应把生效路由表、NAT Gateway 关联和 NIC 的公网 IP 放在一起读。

把Azure NIC 的转发设置与 Linux 的转发分开对待。云端的标志只允许源或目的未分配给该 NIC 的报文通过;它并不开启 net.ipv4.ip_forward,而来宾侧的设置也不会授予云端权限。

隧道套接字有自己的源地址决策

wg-quick 下 WireGuard 的 Address 是为 WireGuard 接口分配地址,而不是外层 UDP 的绑定指令。加密套接字的源地址遵循路由表,因此一条策略路由或第二条默认路由就能改变它,而不必改动接口地址。OpenVPN的 local 选项与 UDP 的 multihome 行为相同:它们只关乎监听及其回应,不关乎每个被转发客户端的互联网源地址。

保留承载隧道的底层路由,并确认客户端仍能从预期的入口安排收到经过认证的回应。不要把地址列表的顺序当作永久的源地址选择策略,因为下一个添加到 NIC 的地址就可能改变谁胜出。

该接受什么,按什么顺序

分别接受三个结果。第一,外部客户端能够到达预期的 VPN 入口。第二,来自该 VPN 客户端的新许可请求从文档化的互联网出口离开。第三,非预期的监听与转发路径保持拒绝。把公网到私网的映射,以及每项决策的来宾侧与云端责任人,记录在同一个地方。

隧道成功只能证明第一部分。要用新的流测试出口,因为被缓存的连接在路由改变之后很久仍可能继续使用旧源地址。

相关文章