Troubleshooting "AWS RDS Access Denied", "Connection Refused", and Timeouts
Fix AWS RDS connection errors including Access Denied, Connection Refused, and Timeouts. A complete guide to Security Groups, IAM auth, VPC routing, and credent
- Security Groups blocking port access (e.g., 3306, 5432) are the #1 cause of 'Connection Refused' and timeout errors.
- 'Access Denied' usually stems from incorrect IAM Database Authentication policies, expired tokens, or invalid native database user credentials.
- VPC routing issues (missing Internet Gateway, NAT Gateway, or RDS deployed in private subnets) prevent external connectivity resulting in dropped packets.
- Quick Fix: Verify your IP is whitelisted in the RDS Security Group's Inbound Rules and ensure the RDS instance has the 'Publicly Accessible' flag set to Yes if connecting over the internet.
| Method | When to Use | Time | Risk |
|---|---|---|---|
| Modify Security Group | Resolving Network Timeouts / Connection Refused | 2 mins | Low (if scoped strictly to your /32 IP) |
| Enable Public Access & IGW | Fixing External Connection Timeouts | 10 mins | Medium (Exposes DB endpoint to public internet) |
| Fix IAM Auth Policy | Resolving IAM Access Denied (rds-db:connect) | 15 mins | Low (Enhances security by removing passwords) |
| Reset Master Password | Fixing Local Access Denied (ERROR 1045) | 5 mins | Low (Does not require instance reboot) |
Understanding the Errors
When connecting to Amazon Relational Database Service (RDS), you may encounter three primary categories of connectivity issues: Timeouts, Connection Refused, and Access Denied. While they manifest similarly—preventing application functionality—their root causes exist at entirely different layers of the infrastructure stack.
1. Connection Timeouts (Layer 3/4)
Symptom: The connection hangs indefinitely and eventually drops.
MySQL: ERROR 2003 (HY000): Can't connect to MySQL server on 'rds-endpoint' (110)
PostgreSQL: psql: error: connection to server at "rds-endpoint", port 5432 failed: timeout expired
Root Cause: Network traffic is being dropped silently. This is almost always caused by AWS Security Groups lacking inbound rules, Network ACLs (NACLs) dropping traffic, or missing routing infrastructure (like an Internet Gateway for public access or a NAT Gateway/VPC Peering connection for private access).
2. Connection Refused (Layer 4)
Symptom: The connection is actively rejected immediately upon request.
Error: Connection refused or TCP RST flag received.
Root Cause: The network path is clear, but the target port is not listening, or a network appliance is actively rejecting the connection. In RDS, this typically happens if the instance is currently rebooting, undergoing a scaling operation, in an incompatible state, or if the database engine crashed.
3. Access Denied (Layer 7)
Symptom: The network TCP handshake succeeds, but the database software rejects the login attempt.
MySQL: ERROR 1045 (28000): Access denied for user 'admin'@'x.x.x.x' (using password: YES)
PostgreSQL: FATAL: password authentication failed for user "admin"
Root Cause: Incorrect database credentials, expired IAM authentication tokens, or missing database-level grants (e.g., restricted pg_hba.conf equivalent CIDR block rules applied at the database user level).
Step-by-Step Troubleshooting and Resolution
Phase 1: Fixing Timeouts and Network Isolation
If your connection is timing out, start at the network layer. Do not modify database users until the network layer is verified.
1. Verify Security Groups (SGs) Ensure the RDS instance's assigned Security Group allows inbound traffic on the specific database port (3306 for MySQL/MariaDB, 5432 for PostgreSQL, 1433 for SQL Server, 1521 for Oracle) from your specific IP address, CIDR block, or application Security Group ID.
- Fix: Navigate to the RDS Console -> Databases -> Select Instance -> Connectivity & security -> Click the VPC security group link. Add an Inbound Rule for the specific port and your IP (e.g.,
203.0.113.50/32).
2. Check Public Accessibility and Subnets
If you are connecting from outside the AWS VPC (e.g., your local development machine), the RDS instance must have the Publicly Accessible attribute set to Yes.
- Critical Warning: Setting this to 'Yes' is not enough. The RDS instance must also be deployed in Public Subnets. A Public Subnet is defined as a subnet with a Route Table that routes
0.0.0.0/0to an attached Internet Gateway (igw-xxx). If the database is in a private subnet, the public IP will not route traffic.
3. Validate Network ACLs (NACLs) VPC NACLs are stateless firewalls. If you explicitly allow inbound traffic on port 5432, you must also explicitly allow outbound ephemeral ports (1024-65535) for the return traffic. Default AWS NACLs allow all traffic, but custom NACLs implemented by security teams might drop return packets.
Phase 2: Fixing "Access Denied" (Authentication)
If the network is configured correctly (verified via a successful telnet or nc command) but you receive an Access Denied error, the issue resides at the database authentication layer.
1. Native Database Credentials Double-check the username and password strings. If you suspect the master password is lost or compromised, you can reset it safely without causing instance downtime:
- Fix: AWS Console -> RDS -> Modify -> Enter a new Master Password -> Continue -> Select "Apply Immediately". The change takes effect in minutes. Connected sessions are usually not dropped, but new connections will require the new password.
2. IAM Database Authentication Failures When using AWS IAM to authenticate to RDS, you generate a short-lived token (valid for 15 minutes) instead of passing a static password.
- Diagnosis: An error like
FATAL: PAM authentication failed for userusually means the 15-minute token expired, or the IAM user/role lacks the requiredrds-db:connectIAM permission. - Fix: Ensure your IAM policy includes the correct resource ARN structure:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["rds-db:connect"],
"Resource": ["arn:aws:rds-db:us-east-1:123456789012:dbuser:db-ABCDEFGHIJKLMNOP/my_db_user"]
}
]
}
- Additionally, ensure the database user was granted the
rds_iamrole inside PostgreSQL or theAWSAuthenticationPluginin MySQL.
Phase 3: Advanced Diagnostic Tools
Do not guess; verify connectivity empirically using standard Linux utility tools from the source machine.
- Test TCP Handshake: Use
nc -zv <rds-endpoint> <port>to verify if the security group and routing allow the connection. If this succeeds but your application DB client fails, it's an SSL/TLS certificate issue, a driver incompatibility, or an Auth issue. - DNS Resolution: Run
nslookup <rds-endpoint>. If it resolves to a private IP (e.g.,10.x.x.x) but you are outside the VPC, your DNS is working, but you lack VPN/peering network access, or the DBPublicly Accessibleflag is disabled.
Best Practices for Secure RDS Connectivity
- Never use
0.0.0.0/0: Exposing your database to the entire internet is a critical security vulnerability. Always scope Security Groups to specific/32IPs or internal VPC CIDRs. - Use SSM Session Manager: Instead of making RDS public for local development, use an EC2 Bastion host combined with AWS Systems Manager (SSM) port forwarding. This allows secure, private, audited access without exposing port 3306/5432 to the public internet.
- Rotate Secrets: Use AWS Secrets Manager to automatically rotate native database credentials, or exclusively use IAM DB Authentication to avoid handling long-lived static passwords entirely.
Frequently Asked Questions
# 1. Test Network Connectivity (Layer 4)
# If this hangs, you have a Security Group or VPC Routing issue.
nc -zv my-database.cluster-xyz.us-east-1.rds.amazonaws.com 5432
# 2. Generate an IAM Auth Token for RDS (Valid for 15 mins)
export RDSHOST="my-database.cluster-xyz.us-east-1.rds.amazonaws.com"
export TOKEN=$(aws rds generate-db-auth-token \
--hostname $RDSHOST \
--port 5432 \
--region us-east-1 \
--username my_iam_db_user)
# 3. Connect using the generated token (PostgreSQL example)
# Note: Enclose TOKEN in quotes or export as PGPASSWORD to handle special characters
PGPASSWORD="$TOKEN" psql -h $RDSHOST -p 5432 -U my_iam_db_user -d my_database
# 4. Secure Local Port Forwarding via AWS SSM (Bastionless access to Private RDS)
# Forwards local port 5432 through an EC2 instance to the RDS instance
aws ssm start-session \
--target i-0abcd1234efgh5678 \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["my-private-rds.xyz.us-east-1.rds.amazonaws.com"],"portNumber":["5432"], "localPortNumber":["5432"]}'Error Medic Editorial
A collective of senior Site Reliability Engineers and Cloud Architects dedicated to solving complex infrastructure, networking, and database connectivity challenges.
Sources
- https://repost.aws/knowledge-center/rds-connectivity-instance-subnet-vpc
- https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Troubleshooting.html
- https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.Connecting.html
- https://stackoverflow.com/questions/14637510/aws-rds-mysql-connection-timeout