隧道失败,安全组已经允许全部流量,结论是 AWS 封禁了 VPN。它什么也没封禁。托管 NAT 网关只转发一组有文档记录的外层协议,原生 GRE 或原生 ESP 不在其中,因此无论你添加什么规则,网关都不会携带它们。允许规则和传输能力是两回事,其中只有一件是你能够改变的。

规则集不是协议集

安全组决定哪些流量可以离开实例。NAT 网关决定它能够转换和转发什么。当第二重限制生效时,宽松规则产生的正是人们误读为防火墙问题的症状:数据包离开实例,控制交换甚至可能完成,而对端什么也没收到。

AWS 的NAT 网关协议规范列出了托管服务所支持的 TCP、UDP 和 ICMP。这就是全部受支持的集合。为另一种 IP 协议添加允许规则无法扩展它,因为规则在到达网关转发路径之前很久就被评估了。

这一区别很重要,因为两种故障从客户端看完全相同,修复方法却截然不同。

PPTP 说明了端口测试为何会撒谎

PPTP 是端口检查什么也证明不了的、最清楚的旧例。它在 1723 端口打开 TCP 控制连接,然后通过 GRE 承载隧道数据,而 GRE 是 IP 协议 47。协议 47 不是 TCP 端口 47,这两个数字除了共用数字之外毫无关系。

运维人员测试到 1723 的连通性并看到握手完成后,会断定路径可用。随后数据通道连一个包都过不去,因为网关没有可提供的 GRE 支持。这是对旧协议要求的解读,而不是部署 PPTP 的建议,后者早已过时多年。

同样的推理适用于任何控制通道是 TCP 或 UDP、而数据路径不是的协议。

IPsec 只能以 UDP 形式存活

IPsec 是答案有条件、而非一概否定的情形。AWS 把 NAT 穿越记录为通过 NAT 网关使用 IPsec 的受支持安排。协商 NAT-T 后,ESP 被封装在 UDP 中,网关看到的是普通 UDP,而不是协议 50。

允许 UDP 4500 并不会让端点使用 NAT 穿越。它只允许已经是那种形态的数据包。从客户端自身的协商输出确认选择了哪种封装,并在接收侧确认对端接受了它。配置为原生 ESP 的两个端点会继续发送原生 ESP,无论规则集怎么说。

基于 TCP 或 UDP 的 VPN 符合有文档记录的传输集合,仍可能因路由、过滤或认证而失败。符合集合是必要条件,不是充分条件。

扩大策略之前先检查路径

先核实工作负载子网的实际路由和 其下一跳的身份。直接公网路径、NAT 实例、托管 NAT 网关,以及经中转网关的私有路径,是四种不同设计,其中只有一种是本文描述的托管服务。

然后记录尝试过的端点、地址族、外层协议,以及协议有端口时的端口号。使用客户端诊断和网络所有者的流观察,而不是一次成功的浏览器请求,后者只能证明 TCP 和 UDP 可用。之后,针对流量的两个方向检查安全组、子网 ACL、来宾防火墙和服务策略。

不要为了补偿服务无法携带的传输而开放全部流量。改规则不会解决问题,而且它会比事故活得更久。

当传输不合适时

如果外层协议在受支持集合之外,解决办法是架构层面的:选择路径能够携带的传输,或者把出口移到能携带你所需协议的地方。OpenVPN的 UDP 版本、WireGuard 的 UDP 版本以及基于 TLS 的隧道,都符合有文档记录的集合。当某个特定协议必须通过、且运行它的运维成本可以接受时,客户自管的 NAT 实例就是选项。

托管入站 VPN 服务器是另一个问题,有另一个答案。NAT 网关提供出站转换,不提供通用的入站端口转发,因此其后的服务器需要按自身条件设计并获得批准的公共入口。

工作顺序:说出外层协议,确认下一跳,与有文档记录的集合比较,然后改变架构或传输。换一个端口号不能把 GRE 变成 TCP,多加一条宽松规则也不能把完成的控制交换变成可用的数据通道。

相关文章