Recently, I wanted to move my applications from a tradional hosting service into AWS. The main services to be migrated are a webserver, an email server, and a database server. Both, webserver and email server connect to the backend database server with their various services (e.g. the webserver running Apache, and the mailserver running Exim).
In this article, I’ll give a detailed explanation how to setup such a solution.
I decided to deploy these services on three dedicated EC2 instances, where the webserver and the mailserver will be accessible from the Internet, and the database server will be only accessible from a private network.
The EC2 instances will be running in the same VPC in one availability zone.
To connect the instances on the public subnet, we’ll use an Internet gateway. These instances will use public Elastic IP addresses to be reached from the Internet.
To allow the instances on the private subnet to connect to the Internet for updates, we’ll place a custom NAT instance in the public subnet.
The VPC will be created with a size /16 IPv4 CIDR block 10.0.0.0/16.
We’ll define the following subnets out of this block:
- A public subnet will be created with a size /24 IPv4 CIDR block 10.0.0.0/24). This public subnet is a subnet that’s associated with a route table that has a route to the internet gateway.
- A private subnet with a size /24 IPv4 CIDR block 10.0.1.0/24.
We will also create an Internet gateway. This connects the VPC to the Internet and to other AWS services.
We deploy instances with private IPv4 addresses in the subnet range. This enables them to communicate with each other and other instances in the VPC.
We also deploy instances in the public subnet with Elastic IPv4 addresses, which are public IPv4 addresses that enable them to be reached from the internet. The instances can have public IP addresses assigned at launch instead of Elastic IP addresses. Instances in the private subnet are back-end servers that don’t need to accept incoming traffic from the Internet and therefore do not have public IP addresses; however, they can send requests to the internet using the NAT instance (in our case this is the database server).
A NAT instance with its own Elastic IPv4 address. A NAT instance is a “poor man’s” NAT gateway, i.e. an EC2 instance which performs IP forwarding and masquerading. Instances in the private subnet can send requests to the Internet through the NAT instance over IPv4 (e.g. for software updates).
We will use two route tables:
- A custom route table associated with the public subnet. This route table contains an entry that enables instances in the subnet to communicate with other instances in the VPC over IPv4, and an entry that enables instances in the subnet to communicate directly with the internet over IPv4.
- The main route table associated with the private subnet. The route table contains an entry that enables instances in the subnet to communicate with other instances in the VPC over IPv4, and an entry that enables instances in the subnet to communicate with the internet through the NAT instance over IPv4.
Public and private subnets will be secured by appropriate NACLs. Security groups for all instances will be implemented.
Security groups control inbound and outbound traffic for the instances, and network ACLs control inbound and outbound traffic for our subnets. In most cases, security groups are sufficient. However, we also use network ACLs since I want an additional layer of security for the VPC.
The following diagram depicts the whole setup.
Create the VPC
First of all, we’re going to create a custom VPC.
- Open the Amazon VPC console at https://console.aws.amazon.com/vpc/
- Navigate to Your VPCs > Create VPC
- Under Resources to create, choose VPC only
- Enter the following data the click on Create VPC
- Name: heissler-vpc
- IPv4 CIDR manual input: yes
- IPv4 CIDR: 10.0.0.0/16
- No IPv6 CIDR block: yes
Create the subnets
We now create the two subnets in the VPC.
First the public subnet:
- Open the Amazon VPC console at https://console.aws.amazon.com/vpc/
- Navigate to Subnets > Create subnet
- Under VPC select the VPC id: heissler-vpc
- Enter the following data the click on Create subnet
- Subnet name: heissler-subnet-public
- IPv4 CIDR block: 10.0.0.0/24
Then the private subnet:
- Navigate to Subnets > Create subnet
- Under VPC select the VPC id: heissler-vpc
- Enter the following data the click on Create subnet
- Subnet name: heissler-subnet-private
- IPv4 CIDR block: 10.0.1.0/24
Create the security groups
We will create a security group for the NAT instance:
- Open the Amazon VPC console at https://console.aws.amazon.com/vpc/
- In the navigation pane, choose Security Groups, and then choose Create Security Group
- In the Create Security Group dialog box, specify heissler-sg-nati as the name of the security group, and provide a description. Select the heissler-vpc from the VPC list, and then choose Yes, Create
- Select the heissler-sg-nati security group that you just created. The details pane displays the details for the security group, plus tabs for working with its inbound and outbound rules
- Add rules for inbound traffic using the Inbound Rules tab as follows:
- Choose Edit inbound rules
- Choose Add rule, and specify the rules as follows. Then choose Save
- Add rules for outbound traffic using the Outbound Rules tab as follows:
- Choose Edit outbound rules
- Choose Addrule, and specify the rules as follows. Then choose Save
Then we create a security group for the webserver. Repeat the above steps, using the following inputs:
- Name: heissler-sg-webserver
- Inbound rules
- Outbound rules
Then we create a security group for the mailserver. Repeat the above steps, using the following inputs:
- Name: heissler-sg-mailserver
- Inbound rules
- Outbound rules
Then we create a security group for the database server. Repeat the above steps, using the following inputs:
- Name: heissler-sg-dbserver
- Inbound rules
- Outbound rules
Create the Internet gateway
- Open the Amazon VPC console at https://console.aws.amazon.com/vpc/
- In the navigation pane, choose Internet Gateways, and then choose Create internet gateway
- Under Internet gateway settings enter the following data:
- Name tag: heissler-igw
- Choose Create internet gateway
- Select the internet gateway that you just created, and then choose Actions, Attach to VPC
- Select the heissler-vpc from the list, and then choose Attach internet gateway
Create the NAT instance
We’ll create an AMI with Amazon Linux 2 to run the NAT instance.
- Open the Amazon EC2 console at https://console.aws.amazon.com/ec2/
- Choose EC2 Dashboard, and then choose Launch instance
- Choose the Amazon Linux 2 AMI
- On the Choose an Instance Type page, choose the t3.nano instance type, and then choose Next: Configure Instance Details
- On the Configure Instance Details page, enter the following data:
- Network: heissler-vpc
- Subnet: heissler-subnet-public
- Auto-assign Public IP: Enable
- Choose Next: Add storage, then choose Next: Add tags
- On the Add Tags page, shown following, choose Add Tag, then enter Name for Key and enter heissler-nati for Value
- Choose Next: Configure Security Group when you are done
- On the Configure Security Group page, select the Select an existing security group option, and select the heissler-sg-nati security group that we’ve created earlier.
- Choose Review and Launch
Now, we’re going to disable source and destination checks on the NAT instance
- In the navigation pane, choose Instances
- Select the NAT instance, choose Actions, Networking, Change source/destination check
- Verify that source/destination checking is stopped. Otherwise, choose Stop
- Choose Save
We’re connecting to the NAT instance using the Instance Connect to configure settings inside the machine.
Inside the guest OS of the NAT instance we configure the following:
sudo sysctl -w net.ipv4.ip_forward=1
sudo /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo yum install iptables-services
sudo service iptables save
Create the route tables
First we create the main routing table.
- Open the Amazon VPC console at https://console.aws.amazon.com/vpc/
- In the navigation pane, choose Route Tables, and then choose Create route table
- In the Create route table dialog box, fill the following data
- Name: heissler-rtb-main
- VPC: heissler-vpc
- Then choose Create route table
- Select the custom route table that we just created.
- On the Routes tab, choose Edit routes, Add route, and add the following routes:
- Specify 0.0.0.0/0 in the Destination box, and select the NAT instance heissler-eni-natinstance in the Target list
- Choose Save changes
- On the Subnet associations tab, choose Edit subnet associations.
- Select the check box for the heissler-subnet-private subnet, and then choose Save associations
Now we create the public routing table.
- In the navigation pane, choose Route Tables, and then choose Create route table
- In the Create route table dialog box, fill the following data
- Name: heissler-rtb-public
- VPC: heissler-vpc
- Then choose Create route table
- Select the custom route table that we just created.
- On the Routes tab, choose Edit routes, Add route, and add the following routes:
- Specify 0.0.0.0/0 in the Destination box, and select the NAT instance heissler-igw in the Target list
- Choose Save changes
- On the Subnet associations tab, choose Edit subnet associations.
- Select the check box for the heissler-subnet-public subnet, and then choose Save associations
Create the Network ACLs
We create two NACLs, one for the private subnet, and one for the public subnet.
First, we create the NACL for the private subnet:
- Open the Amazon VPC console at https://console.aws.amazon.com/vpc/
- In the navigation pane, choose Network ACLs, and then choose Create network ACL
- Fill in the following data:
- Name: heissler-nacl-private
- VPC: heissler-vpc
- Choose Create network ACL
- In the Network ACL list, select the heissler-nacl-private NACL and choose Edit inbound rules from the Actions menu
- Add the following new rules, then click Save changes
- In the Network ACL list, select the heissler-nacl-private NACL and choose Edit outbound rules from the Actions menu
- Add the following new rules, then click Save changes
Now, we must associate the NACL with the private subnet:
- Open the Amazon VPC console at https://console.aws.amazon.com/vpc/
- In the navigation pane, choose Network ACLs, and then select the network ACL heissler-nacl-private
- In the details pane, on the Subnet Associations tab, choose Edit
- Select the Associate check box for the heissler-subnet-private subnet, and then choose Save.
Second, we create the NACL for the public subnet:
- Open the Amazon VPC console at https://console.aws.amazon.com/vpc/
- In the navigation pane, choose Network ACLs, and then choose Create network ACL
- Fill in the following data:
- Name: heissler-nacl-public
- VPC: heissler-vpc
- Choose Create network ACL
- In the Network ACL list, select the heissler-nacl-public NACL and choose Edit inbound rules from the Actions menu
- Add the following new rules, then click Save changes
- In the Network ACL list, select the heissler-nacl-public NACL and choose Edit outbound rules from the Actions menu
- Add the following new rules, then click Save changes
Now, we must associate the NACL with the public subnet:
- Open the Amazon VPC console at https://console.aws.amazon.com/vpc/
- In the navigation pane, choose Network ACLs, and then select the network ACL heissler-nacl-public
- In the details pane, on the Subnet Associations tab, choose Edit
- Select the Associate check box for the heissler-subnet-public subnet, and then choose Save.
Create and configure the database EC2 instance
- Open the Amazon EC2 console at https://console.aws.amazon.com/ec2/
- Choose EC2 Dashboard, and then choose Launch instance
- Choose the Debian 10 AMI
- On the Choose an Instance Type page, choose the t3.nano instance type, and then choose Next: Configure Instance Details
- On the Configure Instance Details page, enter the following data:
- Network: heissler-vpc
- Subnet: heissler-subnet-private
- Choose Next: Add storage, then choose Next: Add tags
- On the Add Tags page, choose Add Tag, then enter Name for Key and enter heissler-dbserver for Value
- Choose Next: Configure Security Group
- On the Configure Security Group page, select the Select an existing security group option, and select the heissler-sg-dbserver security group that we’ve created earlier
- Choose Review and Launch
Create and configure the webserver EC2 instance
- Open the Amazon EC2 console at https://console.aws.amazon.com/ec2/
- Choose EC2 Dashboard, and then choose Launch instance
- Choose the Debian 10 AMI
- On the Choose an Instance Type page, choose the t3.nano instance type, and then choose Next: Configure Instance Details
- On the Configure Instance Details page, enter the following data:
- Network: heissler-vpc
- Subnet: heissler-subnet-public
- Auto-assign Public IP: Enable
- Choose Next: Add storage, then choose Next: Add tags
- On the Add Tags page, choose Add Tag, then enter Name for Key and enter heissler-webserver for Value
- Choose Next: Configure Security Group
- On the Configure Security Group page, select the Select an existing security group option, and select the heissler-sg-webserver security group that we’ve created earlier
- Choose Review and Launch
Create and configure the mailserver EC2 instance
- Open the Amazon EC2 console at https://console.aws.amazon.com/ec2/
- Choose EC2 Dashboard, and then choose Launch instance
- Choose the Debian 10 AMI
- On the Choose an Instance Type page, choose the t3.nano instance type, and then choose Next: Configure Instance Details
- On the Configure Instance Details page, enter the following data:
- Network: heissler-vpc
- Subnet: heissler-subnet-public
- Auto-assign Public IP: Enable
- Choose Next: Add storage, then choose Next: Add tags
- On the Add Tags page, choose Add Tag, then enter Name for Key and enter heissler-mailserver for Value
- Choose Next: Configure Security Group
- On the Configure Security Group page, select the Select an existing security group option, and select the heissler-sg-mailserver security group that we’ve created earlier
- Choose Review and Launch
Now the three tier machines could be configured as needed. But this is another story 😉
Leave a Reply