VPN 终结在一台 EC2 实例上,你能连到该实例的隧道地址,可本该经它转发到另一台私有主机的流量却消失了。这是两个不同的测试,混为一谈会白白浪费几个小时。第一个测试问的是你能否到达该实例;第二个测试要求它为一个并不属于自己的目标转发流量,这需要 Linux 转发、防火墙策略、远端的路由,以及一项与客体操作系统毫无关系的 AWS 层权限。控制台里没有任何地方提示这层差别。症状看起来像路由故障,通常却并不是。

动手之前先把两个测试分开

能到达网关只证明了隧道、到其地址的路由,以及放行这次交互的安全组。为另一台主机转发则什么都证明不了:它用的是不同的源地址、不同的目标,以及一台未必为此而建的实例。把两个测试分开写下来,并记下哪一个失败,因为两者的修正分别在不同的控制台里。只为终结隧道而建的网关实例没有理由替别的目标转发,它的默认配置也正体现了这一点。所以第二个测试需要自己的一套配置,而不是在第一个上做点小调整。

能 ping 通网关、却 ping 不通网关后面的主机,不是时有时无的故障。那是一个从未被告知可以转发的实例的正常表现。

碰任何设置之前,先把路径写下来

记录客户端前缀、承担转发的实例或网卡、目标子网和回程路由。VPC 路由表里指向某台实例的条目,并不会把那台实例的操作系统配置成转发;客体内核即便开了转发,也不会创建 VPC 路由。这段关系的两端都必须存在,而 它们由权限不同的人在不同地方分别编辑。

然后检查真正承担转发的那台组件上的源/目标检查设置,而不是 VPC 里的每一台实例。AWS 的文档说明了为什么替他人转发的实例必须关闭这项检查,也说明了为什么这是逐实例的决定,而不是整个 VPC 的默认值。

四道边界,而检查只是其中一道

把这条路径当成四个问题,按顺序回答。第一个失败的答案就是问题所在,其余任何一道都补不回来。

BoundaryQuestion it answers
VPC route tablesDo the destinations and replies select the intended gateway?
Forwarding instanceDo the AWS check and the guest OS both permit forwarding?
Access policyDo security groups, ACLs and host rules allow the exchange?
DestinationCan the service accept that source and return a reply?

顺序重要,因为检查很便宜:路由一页就能看完,检查只是一个属性,而目标的意见通常是最后才被问到的。

转换会改变目标看到的源

路由式设计保留客户端的源地址,因此目标需要一条回到客户端前缀的回程路由。转换式设计则呈现网关的地址,这去掉了那项要求,代之以网关上的状态表。请按你真正打算采用的架构来决定,而不是因为某个无关的例子用了它就以为可以照搬。

如果你做转换,就把规则限定在客户端前缀和预期目标上。如果你保留源地址,就确认远端确实知道这条路由,而不是假定它自己会学到。

从原始客户端测试,然后把改动保留下来

在网关上发出的请求可能成功,而转发来的请求却失败,因为源不同、转发情形也不同。做过针对性修正之后,用同一个客户端重做那个失败的确切测试,并确认回包真的回来了,而不只是请求到达了。

最后,把设置放进网关的受管配置里,让替换出来的实例也能拿到。依赖手工例外的成功测试,会在下一次重建时失效,而当初发现它的人不会在那儿记得为什么。

相关文章