从 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:
- 允许端口 5432 上的所有入站 IPv4 流量
RDS实例安全组:
- 允许端口 5432 上的所有入站 IPv4 流量
Public 子网 ACL:
- 允许所有端口上的所有 inbound/outbound 流量
Public 子网在其路由中有一个互联网网关 table
EC2 实例安全组:
- 允许端口 22 上来自本地 IP 的入站 SSH 流量
- 允许端口 5432、443 和 80 上的所有 IPv4 出站流量
在我通过 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 的出站访问权限。
背景:
我有一个自定义 VPC,它有 2 个私有子网,其中包含 us-west-2 区域内的 Postgres RDS 实例和 public 子网,其中包含 us-west-2 区域内的 EC2 实例。
私有子网 ACL:
- 允许端口 5432 上的所有入站 IPv4 流量
RDS实例安全组:
- 允许端口 5432 上的所有入站 IPv4 流量
Public 子网 ACL:
- 允许所有端口上的所有 inbound/outbound 流量
Public 子网在其路由中有一个互联网网关 table
EC2 实例安全组:
- 允许端口 22 上来自本地 IP 的入站 SSH 流量
- 允许端口 5432、443 和 80 上的所有 IPv4 出站流量
在我通过 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 的出站访问权限。