TIL

Connecting to private resources at AWS

Let's say you need to connect to an AWS RDS Postgres database in a private subnet. If you have an EC2 instance or ECS task with execute command enabled, you can create a reverse tunnel to it and connect to the database through that.

# For EC2 instance
TARGET=$(aws ec2 describe-instances \
    --filters "Name=tag:Name,Values=my-ec2-name" \
     --query "Reservations[0].Instances[0].InstanceId" \
     --output text)
# For ECS task
TARGET=$(aws ecs list-tasks \
    --cluster my-cluster \
    --service-name my-service \
    --query "taskArns[0]" \
    --output text)

aws ssm start-session \
  --target "$TARGET" \
  --document-name AWS-StartPortForwardingSessionToRemoteHost \
  --parameters '{"portNumber":["5432"], "localPortNumber": ["5432"], "host": ["yourdb.cluster-ro-xxxxxxxxxxxx.us-west-2.rds.amazonaws.com"]}'

Now let's say you want to connect to that database from a virtual machine or Docker container that doesn't have access to the host's localhost. You can use socat to forward the port to 0.0.0.0 and connect to that.

socat TCP-LISTEN:25432,fork,reuseaddr TCP:localhost:5432

In this example, you could connect to the database at yourhost:25432.