While port forwarding using AWS System Manager Session Manager is trivial if you need to forward traffic to a service running on the remote host you connect to, things become more complicated as soon as you need to take an extra hop.
A good example where you need an extra hop is when you start an SSM Session Manager tunnel on your local machine to access an RDS database running privately on AWS. To achieve this, you will need something to forward traffic from the remote EC2 instance to the managed service. To take this extra hurdle I use socat.
Use socat (SOcket CAT) for port forwarding on the remote host
To install and run socat on the remote EC2 instance you need to establish a secure connection with the host first. I highly recommend AWS Session Manager for remote shell access instead of SSH. If you're not familiar with that approach I can highly recommend reading: Keep up with the times: forget SSH, welcome AWS Session Manager
Login into the remote host using Session Manager:
aws ssm start-session --target <id-of-an-instance>
Install socat on the jump host:
sudo yum install -y socat
Create a bidirectional byte stream from the EC2 instance to RDS:
sudo socat TCP-LISTEN:3306,reuseaddr,fork TCP4:mysql-database.rds.amazonaws.com:3306
BTW: All the examples in this article are for MySQL, for other database types change the port numbers.
Create a tunnel to RDS using Session Manager
In another window you can now start a second SSM Session Manger session for port forwarding:
aws ssm start-session --target <id-of-an-instance> --document-name AWS-StartPortForwardingSession --parameters '{"portNumber":["3306"], "localPortNumber":["3306"]}'
You're ready to locally connect to a privately running RDS on AWS.
mysql --port=3306 --host=127.0.0.1 -psome_password -u some_user
Limitations
Once you close a local MySQL connection, it seems necessary to close the Session Manager forwarding session as well. I was unable to reuse the same port forwarding session to establish another MySQL connection.
A little note on SSL errors
My first attempts to start a local MySQL connection failed due to SSL connection errors. To fix this, I had to import the RDS certificates into my local trust store and reboot my system.
In case that wouldn't help I recommend reading Updating applications to connect to MySQL DB instances using new SSL/TLS certificates
Enjoy and until next time!
Top comments (3)
Nice one :)
you may also like mysocket.io which provides this as a service, in a CDN type fashion
Although it seems a nice service and easy to set up, using mysocket.io targets public endpoints. The nice things about AWS Session manager is that it allows me to keep my endpoints secure (in this case RDS).