Access AWS RDS privately using Tailscale
Amazon’s Relational Database Service (AWS RDS) provides a managed relational database accessible using SQL and other methods. RDS is an Amazon-managed service reached via an internal IP address. To make RDS accessible to a tailnet, we use a subnet router.
Before you begin this guide, you’ll need a Tailscale network set up and configured with at least one existing device. Read our getting started guide if you need help with this.
Setting up the RDS instance itself won’t be covered here, we’ll assume that RDS is already in use. There are a number of different database engines available with RDS, from Amazon’s own Aurora, MySQL, PostgreSQL, and more. The connectivity techniques described here works with all of them.
For purposes of this article, let’s assume the RDS is set up in the
First, create an EC2 instance running Amazon Linux on either x86 or ARM. Tailscale produces Linux packages containing binaries for both architectures, and the AWS ARM instances are very cost effective.
Some AWS Regions have multiple datacenters, each with an associated Availability Zone and a subnet of IP addresses. RDS instances in a Region are reachable from all of these subnets, so the EC2 instance can be created on any of them. Other AWS managed services may require connecting to a specific subnet.
If at least one side of a tunnel has “easy NAT,” where Tailscale can determine the UDP port number on the far side of the NAT device, then it will make direct connections to minimize latency. When setting the security policy, allow UDP port 41641 to ingress from any source. This will enable direct connections, to minimize latency.
Then ssh to the system and follow the steps to
install Tailscale on Amazon Linux
and configure subnet routing.
tailscale up, pass your VPC subnet to
For example, if the subnet address range is
172.31.0.0/16, the command would be:
tailscale up --advertise-routes=172.31.0.0/16 --accept-dns=false
tailscale up --accept-routes=trueto use the routes being advertised by the subnet router in AWS.
We need the RDS security policy to allow connection from the subnet router. The RDS security policy can be found in the instance details of the RDS instance. We add the security policy created for the EC2 subnet router instance.
For the benefit of the other nodes in the tailnet we’ll set up split DNS to allow use of the same DNS names as are used inside of AWS.
The AWS DNS server address is always the base of the VPC subnet + 2.
For example, if the subnet is
172.31.0.0, the DNS server will be
172.31.0.2. In the admin console DNS section this can be added as a nameserver restricted to the region-specific
compute.internal domain, for example,
As we can now ssh to the system over the private Tailscale network, there is no reason to leave the SSH port open on a public IP address. In the security group for the EC2 instance, delete the SSH rule allowing inbound connections.
We can now connect to RDS from any node on the tailnet, using the same DNS name as is used inside AWS.
For example, to access your RDS server from your personal computer, while logged into your tailnet:
mysqlsh --firstname.lastname@example.org:3306 MySQL database-2.cqlh98u5sael.us-west-2.rds.compute.internal:3306 ssl JS > \sql Switching to SQL mode... Commands end with ; MySQL database-2.cqlh98u5sael.us-west-2.rds.compute.internal:3306 ssl SQL > show databases; +--------------------+ | Database | +--------------------+ | demo | | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.0297 sec)
Using a subnet router allows us to connect to many services within AWS, not just RDS, using their internal AWS IP address.