从办公网络经站点 VPN 访问 S3,并不是一条静态路由就能独自解决的路由问题。网关端点挂在路由表上,只服务 VPC 内部发起的请求。接口端点在你选择的子网中放置带私有地址的弹性网络接口,这些地址可以从本地经 VPN 或 Direct Connect 访问。请求从哪里发起,决定了你实际需要哪一种;DNS、安全组与策略的工作都由此而来。

按请求的发起位置区分两类端点

网关端点在路由表中表现为指向托管前缀列表的一条记录。它没有网络接口、没有安全组,也没有自己的私有地址,正因如此,本地主机无法向它路由:另一侧没有任何可供路由的对象。来自 VPC 内部的流量能到达 S3,是因为子网路由表把该前缀发往端点。来自其他任何位置的流量都没有这样的记录可循。

接口端点是你所选子网中的一组网络接口,每个接口都带有该子网的私有地址,并挂载了安全组。这正是混合客户端可以使用的形态,因为它是一个普通目标,隧道可以把数据包送到那里。这也意味着端点会消耗子网中的地址,并且可能被耗尽。

aws ec2 describe-vpc-endpoints --query "VpcEndpoints[].{Id:VpcEndpointId,Type:VpcEndpointType,Service:ServiceName,State:State}" --output table

要看 Type 列,而不是看名字。同一个 VPC 常常同时保存同一服务的两种端点,而本地应用需要的是接口那一条。

在测试 S3 之前,先打通到接口地址的路径

三件事必须同时成立:本地路由器有通往端点子网的路由,该子网的返回路径能到客户端网络,端点的安全组允许客户端的源地址范围。三者都满足之后,子网的网络 ACL 仍可能丢包,所以要把它当作第四项来查,而不是事后再想。

到 VPC 内某台 EC2 实例的路径能用,并不能证明上面任何一项。它只说明隧道是通的,而那正是你本来就知道的那一段。请单独验证端点地址,再验证名称是否解析到它。

ip route get 10.60.4.37
nc -vz 10.60.4.37 443
openssl s_client -connect 10.60.4.37:443 -servername bucket.vpce-0123456789abcdef0-abc123.s3.us-east-1.vpce.amazonaws.com </dev/null

第一条命令显示客户端会走哪个接口。第二条证明 TCP 握手完成。第三条证明 TLS 以对端点名称有效的证书完成,正是这项检查在你归咎权限之前抓住了错误地址。

确定应用最终拿到哪个 DNS 答案

VPC 里存在接口端点,并不会自动让本地 SDK 改道。客户端要么使用 AWS 为该端点发布的端点专用名称,要么使用你特意做成可从办公室解析的私有托管区。

要做混合解析,本地解析器需要一条受支持的路径进入 VPC 的 DNS 视图,通常经由 Resolver 入站端点。在没弄清它会影响哪些查询来源之前就打开私有 DNS,正是查询开始返回办公室到不了的地址的原因。这个设置改变的是经 VPC 解析器到达的查询答案,而不是所有地方的所有客户端。

dig +short bucket.vpce-0123456789abcdef0-abc123.s3.us-east-1.vpce.amazonaws.com
aws s3api head-bucket --bucket example-artifacts --endpoint-url https://bucket.vpce-0123456789abcdef0-abc123.s3.us-east-1.vpce.amazonaws.com

两条命令都要在应用主机上跑,不要在 VPC 里的跳板机上跑。在那里应答的解析器才是工作负载实际使用的那个,而从另一台主机得到不同答案,是这套设计里最常见的困惑来源。

可达不等于授权

到达端点的请求仍然需要被授权的主体和适用的桶权限。端点策略可以收窄端点允许的范围,桶策略可以再收窄一层。能连上接口,并不说明调用方可以读哪些对象。

两个方向都要测:一次对目标桶的无害授权调用,以及一次针对策略之外的身份或资源、预期会被拒绝的调用。把端点名称、解析出的地址和策略背景与结果一起留存,下一个人才能复现。一次点名策略类型的拒绝,能省下一小时的猜测。

最后,在开通之前先把两种方案的价钱算清楚。接口端点按接口小时和每 GB 计费,网关端点则不计这两项;对许多只需要 VPC 侧访问的低流量工作负载来说,这个差别就是决定性的。

相关文章