一名用户连接后打开内部应用并得到响应;同一终端节点上的同事用同一 Wi-Fi 下型号相同的笔记本却超时。这种模式正是关联了多个子网的 client VPN 终端节点的特征,此时各条路径并不等价。我从控制台向外逐层排查,因为两个标签页就决定了后续调查是否值得做。客户端配置里没有任何东西能解释它。

从终端节点开始,列出关联

在 VPC 控制台打开 Client VPN endpoints,选中终端节点并读取 Associations 标签页。每个关联都是某个可用区里的一个子网,建立连接时服务选中哪个子网,客户端就落在哪个子网上。记下子网 ID 以及各自实际使用的路由表,因为这两份清单就是你接下来要做的对比。

如果终端节点只显示一个关联,这个推论就不成立,客户端才是更值得怀疑的对象。

把终端节点的路由表与每个关联逐一对比

在同一终端节点上打开 Route table 标签页。其中每个目标 CIDR 都有一个目标对象,而在 client VPN 里目标对象是关联而不是网关。AWS 要求为每个关联子网提供目标条目,所以只指向其中一个关联的路由会让访问取决于会话落在哪里。检查你真正关心的目标,再检查它的授权规则,因为路由只提供路径,规则决定谁可以使用它。

把两层都列成表之后,故障就很难被忽略。

Associated subnetEndpoint route to 10.200.0.0/16VPC route in that subnet
subnet-aaaTargets the association10.200.0.0/16 to pcx-example
subnet-bbbTargets the associationNo matching entry

多数工单里,第二行就是问题全部。终端节点的路由存在,于是没人再往下看,而数据包在下一跳就死在 VPC 内部。

顺着每个子网查它实际生效的路由表

没有显式关联路由表的子网会继承 VPC 的主路由表。要读真正生效的那张表,而不是名字看起来对的那张,并比较目标与目标对象,而不是行上的标签。

AWS 的 间歇性访问指南 把这件事描述为跨关联的路由覆盖,这个模型是正确的。终端节点把数据包送到子网,而该子网的路由表仍然必须知道应用网络在哪里。

在拥有该表的那张路由表里补上缺失的行。从正常子网整表复制,会把从未打算给这个子网使用的互联网、设备和隔离选择一并复制过来,这种交换通常比最初的故障更糟。

再检查授权规则,然后看回程路径

授权规则按目标、按组分别生效,并与路由分开评估。一个处处有路由、却没有针对用户所在组的规则的目标,表现得就像黑洞,尽管路由表看起来健康。

回程路径同样值得关注。peering 连接需要在应用 VPC 里有指回客户端 CIDR 的路由,需要在两端都放行流量的安全组规则,以及不能丢弃它的网络 ACL。单向可达、也就是 ping 能通但 TCP 握手不通,通常指向 ACL 或安全组,而不是 VPN。

终端节点自身的安全组挂在关联的弹性网络接口上,因此允许来自客户端 CIDR 访问应用端口的那条规则必须绑在关联上,而不只是绑在实例上。

用重新连接来验证,而不是靠一次侥幸的请求

在 split tunnel 下,终端节点路由在连接建立时下发,所以改变后的路由集合永远不会到达保持连接的客户端。用受支持的客户端断开再重连,然后确认新路由已经出现在机器上。

最后,把连接日志与客户端拿到的地址对上,并重复测试足够多次,以命中不止一个关联。修好之后一次成功的请求只能证明一条路径可用,而工单说的是另一条。

相关文章