RDS instances can become accessible from anywhere on the internet if not properly configured, creating a significant security risk.
Let’s see this in action with a concrete example. Imagine you have an RDS PostgreSQL instance. By default, if you don’t specify a VPC and security group, it might get a public IP and be accessible from the internet. This is bad. What we want is to restrict access so only specific applications or servers within our VPC can connect.
Here’s how to set up an RDS instance to be only accessible from within your VPC.
First, when you create your RDS instance, you must select a VPC. If you don’t specify a VPC, RDS will create one for you, which is generally not what you want for granular control. You’ll also need to select a DB Subnet Group. This group defines which subnets within your VPC your RDS instance can reside in. For high availability, this should span multiple Availability Zones.
Crucially, you need to assign a Security Group to your RDS instance. This is where the network access control happens. Let’s say your application servers are running on EC2 instances within the same VPC.
Example Scenario:
- RDS Instance:
my-pg-instance(PostgreSQL, port 5432) - VPC:
vpc-0123456789abcdef0 - Application EC2 Instances: In a subnet with a specific CIDR block, e.g.,
10.0.1.0/24. - RDS Security Group:
sg-abcdef0123456789
Steps to Restrict Access:
-
Create a Security Group for your RDS instance:
- Go to the EC2 console -> Security Groups -> Create security group.
- Name:
rds-access-sg - Description: "Allow access to RDS from application servers."
- VPC: Select your VPC (e.g.,
vpc-0123456789abcdef0).
-
Add an Inbound Rule to
rds-access-sg:-
Select
rds-access-sg. -
Under "Inbound rules," click "Edit inbound rules."
-
Click "Add rule."
-
Type:
PostgreSQL(this automatically sets the protocol to TCP and port to 5432). -
Source: This is the critical part. Instead of
0.0.0.0/0(which means "anywhere"), you want to specify the source of your application servers.- Option A (Recommended): Security Group of your App Servers. If your application servers are in EC2 instances, and they have their own security group (let’s call it
app-servers-sg), you can selectCustomfor the source and then typeapp-servers-sgin the box. AWS will resolve this to the CIDR block(s) associated with that security group. This is dynamic; if your app server IPs change, access is maintained. - Option B: CIDR Block of your App Subnet. If you know the specific subnet CIDR where your application servers reside (e.g.,
10.0.1.0/24), you can enter that here.
- Option A (Recommended): Security Group of your App Servers. If your application servers are in EC2 instances, and they have their own security group (let’s call it
-
Click "Save rules."
-
-
Modify your RDS Instance (or create a new one):
- If your RDS instance already exists, go to RDS -> Databases -> select your instance -> "Modify."
- Scroll down to "Network & Security."
- VPC Security Groups: Ensure your
rds-access-sgis selected here. If there are other security groups, ensure they are either removed or also configured to allow traffic from your application sources. For maximum restriction,rds-access-sgshould be the only one, or the only one with inbound rules allowing your app servers. - Publicly accessible: Make sure this is set to
No. - Click "Continue" and then "Apply immediately" (or schedule for a maintenance window).
Why this works:
Security Groups act as a virtual firewall for your RDS instance. By default, they deny all inbound traffic. You explicitly grant permission for traffic on specific ports (like PostgreSQL’s 5432) only from specified sources. By setting the source to another security group or a private IP range within your VPC, you ensure that only resources within your trusted network can initiate a connection to your database. Setting "Publicly accessible" to No prevents RDS from assigning a public IP address, further isolating it.
The Mental Model:
Think of your VPC as a private network. Your RDS instance lives inside this private network. Security Groups are like guards at the doors of your RDS instance. You configure these guards to only let people (network traffic) in if they are coming from a specific location (another security group or IP range) and on a specific errand (the correct port and protocol).
The "Levers" you control:
- VPC: The overall private network boundary.
- DB Subnet Group: Which parts of your VPC are candidates for hosting the RDS instance.
- Publicly Accessible: Whether the instance gets a public IP. Always
Nofor private access. - Security Groups: The granular inbound/outbound traffic rules.
- Inbound Rules: Who can connect to the RDS instance.
- Outbound Rules: Who the RDS instance can connect to (less common for basic RDS access control, but relevant if your RDS needs to reach other services).
- Source IP/Security Group: The specific origin allowed by an inbound rule.
One commonly overlooked detail is that when you specify a security group as the source for an inbound rule, it applies to all EC2 instances/resources associated with that source security group, regardless of their specific private IP addresses. This is a powerful feature for managing access dynamically.
If you’ve followed these steps and your application still can’t connect, the next error you’ll likely encounter is a timeout, indicating that traffic is being blocked somewhere along the path, most likely by an incorrect security group rule or a NACL issue.