Home > front end >  Connect to RDS instance from Ec2 instance within VPC
Connect to RDS instance from Ec2 instance within VPC

Time:01-26

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:

  • Allow all inbound IPv4 traffic on port 5432

RDS instance security group:

  • Allow all inbound IPv4 traffic on port 5432

Public Subnet ACL:

  • Allow all inbound/outbound traffic on all ports

Public Subnet has an internet gateway within its route table

EC2 instance security group:

  • Allow inbound SSH traffic from my local IP on port 22
  • Allow all IPv4 outbound traffic on ports 5432, 443, and 80

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

CodePudding user response:

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:

enter image description here

CodePudding user response:

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:

  • A Security Group on the Amazon EC2 instance (EC2-SG) that permits inbound SSH access (port 22) from your IP address
  • A Security Group on the Amazon RDS database (DB-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.

  •  Tags:  
  • Related