Securely Accessing EC2 Windows Instances via SSH Port Forwarding

Securely Accessing EC2 Windows Instances via SSH Port Forwarding

Reaching an EC2 Windows instance in a private subnet through an SSH bastion host, keeping RDP off the public internet entirely.

Takahiro Iwasa
3 min read

Placing an EC2 Windows instance in a private subnet and accessing it through a bastion host in a public subnet is a common pattern for securing remote desktop access without exposing the instance directly to the internet.

Important

This method secures only the connection between the client and the bastion host. No encryption is applied between the bastion host and the EC2 Windows instance.

The overall architecture is illustrated below.

Architecture Diagram

Building Backend

VPC

Create a private subnet within the target VPC. This step can be skipped if a suitable subnet already exists.

Private Subnet

Create a route table and associate it with the private subnet.

Route Table Configuration

🔥 Caution

Ensure the internet gateway is removed from this route table; its presence would render the subnet effectively public.

If the EC2 Windows instance requires internet access, create a NAT gateway in a public subnet and attach it to the route table.

🔥 Caution

Running NAT gateway instances incurs additional costs.

NAT Gateway

SSH Bastion Host

  1. Launch an EC2 instance in the public subnet to serve as the bastion host.
  2. Configure the security group to allow inbound traffic on ports 22 (SSH) and 3389 (RDP).
💡 Tip

Assigning an Elastic IP (EIP) makes access to the bastion host easy.

EC2 Windows Instance

  1. Launch an EC2 Windows instance in the private subnet.
  2. Retrieve the remote desktop credentials using the Get Windows Password option in the EC2 dashboard.
  3. Restrict security group access to allow inbound traffic on ports 22 and 3389 only from the bastion host.

EC2 Windows Security Group

Testing the Connection

To establish a secure connection to the EC2 Windows instance, execute the following command from a local terminal:

Terminal window
ssh -i <YOUR_PRIVATE_KEY> -L 13389:<YOUR_EC2_WINDOWS_IP>:3389 ec2-user@<YOUR_SSH_BASTION_IP>

This command forwards traffic from local port 13389 to the EC2 Windows instance in the private subnet via the bastion host. A remote desktop session can then be initiated by connecting to localhost:13389.

Remote Desktop Connection

Conclusion

Putting the EC2 Windows instance in a private subnet with no internet gateway route, then reaching it through an SSH bastion in the public subnet, keeps RDP off the public internet entirely. The key piece of this setup is the security group on the private instance: restricting ports 22 and 3389 to traffic from the bastion host only, rather than to a broader CIDR range, is what actually enforces that. ssh -L 13389:<EC2_WINDOWS_IP>:3389 then does the rest, tunneling the RDP session through the bastion so localhost:13389 on the client machine reaches an instance that has no route in from outside the VPC. Since the tunnel only encrypts the client-to-bastion hop, the bastion host itself is the piece worth hardening most carefully — a tight security group and, ideally, an EIP reserved for known administrative access rather than an open range.

About the author

Takahiro Iwasa

Takahiro Iwasa

Software Developer

This blog shares technical notes from hands-on projects—architecture, implementation, and AWS service integrations.