从 VPC 中的 Ec2 实例连接到 RDS 实例

Connect to RDS instance from Ec2 instance within VPC

背景:

我有一个自定义 VPC,它有 2 个私有子网,其中包含 us-west-2 区域内的 Postgres RDS 实例和 public 子网,其中包含 us-west-2 区域内的 EC2 实例。

私有子网 ACL:

RDS实例安全组:

Public 子网 ACL:

Public 子网在其路由中有一个互联网网关 table

EC2 实例安全组:

在我通过 SSH 连接到 EC2 实例后,我导出了与 RDS 实例的 Postgres 凭证关联的环境变量(例如 PGDATABASE=testdb、PGUSER=foo_user、PGHOST=identifier.cluster-foo.us-west-2.rds.amazonaws.com, PGPASSWORD=bar) 和 运行 以下 python 脚本 python 版本 3.7.10:

import psycopg2

try:
    conn = psycopg2.connect(connect_timeout=10)
    cur = conn.cursor()
    cur.execute("""SELECT now()""")
    query_results = cur.fetchall()
    print(query_results)
except Exception as e:
    print("Database connection failed due to {}".format(e))    

我收到以下超时错误:

Database connection failed due to connection to server at "foo-endpoint" (10.0.102.128), port 5432 failed: timeout expired
connection to server at "foo-endpoint (10.0.101.194), port 5432 failed: timeout expired

您检查过是否启用了 VPC 的 DNS 主机名?这更有可能是由于无法解析同一子网中的 DNS(知道 RDS 的安全组欢迎来自任何地方的 Postgres 流量)。

除此之外,我还建议在 RDS 的安全组上将 ec2 的安全组 + Postgres 的端口列入白名单。你可以看看下面这张图:

一般而言,网络访问控制列表 (NACL) 应保留其默认的“允许所有入站和出站”设置,除非您有非常具体的网络要求(例如创建 DMZ)。

NACL 是有状态的,这意味着它们需要允许双向流量。这与安全组不同,后者是 无状态 并允许 return 流量发出以响应允许的入站流量。安全组可以配置为零出站规则,并且仍然允许用户连接到资源并接收响应。

您的场景的正确安全配置应该是:

  • Amazon EC2 实例 (EC2-SG) 上的安全组允许从您的 IP 地址进行入站 SSH 访问(端口 22)
  • Amazon RDS 数据库 (DB-SG) 上的一个安全组,允许来自 EC2-SG
  • 的入站 PostgreSQL 访问(端口 5432)

即,DB-SG 应明确引用 EC2-SG 允许入站访问。这是最安全的配置,因为数据库只能从与 EC2-SG 关联的 EC2 实例访问。如果该实例被另一个 EC2 实例替换,如果它与 EC2-SG.

相关联,它仍然能够连接

请注意,EC2-SG 不需要安全组中的任何出站规则,因为它可以自动响应任何入站请求。但是,通常建议 保留默认的出站规则 以便实例上的软件 运行 可以访问 Internet(例如安装 psycopg2 库)。由于您自己安装了该软件,因此通常可以信任实例具有对 Internet 的出站访问权限。