Build a secure web application on AWS “the hard way”

Ek Danwanichakul
Jul 24, 2017 · 3 min read

The purpose of this post is to show you how to create a very secure web application on AWS “the hard way”. Why the hard way? This is because you can just use AWS default settings but you won’t understand and/or utilizing all of AWS core components.

VPC

  • Name: manual-vpc
  • Region: US-East-1
  • CIDR: 192.168.0.0/16

Private Subnets

  • Name: private-a-manual | private-b-manual
  • CIDR: 192.168.1.0/24 | 192.168.1.0/24
  • Availability zone: us-east-1a | us-east-2b

Public Subnets

  • Name: public-a-manual | public-b-manual
  • CIDR: 192.168.10.0/24 | 192.168.20.0/24
  • Availability zone: us-east-1a | us-east-2b

Internet Gateway

  • Name: ig-manual
  • Attach to manual-vpc

Route Table

  • Name: public-rt-manual
  • Destination: 0.0.0.0/0
  • Target: ig-manual
  • Subnet associations: public-a-manual, pubic-b-manual

Bastion Host — ec2 instance

  • Linux Distro: Amazon Linux
  • Instance Type: t2.micro
  • Network: manual-vpc
  • Subnet: public-a-manual
  • Name: Bastion Host
  • Auto-assign Public IP: use subnet setting(disable)
  • Volume type’s root: 8GB
  • Tags: Bastion Host
  • Security Group: Create a new security group
  • Security Group Name: bastion-host
  • Security Group Type: SSH
  • Security Group Port: 22
  • Source: Your home/office ip-address

Elastic IP

  • Instance: Bastion Host

At this point, you should be able to ssh into bastion host instance with ssh -K -i ~/.ssh/YOURKEY.pem ec2-user@ELASTIC-IP-ADDRESS (-K is for forwarding ssh-agent). Once you are in run sudo yum -y update to confirm that your instance can download and install update from the internet which means we have configured our public subnet correctly.

Next, let’s spin up two more ec2-instance that live in a private subnet, then we will try to ssh into those instances through our bastion host.

App1/App2 — ec2 instances

  • Linux Distro: Amazon Linux
  • Instance Type: t2.micro
  • Network: manual-vpc
  • Subnet: private-a-manual/private-b-manual
  • Name: app1/app2
  • Auto-assign Public IP: use subnet setting(disable)
  • Volume type’s root: 8GB
  • Tags: apps
  • Security Group: Create a new security group
  • Security Group Name: private-web
  • Security Group Type: SSH,HTTP
  • Security Group Port: 22,80
  • Source: 0.0.0.0/0

From bastion host, you should be able to run ssh ec2-user@APP1_PRIVATE_IP to login to app1 instance! Next, try to run sudo yum -y update , this won’t work because our instance has no way to route traffic to the internet since it sits in a private subnet that doesn’t have internet gateway attach to it. To solve this problem, we have to use Nat Gateway(Nat Instance).

Nat Gateway

  • Subnet: public-a-manual
  • Elastic IP Allocation ID: create a new one

Route Table

  • Name: private-rt-manual
  • Destination: 0.0.0.0/0
  • Target: nat-manual
  • Subnet associations: private-a-manual, private-b-manual

Now back to app1/app2 instance, try sudo yum -y update again and it should work!

Install Nginx(web server) on app1/app2

  • Run sudo yum -y install nginx && sudo service nginx start
  • Run curl -IL localhost , it should return http 200.

Next problem for us to solve is how to serve these two instances to the internet. If you noticed, there is no Public IP attached to the instance itself. To solve this, we can use a load balancer.

Load Balancer

  • Type: Classic Load Balance
  • Load Balance Name: lb-manual
  • Create LB Inside: manual-vpc
  • Load Balancer Protocol: HTTP
  • Load Balancer Port: 80
  • Instance Protocol: HTTP
  • Instance Port: 80
  • Subnets: public-a-manual, public-b-manual
  • Security group protocol: http/https
  • Security group port: 80/443
  • Security group source: 0.0.0.0/0
  • Health Check: leave it as default settings
  • Add EC2 Instances: app1, app2

AWS creates a DNS for us to use such as http://lb-manual-783608569.us-east-1.elb.amazonaws.com.

Conclusion

We’ve created a very secure web application that utilizes all of the core components of AWS such as VPC, Subnets, Network ACLs, Route Tables, Security Groups, Load Balancer, and EC2 instances!

I hope you like it. Please share, comment, like. I’d love to hear feedback from you. Lastly, don’t forget to be awesome!

Ek Danwanichakul

Written by

DevOps Engineer. Currently automate all the things @prattledata.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade