Skip to main content

Port Forwarding your private AWS RDS Instance

·3 mins

In the last post we’ve explored how to connect to EC2 via SSM from our local terminal. Now, most of the time developers don’t want the hassle of using the Linux terminal to access the private resource, they actually want to work with.

In this post we’ll go through a practical scenario developers are facing every day: Suppose you want to directly access your AWS RDS PostgreSQL instance in a private subnet with a tool like pgAdmin. We’ll achieve this by by adding local port forwarding via SSH to our configuration.

Prerequisites #

Configuring the SSH-Tunnel with Forwarding #

In the last post we’ve configured a SSH connection hinging mainly on the ProxyCommand, utilizing the aws cli ssm plugin. This time we’ll be adding a Localforward directive to forward a port from another private resource to our local machine.

Open your local SHH config (~/.ssh/config) and add a configuration block for your new connection:

Host rds-tunnel
  User ec2-user
  Localforward 5432 rds-postgresql.XXXXXXXXXXXXXX.eu-central-1.rds.amazonaws.com:5432
  IdentityFile ~/.ssh/id_rsa
  RequestTTY no
  ProxyCommand sh -c "aws ssm start-session --target i-XXXXXXXXXXXXXXXX --region eu-central-1 --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
Make sure, that your RDS instance is actually reachable from your EC2 bastion host. This means you need to properly configure your security groups, NACLs or routing tables on the subnet level. For general troubleshooting grab a helping hand from AWS: https://aws.amazon.com/premiumsupport/knowledge-center/rds-cannot-connect/

The Host rds-tunnel names the host we connect to later via SSH. User defines the linux user ec2-user on the bastion host we’re using to hop through to RDS. Obviously, if you want to connect via a different user, configure it accordingly. The IdentityFile sets the path to the private key. ProxyCommand calls the SSM plugin: it starts a port forwarding session with the instance id of the target bastion host. The actual tunneling is configured via Localforward: You can forward services from private subnets, e.g. the AWS RDS endpoint.

If you set up everything correctly, you can start the SSH-Tunnel over SSM with the command:

ssh rds-tunnel

The session starts, the port 5432 gets locally forwarded to 5432 as defined in the Localforward line in the SSH config. Important: You have to leave this terminal window open and running while connecting to your database.

Configuring your Connection #

First you have to retrieve the correct credentials for your database connection. Any connection in GUI/CLI applications can be set up with the following parameters; notice the forwarded port from the SSH config:

Host: localhost (127.0.0.1)
Port: 5432

So you’ll be connecting to localhost:5432 with your set up username and password from RDS. In pgAdmin configure your connection accordingly (password can be saved after connecting once):

pgAdmin
If you’re more inclined to use the psql cli tool, your connection string would something like this:

psql -h 127.0.0.1 -p 5432 -U admin-user -d database-name

And if everything is set up correctly, you should successfully connect to your private RDS instance 🎉.