🔐 Secure RDP Access to Windows EC2 Without Public IP – Using EC2 Instance Connect Tunnel

BalajiBalaji
5 min read

🧩 Introduction

In cloud environments, security is a top priority. One common best practice is to deploy EC2 instances in private subnets — without public IPs — to reduce exposure to the internet. But what happens when you need to connect to one of these private Windows instances using RDP?

Traditional methods involve setting up:

  • A bastion host

  • Modifying security group rules

  • Or deploying a VPN

But AWS now provides a smarter, safer, and serverless option — EC2 Instance Connect Tunnel.

This guide will walk you through connecting to a private Windows EC2 instance via RDP, using a temporary SSH tunnel created by AWS CLI, without ever assigning a public IP. We’ll cover instructions for both Windows and Linux users, use cases, and configuration tips.


🎯 Why Use EC2 Instance Connect Tunnel?

Let's start with a real-world scenario:

Imagine you're a DevOps engineer managing a highly secure VPC. You launch a Windows Server EC2 instance in a private subnet. It has no public IP, and your company policy forbids exposing port 3389. Now, you need to log in and troubleshoot an app.

✅ Solution: Use AWS EC2 Instance Connect Tunnel.

✅ Benefits:

  • No need for bastion hosts or VPNs

  • Works even if the security group doesn't allow external RDP

  • Easy to use from any CLI with AWS access

  • Tunnel closes automatically when done — no cleanup required


🧱 How It Works (High-Level)

  1. AWS CLI starts a secure, temporary tunnel from your machine to the EC2 instance.

  2. The tunnel maps your local port (e.g., 9999) to the instance's RDP port (3389) over a secure AWS channel.

  3. You edit the .rdp file to point to localhost:9999.

  4. RDP traffic flows securely to your private instance — no public IP needed.


🧰 Prerequisites

Make sure you have:

RequirementPurpose
Windows EC2 InstanceTarget instance to connect to
No Public IPEnsures it's truly private
.pem KeyUsed to decrypt the Administrator password
AWS CLI v2Required to run open-tunnel command
IAM AccessMust have permission for EC2 and Instance Connect
RDP ClientBuilt-in on Windows or tools like Remmina, xfreerdp on Linux

🪟 For Windows Users: Step-by-Step Guide


🔹 Step 1: Get Instance Details

Go to EC2 Console, locate your Windows instance, and copy:

  • Instance ID: e.g., i-012345xxxxxdef0

  • Private IP (if needed)

  • Confirm instance is running


🔹 Step 2: Decrypt the Administrator Password

  1. Select your instance → Connect

  2. Go to RDP Client tab

  3. Click Get Password

  4. Upload your .pem file to decrypt the password

  5. Save this password — you’ll use it to log in


🔹 Step 3: Open a Secure Tunnel Using AWS CLI

Launch PowerShell or CMD, then run:

aws ec2-instance-connect open-tunnel `
  --instance-id i-01234xxxxxxef0 `
  --remote-port 3389 `
  --local-port 9999
  • --remote-port 3389: Target RDP port on EC2

  • --local-port 9999: Your local machine’s port

📌 Keep this window open — closing it shuts down the tunnel.


🔹 Step 4: Edit the RDP File

Open the downloaded .rdp file in Notepad.

Update the line:

full address:s:10.0.x.x

To:

full address:s:localhost:9999

Why? Because your RDP traffic is now going through the local tunnel.

Make sure these lines exist:

auto connect:i:1
full address:s:localhost:9999
username:s:Administrator

Save the file.


🔹 Step 5: Connect via Remote Desktop

Double-click the .rdp file or open it using Remote Desktop Connection.

  • Enter username: Administrator

  • Enter the decrypted password from Step 2

  • Accept the certificate warning

✅ You're now inside your Windows instance in a private subnet!


🐧 For Linux Users (Using Remmina or xfreerdp)


🔹 Step 1: Run the Tunnel Command

aws ec2-instance-connect open-tunnel \
  --instance-id i-01234xxxxxf0 \
  --remote-port 3389 \
  --local-port 9999

Leave this terminal open to keep the tunnel alive.


🔹 Step 2: Connect with Remmina GUI

  1. Launch Remmina

  2. Create a new connection:

    • Protocol: RDP

    • Server: localhost:9999

    • Username: Administrator

    • Password: Decrypted password

  3. Save & connect


🔹 Or Use xfreerdp CLI

xfreerdp /v:localhost:9999 /u:Administrator /p:'YourPasswordHere' /cert-ignore

This works well for CLI fans and scripting.


🔐 Security Notes

  • ✅ This method uses temporary, encrypted channels — much safer than opening port 3389

  • ✅ No persistent resources (no need to maintain bastion hosts)

  • ✅ IAM roles control who can initiate tunnels

  • ✅ Sessions are auditable via CloudTrail


⚙️ IAM Policy Required

Here’s a sample IAM policy to allow tunneling:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2-instance-connect:OpenTunnel",
        "ec2:DescribeInstances"
      ],
      "Resource": "*"
    }
  ]
}

Apply it to IAM users or roles that need tunneling access.


🧪 Use Case Scenarios

ScenarioBenefit
Accessing QA environmentsTemporary secure access without modifying security groups
Emergency troubleshootingConnect instantly to a private instance from CLI
High-security VPCsEliminate bastion hosts and reduce surface area
Compliance and auditsUse CloudTrail to track access attempts

🧹 Cleaning Up

When you're done:

  1. Close RDP session

  2. Close the terminal running the tunnel

💡 The connection is gone. No changes linger in your environment — secure by design.


🏁 Conclusion

The EC2 Instance Connect Tunnel is a powerful yet underused tool that allows developers, sysadmins, and DevOps engineers to securely access private EC2 instances without the hassle of configuring bastion hosts or modifying firewalls.

No public IP
No open ports
No long-lived infrastructure

It’s a clean, temporary, and secure solution that fits perfectly in modern cloud environments.

0
Subscribe to my newsletter

Read articles from Balaji directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Balaji
Balaji

👋 Hi there! I'm Balaji S, a passionate technologist with a focus on AWS, Linux, DevOps, and Kubernetes. 💼 As an experienced DevOps engineer, I specialize in designing, implementing, and optimizing cloud infrastructure on AWS. I have a deep understanding of various AWS services like EC2, S3, RDS, Lambda, and more, and I leverage my expertise to architect scalable and secure solutions. 🐧 With a strong background in Linux systems administration, I'm well-versed in managing and troubleshooting Linux-based environments. I enjoy working with open-source technologies and have a knack for maximizing performance and stability in Linux systems. ⚙️ DevOps is my passion, and I thrive in bridging the gap between development and operations teams. I automate processes, streamline CI/CD pipelines, and implement robust monitoring and logging solutions to ensure continuous delivery and high availability of applications. ☸️ Kubernetes is a key part of my toolkit, and I have hands-on experience in deploying and managing containerized applications in Kubernetes clusters. I'm skilled in creating Helm charts, optimizing resource utilization, and implementing effective scaling strategies for microservices architectures. 📝 On Hashnode, I share my insights, best practices, and tutorials on topics related to AWS, Linux, DevOps, and Kubernetes. Join me on my journey as we explore the latest trends and advancements in cloud-native technologies. ✨ Let's connect and dive into the world of AWS, Linux, DevOps, and Kubernetes together!