AWS Architecture Blog
How Wego secured developer connectivity to Amazon Relational Database Service instances
How do you securely access Amazon Relational Database Service (Amazon RDS) instances from a developer’s laptop? Online travel marketplace, Wego, shares their journey from bastion hosts in the public subnet to lightweight VPN tunnels on top of Session Manager, a capability of AWS Systems Manager, using temporary access keys.
In this post, we explore how developers get access to allow-listed resources in their virtual private cloud (VPC) directly from their workstation, by tunnelling VPN over secure shell (SSH), which, in turn, is tunneled over Session Manager.
Note: This blog post is not intended as a step-by-step, how-to guide. Commands stated here are for illustrative purposes and may need customization.
Wego’s architecture before starting this journey
In 2021, Wego’s developer connectivity architecture was based on jump hosts in a public subnet, as illustrated in Figure 1.
Figure 1 demonstrates a network architecture with both public and private subnets. The public subnet contains an Amazon Elastic Compute Cloud (Amazon EC2) instance that serves as jump host. The diagram illustrates a VPN tunnel between the developer’s desktop and the VPC.
In Wego’s previous architecture, the jump host was connected to the internet for terminal access through the secure shell (SSH) protocol, which accepts traffic at Port 22. Despite restrictions to the allowed source IP addresses, exposing Port 22 to the internet can increase the likeliness of a security breach; it is possible to spoof (mimic) an allowed IP address and attempt a denial of service attack.
Moving the jump host to a private subnet with Session Manager
Session Manager helps minimize the likeliness of a security breach. Figure 2 demonstrates how Wego moved the jump host from a public subnet to a private subnet. In this architecture, Session Manager serves as the main entry point for incoming network traffic.
We will explore how developers connect to Amazon RDS directly from their workstation in this architecture.
Tunnel TCP traffic through Session Manager
Session Manager is best known for its terminal access capability, but it can also tunnel TCP connections. This is helpful if you want to access EC2 instances from your local workstation (Figure 3).
Here’s an example command to forward traffic from local host Port 8888 to an EC2 instance:
$ aws ssm start-session --target <instance-id> \
--document-name AWS-StartPortForwardingSession \
--parameters '{"portNumber":["8888"], "localPortNumber":["8888"]}'
This assumes the target EC2 instance is configured with AWS Systems Manager connectivity.
Tunnel SSH traffic over Session Manager
SSH is a protocol built on top of TCP; therefore, you can tunnel SSH traffic similarly (Figure 4).
To allow a short-hand notation for SSH over SSM, add the following configuration to the ~/.ssh/config
configuration file:
host i-* mi-*
ProxyCommand sh -c "aws ssm start-session --target %h \
--document-name AWS-StartSSHSession \
--parameters 'portNumber=%p'"
You can now connect to the EC2 instance over SSH with the following command:
ssh -i <key-file> <username>@<ec2-instance-id>
For example:
ssh -i my_key ec2-user@i-1234567890abcdef0
Ideally, your key-file is a short-lived credential, as recommended by the AWS Well-Architected Framework, as it narrows the window of opportunity for a security breach. However, it can be tedious to manage short-lived credentials. This is where EC2 Instance Connect comes to the rescue!
Replace SSH keys with EC2 Instance Connect
EC2 Instance Connect is available both on the AWS console and the command line. It makes it easier to work with short-lived keys. On the command line, it allows us to install our own temporary access credentials into a private EC2 instance for the duration of 60 seconds (Figure 5).
Ensure the EC2 instance connect plugin is installed on your workstation:
pip3 install ec2instanceconnectcli
This blog post assumes you are using Amazon Linux on the EC2 instance with all pre-requisites installed. Make sure your IAM role or user has the required permissions.
To generate a temporary SSH key pair, insert:
$ ssh-keygen -t rsa -f my_key
$ ssh-add my_key
To install the public key into the EC2 instance, insert:
$ aws ec2-instance-connect send-ssh-public-key \
--instance-id <instance-id> \
--instance-os-user <username> \
--ssh-public-key <location ssh key public key> \
--availability-zone <availabilityzone> \
--region <region>
For example:
$ aws ec2-instance-connect send-ssh-public-key \
--instance-id i-1234567890abcdef0 \
--instance-os-user ec2-user \
--ssh-public-key file://my_key.pub \
--availability-zone ap-southeast-1b \
--region ap-southeast-1
Connect to the EC2 instance within 60 seconds and delete the key after use.
Tunneling VPN over SSH, then over Session Manager
In this section, we adopt a third-party, open-source tool that is not supported by AWS, called sshuttle. sshuttle is a transparent proxy server that works as a VPN over SSH. It is based on Python and released under the LGPL 2.1 license. It runs across a wide range of Linux distributions and on macOS (Figure 6).
Why do we need to tunnel VPN over SSH, rather than using the earlier TCP over Session Manager? After all, you could use port forwarding to remote hosts using Session Manager as explained in the AWS blog post Use port forwarding in AWS Systems Manager Session Manager to connect to remote hosts.
A lightweight VPN solution, like sshuttle, simplifies the connectivity by allowing you to forward traffic from Amazon EC2 to Amazon RDS. From the developer’s perspective, this works transparently, as if it is regular network traffic.
To install sshuttle, use one of the documented commands:
$ pip3 install sshuttle
To start sshuttle, use the following command pattern:
$ sshuttle -r <username>@<instance-id> <private CIDR range>
For example:
$ sshuttle -r ec2-user@i-1234567890abcdef0 10.0.0.0/16
Make sure the security group for the RDS DB instance allows network access from the jump host. You can now connect directly from the developer’s workstation to the RDS DB instance based on its IP address.
Advantages of this architecture
In this blog post, we layered a VPN over SSH that, in turn, is layered over Session Manager, plus we used temporary SSH keys.
Wego designed this architecture, and it was practical and stable for day-to-day use. They found that this solution runs at lower cost than AWS Client VPN and is sufficient for the use case of developers accessing online development environments.
Wego’s new architecture has a number of advantages, including:
- More easily connecting to workloads in private and isolated subnets
- Inbound security group rules are not required for the jump host, as Session Manager is an outbound connection
- Access attempts are logged in AWS CloudTrail
- Access control uses standard IAM policies, including tag-based resource access
- Security groups and network access control lists still apply to “allow” or “deny” traffic to specific destinations
- SSH keys are installed only temporarily for 60 seconds through EC2 Instance Connect
Conclusion
In this blog post, we explored Wego’s access patterns that can help you reduce your exposure to potential security attacks. Whether you adopt Wego’s full architecture or only adopt intermediary steps (like SSH over Session Manager and EC2 Instance Connect), reducing exposure to the public subnet and shortening the lifetime of access credentials can improve your security posture!