AWS NETWORKING 101
Published: 2023-10-08 09:45:52

AWS networking can be overwhelming, at least it was for me at first. But when you piece its various parts apart it's simple and digestible.
In this post, let's understand the network components in AWS that make your EC2 instance possible, say to run a web server.

**Outline/ Components**
- [VPC](#vpc)
- [Network Access Control List (NACL)](#nacl)
- [Internet Gateway](#igw)
- [Route Table & Routes](#rt)
- [Subnets](#subnets)
- [Security Groups](#sg)
- [Network Interface](#eni)
- [NAT Gateway](#natgw)
- [Create EC2 Instance](#ec2)


_We would be using AWS CLI, so go ahead, install and set up AWS CLI -_ [https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)


## <a name="vpc"></a>VPC
A virtual private cloud (VPC) is a logically isolated portion of the AWS Cloud. Think of it as your own special cloud environment to create all kind of resources. A VPC spans a region. Subnets, explained later, helps VPC isolate resources to different availability zones (AZs) for redundancy.
VPC is the first resource you create before anything else. A VPC helps you define an IP range, which would be sub-divided by subnets. Your AWS account comes with a default VPC but you're not to use that for production.

_Let's create a VPC and enable fancy hostnames_
`aws ec2 create-vpc --cidr-block 10.0.0.0/16`

_# Take note of the VcpId. I usually would store it as an env var_

`aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames "{\"Value\":true}"`

_Check my post to understand VPC/Subnet IP range and CIDR sub-division_ - [Dividing IPs for Multiple Subnets in a VPC](https://dev.to/zeelz/dividing-ips-for-multiple-subnets-in-a-vpc-4f2a)


## <a name="nacl"></a> Network Access Control List
Network Access Control List (NACL) is a stateless network resource that controls traffic to/fro resources in a VPC from the subnet level. It allows or denies access.
Every VPC needs at least a NACL. Hence, on creation of a new VPC AWS automatically creates a default NACL attached to the VPC.


## <a name="igw"></a> Internet Gateway
Internet Gateway (IGW) is truly a VPC's gateway to the internet. 

Say, we have a website domicile in an EC2 instance with a public-facing IP, when Kayode from Ibadan hits that IP or hostname how does that request get to the EC2? Traffic gets to the EC2 through, you guessed it - IGW

_Let's create one and attach it to our VPC, else Kayode won't be able to browse our fancy blog_

`aws ec2 create-internet-gateway`
_# Take note of IgwId from the output_

`aws ec2 attach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID`


## <a name="rt"></a> Route Table and Routes
A route table is basically a collection of routes that determine the flow of internal and external traffic to/fro resources in a VPC.

Upon creation of a new VPC, AWS automatically creates a default (main) route table

Since, a VPC may have multiple route tables each route table associates with at least a subnet so resources know which route table routes their traffic per the subnet they belong to. But then if route table/subnet association is not explicitly defined, it's assumed that all subnets are associated with the default (main) route table (The one AWS gave us).

We said a route table is a collection of routes, right? Yes, so we need to define a route for internet access (egress & ingress). This route would use the IGW as its target (router).

`aws ec2 create-route --route-table-id ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id IGW_ID`

_# IGW_ID from when we created IGW_

_To get id of default route table list all route tables and copy the RouteTableId where the DestinationCidrBlock is 30.0.0.0/24_
`aws ec2 describe-route-tables`


## <a name="subnets"></a>Subnets
Think of subnets as a way of splitting your VPC to bits, to be put in different AZs and to hold different applications or resources.

_Create a subnet for the VPC. Let AWS place it in any Az within the VPC's region_
`aws ec2 create-subnet --cidr-block 30.0.0.0/16 --vpc-id $VPC_ID`

[Why 30.0.0.0/16?](https://dev.to/zeelz/dividing-ips-for-multiple-subnets-in-a-vpc-4f2a) Just incase we decide to create another subnet.

_Enable public IP generation for public subnet_
_If not EC2s you create in this subnet won't have public-facing IP address_
`aws ec2 modify-subnet-attribute --subnet-id $SUBNET_ID --map-public-ip-on-launch`

AWS automatically associates this subnet to the default NACL of the VPC. NACLs are for subnets after all 🤷‍♂️  

A subnet that wants internet access should have a route in its route table pointing to an IGW, that is how a subnet is even said to be "public" anyway.


## <a name="sg"></a>Security Group
A security groups (SG) is a stateful firewall at the instance level, as against NACL at the subnet level.
You can create SG rules to define various traffic types, ports and sources.
Say we want to create a rule for tcp traffic for port 80 and 0.0.0.0/0 as source. This would allow anyone on the internet to access our blog on port 80.

_Create a security group_
`aws ec2 create-security-group --vpc-id $VPC_ID --group-name http-80 --description "http 80"`
_# Copy the groupId (sg-04dffb200473a5ce9)_

_Add a rule to open port 80, (Allows non-secure http traffic from anywhere)_
`aws ec2 authorize-security-group-ingress --group-id $SG_ID --protocol tcp --port 80 --cidr 0.0.0.0/0`

Go ahead and add a rule to open port 22 for SSH access


## <a name="eni"></a> Network Interface
AWS Elastic network interface (ENI) is a virtual network adapter that lets resources between a VPC connect with each other and with the internet. ENIs are created in subnets.

So how does an ENI work you ask? An ENI connects an EC2 instance to network resources through its subnet.
Remember our subnet is associated with a route table, which has an IGW route. You get the flow
_ENI => subnet => route table => IGW route => internet_

But we mustn't create an ENI ourselves. AWS creates one for us on EC2 creation and attaches it to the instance. It would use the subnet and SG we specify for the EC2.


## <a name="natgw"></a> NAT Gateway 
For every route table there's a default (local) route for resources within a VPC to communicate. But what if an EC2 which isn't public needs internet to download stuffs and update itself? This is where a Network Address Translation gateway (NAT gateway) comes in.
A NAT gateway allows instances in a private subnet to connect to the internet.

_Create a NAT gateway in a public subnet_

`aws ec2 create-nat-gateway --subnet-id $SUBNET_ID
`
_# Take note of the NatGatewayId_

_Create a route in a private subnet route table to target the NAT gateway_

`aws ec2 create-route --route-table-id ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --nat-gateway-id NatGatewayId`

_**Note**: A private subnet is one that isn't associated with a route table, which has an IGW route._

Now the instances you create in this private subnet can't be accessed from the internet but can access the internet to download software packages.


## <a name="ec2"></a> EC2 Instance
This is not an exhaustive list of AWS network components, but they are the basic ones you need.

To finalize, let's create an EC2 instance utilizing the network resources created and configured above to install a web server to check our new networking prowess 😃 

SSH Key Pair
To login (ssh) to the instance, we would be need an SSH key file.

_Create an SSH key-pair with which you would ssh into the instance_
`aws ec2 create-key-pair --key-name fancy-blog-ssh`

_# Carefully copy and save the private key string to a file - `privkey.pem`_


`aws ec2 run-instances \
--image-id ami-067d1e60475437da2 \
--instance-type t2.micro \
--subnet-id $SUBNET_ID \
--security-group-ids sg-04dffb200473a5ce9 \
--key-name fancy-blog-ssh \
--associate-public-ip-address`

- image-id => OS image (AWS Linux 2)
- instance-type => CPU & memory categorization (1vCPU 1GiB memory)
- subnet-id => our subnet id
- security-group-ids => our SG id
- key-name => the name we gave our key pair
- associate-public-ip-address => generate a public IP for this instance

_# Take note of the InstanceId_

You need the `PublicIpAddress` value, which is not populated at first but when you view that instance.

_# To view the instance details to get our `PublicIpAddress`, run:_
`aws ec2 describe-instances --instance-id INSTANCE_ID
`
_Let's SSH into our machine and install a simple web server - `httpd`_
`ssh -i privkey.pem ec2-user@54.210.11.65`

`sudo yum install httpd
sudo systemctl start httpd`

Now open your browser and enter `http://54.210.11.65`

You should see "**It works!**", if you didn't may have done something wrong. Comment below.

**Resources**
[https://docs.aws.amazon.com/cli/latest/reference/ec2/](https://docs.aws.amazon.com/cli/latest/reference/ec2/)

**Tear Down**
Always remember to tear down all the resources you create for learning purposes, to avoid incurring cost. AWS likes money like all of us 😆 

❤️ ✌️