AWS guide: Setting SSH connection from Windows Client to a Linux EC2 instance

Useful tips and step-by-step guide on how to connect to a Linux-based EC2 server from a local Windows client

Recently I have finished developing an MVC.NET Core application, which I wanted to encapsulate into a Docker image and be able to deploy on any OS. Unfortunately, my local development workstation OS does not support Hyper-V, which is one of Docker prerequisite.

Docker installation failed

So, instead of limiting myself only to VirtualBox or installing an old Docker version (such as Docker Toolbox), I decided to harness the cloud services to overcome this problem, any better than that?

My plan is to use an EC2 instance, with pre-installed Docker, to complete my original goal: building a Docker image with my MVC.NET Core application and test it.

Follow me in preparing the required network resources (Virtual Private Cloud) and spinning up my EC2 server.

Preparing the network

Before rushing to configure the EC2 instance, you need to ensure your network is ready. You can refer to this blog post if you’re not familiar with VPC concept. It will give you a good overview to grasp the principles.

In case the AWS region you are using still has its default VPC, you’re in a good position. Otherwise, you can always create a default VPC in your region (Actions → Create Default VPC).

However, creating custom VPC has advantages. First, you define a dedicated network for a certain purpose without affecting the other resources in your network, which allows you to govern your networks better. Second, you to gain more knowledge and really understand what’s behind the scenes.

Some caveats when defining the VPC in order to avoid reconfiguring some steps again:

Firstly, ensure the VPC has at least one subnet connected to the internet, that’s your public subnet. Your EC2 should reside in this subnet. For more information on how to configure a public subnet, you can follow the explanations in this blog-post: VPC building-block and principles.

Secondly, you need to open the SSH port (22) in the security group of the public subnet. Without this rule, the SSH connection will be blocked and establishing SSH communication with your instance will fail.

Lastly, it’s also recommended to open ICMP port, to have the option for checking whether your instance is alive or not. For more details on how to define the security group’s rules, follow the tutorial on how to open the traffic for ping requests.

A word about security: the best practice rule is to limit the allowed traffic only to necessary endpoints. Therefore, it’s recommended to set the source to your IP endpoint address. You can do that by accessing the security group definition from the EC2 management console, which allows you to set the source as “My IP” without the hassle to key it in specifically. However, if you don’t have a fixed endpoint IP address, you’ll obtain a new IP address each time you connect to the internet, and thus you will have to update this source field before connecting to your EC2 instance. Anyway, it’s a more secure option than opening your instance to incoming requests from any IP address.

Setting up the EC2 server

So, after ensuring your VPC is ready, let’s begin with defining the EC2 instance. I selected an image that already contains a Docker version (ami-0260887a, for example). The setup is quite straight forward, but when you reach to network configuration (Step 3), make sure you select the VPC you’ve configured earlier with its public subnet.

Another thing to note is the Auto-assign Public IP field, which should be “enable”. You can select the option “Use subnet setting”, but make sure it’s enabled too. Without this definition, your EC2 instance will not obtain any public IP, and thus will be inaccessible.

At the security group step, select the security group you’ve prepared previously. That will facilitate the subsequent configuration steps.

Lastly, before launching the EC2, AWS requires to configure a private key to associate with the new instance. It can be an existing key or a newly generated key. It’s better to create a key per instance to enhance the access control to your instances by segregating authentications. If one key has been compromised or lost, you will be able able to contain and control this incident better.

That’s it, your instance is ready to be launched. Click on the Launch button and have a short break before we continue 🍕.

EC2 instance — Are you alive?

When the setup is over and the instance state is running (green icons ), let’s check if it is alive properly by accessing it. In my view, it’s essential to confirm it first before moving forward to more complicated steps.

Obtain the EC2 instance public IP and try to ping it. If the ping responses are flowing, then touché! It’s an acknowledgement that your VPC is configured properly.

Troubleshooting is required if the ping requests get no response. Most likely, the problem is not the internet gateway association with the VPC, since otherwise its status in the route table would have been “black hole” and not “active”. Therefore, we shall check other areas.

Examining the route table

The internet gateway should be associated with at least one route table. Let’s look at this route table’s definitions and verify the internet gateway is associated with our subnet adequately.

There are two options: either the subnet is associated with the route table directly or it’s not associated with any other route table and the route table is set as “main”. If one of these options applies, then the route table-subnet association is configured properly. Otherwise, need to rectify this association.

Besides subnet association, also check the internet gateway destination. To ensure you’re not limiting yourself to a specific IP range, open the destination to

Ensure the IGW status is Active and the destination IP is open

Checking the network ACL

If the route table is configured properly, check whether the blocking is not related to the network ACL. If you’re not using the default network ACL, then check the traffic rules. Any new network ACL rules are configured as “Deny” by default, and thus, deliberately changing it is essential.

What about the security group?

If the ping requests still remain unanswered, let’s examine the security group that’s associated with the EC2 instance and review its inbound rules. As configured at the earlier stage, the ICMP should be open.

Reviewing the inbound rules

I hope that by reaching this step, you’ve managed to overcome the ping problem and your server is reachable. Otherwise, a more thorough investigation is required 🤔, which is not part of this post.

Connecting to our instance

Those who are familiar with Windows OS instinctively look for the remote control utility, whereas Linus users are more intuitive with the CLI black screen. Our instance is Linux-based, so Windows fans, you have to adjust to a different approach 🙄. But not to worry, it’s not scary as it may seem.

I’ll exemplify two ways to connect to our instance: CLI (command language interpreter) and PuTTY.

Using OpenSSH (CLI)

There are some prerequisites before being able to interact with our EC2 instance. AWS has extensive documentation about it, so I won’t dive into it. You can find this link as very useful for installing and configuring SSH in your environment.

Once your environment is ready, you can start by interacting with the AWS CLI. Start with checking the AWS CLI version:

aws --version

An example of a valid output is:

Checking the AWS installed version

Try to get the instance id and type the following command to see the EC2 details:

aws ec2 get-console-output --instance-id <<instance id>>

Setting the private key file’s permissions

The next step is preparing the private key file (.pem file) and ensuring it is protected. It must be protected from reading and writing operations from any other user, otherwise, SSH ignores this key and prompts an error message.

If you were in a Linux environment, permissions could be changed by using “chmod” command. The equivalent Windows command is “cacls” (which is deprecated) or its successor “icacls”.

To review the pem file’s current permissions, run the following command (it can be run from pem file local folder or just ensure the pem file path is correct):

icacls <pem file path>

The possible output is:

PEM file permissions

Next, you need to remove all other permissions and assign only read permission to your account. Follows the commands below:

# Remove the permissions inheritance
icacls <<pem file path>> /inheritance:r /T# Grant read permission to the current user
icacls <<pem file path>> /grant <<user name>>:R

Once done, the pem file permissions should be only read permission for your user. You can check it by running again the command: icacls <<pem file path>>.

Connecting to the server

You can connect to the server using its public IP or its public DNS. If you opt for using the DNS, get it from the EC2 instance details. In case you do not see any the DNS value (the field is blank), ensure the VPC configuration include DNS Hostnames option.

# Connecting using the public DNS
ssh -i <<pem file path>> ec2-user@<Public DNS># Alternatively, connecting using the public IP
ssh -i <<pem file path>> ec2-user@<Public IP>

In case the pem file’s permissions were not properly configured, the SSH prompts an error message, see the example below 👇.

On the other hand, a successful login yields the following output:

Congratulations! You have managed to connect to your Linux instance successfully 👍.

Using PuTTY

The second option is opening an SSH connection using the PuTTY tool. It involves less preparation than using the CLI. Once you download PuTTY for windows, you get the tools that allow you to connect properly.

The first step is preparing the private key file. PuTTY does not use pem file but another file format: ppk file (PuTTY Private Key file), and thus we need to create it based on our pem file. AWS has a simple guide on how to do it with the PuTTYgen application, follow its steps here.

The second step is running the PuTTY application and providing two essential values: the public IP of the EC2 instance and the ppk file we’ve created earlier.

The IP field can also include the user name, which allows a direct login with its credential (ec2-user@<Public IP>), otherwise, you will have to provide a user name after the connection has been initialized. By default, AWS allows to login with ec2-user account and blocks the option to login with root.

Now, just set the ppk file and click on the Open button.

Setting the ppk file

PuTTY may prompt some warning messages if this is your first attempt to connect to the instance (read more about it here), but you can accept them and continue.

At the next screen, you should see is your instance. Voilà!

What’s next?

After a successful login to the server, typing the following command will present the installed Docker version on your Linux EC2 instance:

docker --version

There it is. You’ve managed to establish the communication with your instance. For me, this is the beginning of my original task of building a docker image and running it, but that can be a topic for another blog post.

Closing notes

That was a short guide on how to interact with your Linux-based EC2 instance using SSH protocol. I hope you find it useful.

– Lior

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s