How to create AWS NAT and Bastion Hosts in VPC

Jephe Wu - http://linuxtechres.blogspot.com


Objective:  Use VPC wizard to create public and private subnets in different AZ and use NAT service for private subnets and access servers on private subnets through bastion host.

Steps:


1. Use VPC wizard to create required subnets.


We will create the following VPC network and subnets:
10.0.0.0/16 with subnets:

10.0.0.0/24 public subnet A in ap-southeast-2a with Elastic IP 1 hosting company web server and NAT box
10.0.1.0/24 private subnet C in ap-southeast-2a  hosting SQL server, access Internet through NAT box in public subnet A
10.0.10.0/24 public subnet B in ap-southeast-2b with Elastic IP 2 hosting a bostion server which is Windows 2008 R2 base OS, jumphost for accessing SQL server in subnet C
10.0.11.0/24 private subnet D in ap-southeast-2b hosting other servers or applications, accessing Internet through NAT box in public subnet A


Above wizard will only create subnet A and C and NAT box. 
After that, follow normal procedure to create Internet facing web server instance with elastic IP and automatic assigned or manually specified private IP e.g. 10.0.0.104/24

Eventually, we need to create 2 more subnet in another AZ manually to make it like this:

Network Diagram:
----Internet --- public subnet A (with 10.0.0.0/24)  --- private subnet C ( with 10.0.1.0/24)  [ ap-southeast-2a ]
----Internet ----pubic subnet B  (with 10.0.10.0/24) ---- private subnet D  (with 10.0.11.0/24) [ ap-southeast-2b ]
          

2. Configure NAT box
After finishing wizard, the NAT is up and running, you still need to configure the following to make it as masquerading NAT box for your entire VPC network 10.0.0.0/16, by default, it only allow the outbound Internet traffic.

  • check security group configuration of NAT box instance, by default, it doesn't allow the entire VPC 10.0.0.0/16 for incoming traffic which will block Internet access for all private subnets.
Also, check other settings such as disable src/destination check, the routing table for private subnet hosts routing table (must be pointing to NAT box ENI).

You can also ssh into NAT box from Internet to check iptables rules and ip forwarding:

[root@ip-10-0-0-104 ec2-user]# iptables -L -v -n -t nat | grep 10.0
  531 31715 MASQUERADE  all  --  *      eth0    10.0.0.0/16          0.0.0.0/0 

[root@ip-10-0-0-104 ec2-user]# more /proc/sys/net/ipv4/ip_forward
1

[root@ip-10-0-0-104 ec2-user]# grep nameserver /etc/resolv.conf 
nameserver 10.0.0.2

2.1 use NAT instance as port forwarding for RDS instance (e.g. to RDS Postgres)
Firstly make sure from Nat box e.g 10.0.20.254, you can telnet to e.g. 10.0.23.114 port 5432, then run commands below on NAT box
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 5432 -j DNAT --to 10.0.23.114:5432
iptables -A FORWARD -p tcp -d 10.0.23.114 --dport 5432 -j ACCEPT (might be optional)
iptables -A POSTROUTING -t nat -p tcp -s 0.0.0.0/0 -d 0.0.0.0/0 --dport 5432 -j SNAT --to 10.0.20.254
Note: 10.0.23.114 is the RDS internal ip and 10.0.20.254 is NAT internal ip 
Now add the external application ip into the NAT box security group to allow connection.

3. Configure Bostion Windows Server in public subnet C

Create another 2 more subnets C and D in another AZ ap-southeast-2b,  replace public subnet C routing table from ENI of NAT box to igw so that we can access it from Internet as jumphost.


4. Create SQL server database host in private subnet B
configure security group setting to only allow the internal IP of Bostion Windows server or the whole private subnet 10.0.0.0/16.

Notes for security group:
You can also specify another security group groupid in the customer IP part to quote the same security group settings. 

For either Linux or Windows server, if you remove your current connection source IP from security group while you are on the servers, the existing connection will be still okay, but if you exit ssh/rdp, the new connection won't be able to make.