22

I have created a VPC in aws with a public subnet and a private subnet. The private subnet does not have direct access to external network. So, there is a NAT server in public subnet which forward all outbound traffic from private subnet to outer network.

Currently, I can SSH from public subnet to private subnet, also SSH from NAT to private subnet. However, what I want is SSH from any machine(home laptop, office machine and mobile) to instances in private subnet.

I have done some research that I can setup the NAT box to forward SSH to instance in private subnet. But I got not luck for this.

Can anyone list what I need to setup to make this possible.

Naming are :

laptop (any device outside the VPC)

nat (the NAT server in the public subnet)

destination (the server in the private subnet which I want to connect to)

Not sure following are limitations or not:

The "destination" does not have a public IP, only a subnet ip, for example 10.0.0.1 The "destination" can not connect to "nat" via nat's public. There are several "destination" servers, do I need to setup one for each?

Thanks

jasonfungsing
  • 405
  • 2
  • 4
  • 6
  • This [link](http://blogs.aws.amazon.com/security/post/Tx3N8GFK85UN1G6/Securely-connect-to-Linux-instances-running-in-a-private-Amazon-VPC) outlines the steps required to connect to EC2 instances in Private Subnet through SSH Agent Forwarding. – Shailender Rawat Apr 07 '15 at 05:08

3 Answers3

36

You can set up a bastion host to connect to any instance within your VPC:

http://blogs.aws.amazon.com/security/post/Tx3N8GFK85UN1G6/Securely-connect-to-Linux-instances-running-in-a-private-Amazon-VPC

You can choose to launch a new instance that will function as a bastion host, or use your existing NAT instance as a bastion.

If you create a new instance, as an overview, you will:

1) create a security group for your bastion host that will allow SSH access from your laptop (note this security group for step 4)

2) launch a separate instance (bastion) in a public subnet in your VPC

3) give that bastion host a public IP either at launch or by assigning an Elastic IP

4) update the security groups of each of your instances that don't have a public IP to allow SSH access from the bastion host. This can be done using the bastion host's security group ID (sg-#####).

5) use SSH agent forwarding (ssh -A user@publicIPofBastion) to connect first to the bastion, and then once in the bastion,SSH into any internal instance (ssh user@private-IP-of-Internal-Instance). Agent forwarding takes care of forwarding your private key so it doesn't have to be stored on the bastion instance (never store private keys on any instance!!)

The AWS blog post above should be able to provide some nitty gritty regarding the process. I've also included the below in case you wanted extra details about bastion hosts:

Concept of Bastion Hosts: http://en.m.wikipedia.org/wiki/Bastion_host

If you need clarification, feel free to comment.

jca-
  • 476
  • 4
  • 4
  • 3
    Be sure to allow SSH/22 on both inbound and outbound on the bastion. – user464180 Nov 03 '15 at 16:22
  • This is such a critical point that it must be a part of the answer! – Tariq Jul 27 '18 at 18:17
  • In addition to the accepted answer which help a lot but not entirely, I had to make sure that security groups allow inbound and outbound traffic. At first glance it looked like they already do, but since I used CloudFormation template, I hadn't noticed that the source for incoming traffic to the private subnet was my ELB. So, it allowed all traffic but only coming from ELB. Changing that to my public subnet fixed the problem. – Milan Markovic Jan 30 '19 at 12:03
1

The only way I could make it work.

1) Make sure that the security group for this private instance has in the inbound rule the security group from the public subnet

Ports Protocol Source
All All sg-0b6616e070b9ea2d (public security group)

2) Using proxy commands, configure your ssh config file, to have something like this

vim ~/.ssh/config

Host publichost
   HostName 24.123.34.45
   User ubuntu
   IdentityFile ~/mypem.pem
   ProxyCommand none
Host privatehost
   HostName 10.0.2.133
   User ubuntu
   IdentityFile ~/mypem.pem
   ProxyCommand ssh publichost -W %h:%p

Run ssh privatehost it should work

0

Just to clarify: once you've ssh'd into your bastion host, you need to ssh into the NAT host as user ec2-user. This trumped me up a bit, since normally the ubuntu user is ubuntu on AWS. So I did:

laptop> ssh -A ubuntu@ssh_bastion
ssh_bastion> ssh ec2-user@nat_private_dns_or_private_ip

Also, remember that your ssh_bastion should have an outbound rule that allows traffic out to other hosts and sg's.

Joel
  • 101
  • Is that 'ec2_user' name as a result of spinning up an Amazon AMI specifically, already configured for NAT service? So, how did 'ec2-user' get an account on the private machine? – Dennis Jul 22 '15 at 23:13
  • and directly how can you establish a ssh connection to the private instance (through the bastion ) from your local computer? – Joaquin Diaz Sep 02 '20 at 14:19