开发者的笔记本连接私有 RDS 终端节点时超时,而同样的凭据从堡垒机可以正常工作。没有任何服务宕机。笔记本与数据库之间的链路上缺了三样东西之一:能解析的名字、承载流量的路由,或允许数据库真正看到的源地址的安全组规则。先弄清缺的是哪一样,再去改另外两样。

在正确的层上读故障

超时并不是单一错误。名字解析不了,会在数据包离开本机之前就失败。地址没有路由,数据包就会掉进黑洞。端口被过滤,表现出的等待与主机写错一模一样。按顺序执行这些步骤,在第一个失败处停下。

dig +short db.internal.example
nc -vz db.internal.example 5432

如果名字返回公网地址,或者什么也不返回,那隧道还不是问题所在。

如果名字能解析而端口测试卡住,就把解析到的地址与数据库报告的地址对比。托管终端节点在 VPC 内可能解析为私有地址,在 VPC 外则解析不出有用的东西;而从旧查询里抄来的地址,会指向一台已经不再响应的主机。

把隧道和路由分开

连接客户端 VPN 并不会自动为所有私有网段添加路由。配置文件只携带服务下发的路由,客户端可能只安装其中一部分。看看客户端实际加了哪些网段,以及数据库地址是否落在其中之一。

ip route get 10.20.40.15
ip addr show tun0

指向隧道接口的路由是必要条件,但并不充分,因为对端还必须接受这些流量。

分离隧道配置是这种半截故障的常见来源。它对配置所针对的应用有效,却把数据库网段留在隧道之外,于是产生了和防火墙一模一样的超时。

让安全组匹配真实源

RDS 安全组放行的是源地址,不是人。取决于架构,源可能是 VPN 客户端地址池、堡垒机的私有地址,或流量经 NAT 转换后的地址。要把规则和实际的数据包源放在一起读。

aws ec2 describe-security-groups --group-ids sg-0123456789abcdef0 \
  --query 'SecurityGroups[].IpPermissions'

为某一台笔记本的家庭地址单独开规则,是维护负担,而不是访问设计。

当链路中夹着客户端 VPN 或 NAT 网关时,数据库看到的可能是转换器的地址,而不是开发者的隧道地址。这就是为什么从可用的堡垒机配置里抄来的规则,换到笔记本上会失败:两条路径来自不同的源,尽管看起来都是内网。

宁要窄路,不要宽路

当一位开发者只需要一个数据库时,基于会话的转发往往比完整的网络隧道更省运维成本。本地客户端连接转发端口,由远端组件从网络内部发起数据库连接。

ssh -N -L 5432:db.internal.example:5432 bastion.internal.example

这种设计里要保留 TLS 校验。客户端仍应按自己期望的名字校验证书;本地转发端口不是关闭校验的理由,关掉它恰好会掩盖值得抓出来的身份问题。

在完整隧道与窄转发之间做选择,是范围问题,不是安全表演。

留下可复现的路径

记录终端节点的名字而不是解析后的地址,记录安全组放行的源网段,以及开发者使用的数据库角色。这三件事能解释今后大多数故障,无需打电话。还要记下客户端配置的版本,因为配置变更可能删掉旧版本携带的路由。

然后测一次反向情况:不在允许源范围内的客户端,仍然应该被拒绝。

只对配置者本人可用的私有数据库不算私有访问,而是一个等待被重新发现的未记录例外。把路径写下来,下一位开发者继承的就是方法,而不是谜团。

相关文章