I’ve been using AWS services like EC2 and RDS under the free tier and recently started incurring charges due to the use of public IP addresses. AWS provides one free public IP, but my RDS instance had another public IP attached — and that’s where the billing began.

AWS Billing Screenshot – Public IP Charges AWS billing showing charges for additional public IPv4 addresses.

A better, more secure, and cost-effective solution is to keep your RDS private within a VPC and connect to it via a method called SSH tunneling through a bastion host.

Below, I’ll explain what that means and how you can set it up.


🔁 What is SSH Tunneling?

SSH tunneling (port forwarding) is a method of transporting network data over an encrypted SSH connection. SSH is a standard protocol for secure remote logins and file transfers over untrusted networks.

It also provides a way to secure data for any given application using port forwarding — the data flows through an encrypted SSH connection, making it safe from interception. This is especially useful when you need to connect to a private network (one without a public IP) via a bastion host, such as in production or secure VPC environments.


🧱 What is a Bastion Host?

A bastion host is a public-facing machine that acts as a gateway between your local computer and private infrastructure. It allows you to connect securely to private resources without exposing them directly to the internet.

In our case, an EC2 instance serves as the bastion host that connects to an RDS instance located in a private subnet.


🛠️ Example Setup

Let’s say we have the following:

SSH Tunneling Architecture – Bastion Host to Private RDS Secure access to a private RDS through a Bastion Host using SSH tunneling.

Component Example
Bastion Host (EC2) 3.25.100.100 (public IP)
RDS Endpoint mydb.databsexxx.rds.amazonaws.com (private)
RDS Port 3306
Local Port 3307
SSH Key key.pem
User ec2-user

💡 Note: The EC2 instance must be allowed to connect to the RDS instance. In your RDS setup, make sure the EC2’s security group is authorized for inbound access.


🔐 SSH Command

ssh -i /path/to/key.pem -L 3307:mydb.databsexxx.rds.amazonaws.com:3306 ec2-user@3.25.100.100

This command does the following:

  • Connects to the bastion EC2 instance
  • Forwards your local port 3307 to the RDS instance’s port 3306
  • Allows your local database client to communicate with the private RDS as if it were running locally

💻 Connect from a Database Client

Once the SSH tunnel is active, open your preferred database client (like MySQL Workbench, DBeaver, or Beekeeper Studio) and use:

Host: 127.0.0.1
Port: 3307
Username/Password: Your RDS credentials
Database Name: <your_db_name>

That’s it! You’re now securely connected to a private RDS instance.


🎯 Benefits

  • No need to expose RDS publicly (better security)
  • Avoids unnecessary billing for Elastic IPs
  • Follows DevOps best practices for accessing private cloud resources

📌 Bonus Tip: Simplify with SSH Config

You can avoid typing the full SSH command every time by adding this to your ~/.ssh/config file:

Host my-bastion
    HostName 3.25.100.100
    User ec2-user
    IdentityFile ~/path/to/key.pem
    LocalForward 3307 mydb.databsexxx.rds.amazonaws.com:3306

Then just run:

ssh my-bastion

🔚 Conclusion

If you want to make your infrastrucure more secure and decrease the cost, the should keep your database with a private subnet and attach it to the ec2 instance. To connect to sql clients you can use a bastion host and SSH tunneling to access your database securely