Thursday, 16 June 2022

How to access a private EC2 instance using a bastion host


 

A bastion host is a server whose purpose is to provide access to a private network from an external network, such as the Internet. [source: How to Record SSH Sessions Established Through a Bastion Host]

 

The idea is to have a public EC2 instance which would be a bastion host, SSH to it first and then from that session to SSH to a private EC2.
 

Prerequisites

 
Here is the list of resources we need to create, step by step:
  • Custom VPC in which we want to run EC2 instances
  • Internet Gateway which connects VPC with Internet; depends on VPC (ID)
  • (Internet) Route Table (for this VPC) which allows connection to Internet (routing to Internet Gateway); depends on VPC (ID) and CIDR chosen for public subnet
  • (Local) Route Table (for this VPC) which allows only local traffic (within VPC); depends on VPC (ID) and CIDR chosen for private subnet
  • A (public) subnet in chosen AZ in this VPC
    • connected to route table which allows Internet connection => that makes this subnet public
  • A (private) subnet in the same AZ in this VPC 
    • connected to route table which allows local traffic only => that makes this subnet private
  • Security group in this VPC that allows SSH; depends on VPC (ID)
  • Running (public) EC2 instance (bastion host)
    • running in the same VPC
    • running in the same AZ
    • running in the created public subnet
    • having attached security group mentioned above
  • Running (private) EC2 instance
    • running in the same VPC
    • running in the same AZ
    • running in the created private subnet
    • having attached security group mentioned above
  • SSH client available on a dev machine
 

Resource Details

 
VPC:
  • Name: test-vpc
  • CIDR: 10.10.0.0/16
     
We need to have a security group which is created in the same VPC as in which we want to run EC2 instances and which allows inbout and outbound SSH traffic. 
  • Name: Allow public SSH
  • VPC: test-vpc
  • Inbound rules: 
    • IP version: IPv4
    • Type: SSH
    • Protocol: TCP
    • Port range: 22
    • Source: 0.0.0.0/0 
    • Description: SSH access
  • Outbound rules: 
    • IP version: IPv4
    • Type: All traffic
    • Protocol: All
    • Port range: All
    • Destination: 0.0.0.0/0
    • Description: -

EC2 is public if it runs in a public subnet and has Auto-assign public IP enabled. Subnet is public if it is associated with routing table which has at least one Target set to Internet Gateway. 
 
Public EC2 instance needs to have attached to it Allow public SSH security group.
 
EC2 is private if it runs in a private subnet. Subnet is private if it is associated with routing table which has all Targets set to local. The following settings don't make subnet a private by default:
  • Subnet has Enable auto-assign public IPv4 address disabled
    • When launching EC2 instance, this can be overridden with EC2 setting Auto-assign public IP
  • Subnet uses a private IP range as its CIDR block

A private EC2 has a network interface which does not have a public IPv4 address but has a private IPv4 address e.g. 10.10.3.226 if it's in 10.10.3.0/24 subnet.

Private EC2 instance needs to have attached to it Allow public SSH security group (SSH Access Security Group in the diagram below).

Architecture diagram:

 



SSH Connection

We'll use SSH feature called agent forwarding. If we load a key into a local SSH agent, we can use ssh -A command to allow any remote ssh server to read this key as if it was added to the local SSH agent. We need to use -A only when establishing the first SSH connection.

From man ssh:

     -A      Enables forwarding of connections from an authentication agent such as ssh-agent(1).  This can also be specified on a per-host basis in a configuration file.
Agent forwarding should be enabled with caution.  Users with the ability to bypass file permissions on the remote host (for the agent's UNIX-domain socket) can access the local agent through the forwarded connection.  An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into the agent. A safer alternative may be to use a jump host (see -J).

To add a private key to the local ssh agent:

$ ssh-add MyTestMachine.pem
Identity added: MyTestMachine.pem (MyTestMachine.pem)

 

Now we can connect to the bastion host (ec2-user is the default user for Amazon Linux 2 AMIs):

$ ssh -A ec2-user@34.255.30.127
Last login: Wed Jun 15 16:38:34 2022 from r-123.45.67.195.ptr.example.com

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
16 package(s) needed for security, out of 26 available
Run "sudo yum update" to apply all updates.


From inside the bastion host we can connect to the target private EC2:

[ec2-user@ip-10-10-0-85 ~]$ ssh ec2-user@10.10.3.226

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-10-10-3-226 ~]$

---

No comments: