Reputation: 1175
Background:
I have a custom VPC with 2 private subnets that contain a Postgres RDS instance within the us-west-2 region and a public subnet that contains an EC2 instance within the us-west-2 region.
Private Subnet ACL:
RDS instance security group:
Public Subnet ACL:
Public Subnet has an internet gateway within its route table
EC2 instance security group:
After I SSH into the EC2 instance, I export the environment variables associated with the RDS instance's Postgres credentials (e.g. PGDATABASE=testdb, PGUSER=foo_user, PGHOST=identifier.cluster-foo.us-west-2.rds.amazonaws.com, PGPASSWORD=bar) and run the following python script with python version 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))
I get the following timeout error:
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
Upvotes: 1
Views: 1012
Reputation: 270114
In general, Network Access Control Lists (NACLs) should be left at their default "Allow All Inbound & Outbound" settings unless you have a very specific network requirement (eg creating a DMZ).
NACLs are stateful meaning that they need to permit traffic in both directions. This is different to a Security Group, which is stateless and allows return traffic to go out in response to permitted Inbound traffic. A Security Group could be configured with zero Outbound rules and would still allow users to connect to the resource and receive a response.
The correct security configuration for your scenario should be:
EC2-SG
) that permits inbound SSH access (port 22) from your IP addressDB-SG
) that permits inbound PostgreSQL access (port 5432) from EC2-SG
That is, DB-SG
should specifically reference the EC2-SG
as being permitted for Inbound access. This is the most secure configuration since the database is only reachable from an EC2 instance that is associated with EC2-SG
. If the instance is replaced with another EC2 instance, it will still be able to connect if it is associated with EC2-SG
.
Please note that EC2-SG does not require any Outbound rules in the Security Group since it can automatically respond to any inbound requests. However, it is normally recommended to leave the default Outbound rules in place so that software running on the instance can access the Internet (eg to install the psycopg2 library). Instances can normally be trusted to have Outbound access to the Internet since since you have installed the software yourself.
Upvotes: 1
Reputation: 10185
Have you checked if the VPC's DNS Hostnames are enabled? This is more likely the stemming from the failure to resolve the DNS in the same subnet (Knowing that the security group of the RDS welcomes Postgres traffic from anywhere).
Aside from that, I would also recommend whitelisting the security group of the ec2 + the port of Postgres on the security group of the RDS. You can look at this diagram below:
Upvotes: 1