How to build an Ubuntu NAT Gateway on AWS

At Earthlink we called it a "pocket net", a private net segment with no public access except outbound through a NAT based router. An Amazon AWS VPC can provide such, but I found the setup cumbersome, the "wizard" didn't work, and worst of all, I was stuck with a Red Hat NAT instance that couldn't run any of my usual Ubuntu scripts (mostly due to apt dependencies). I wrote this doc because in all of google-space, I could not find a concise guide, and certainly not on AWS.

With a little fiddling to get the AWS networking correct, plus a reminder from this link (tyvm) on how easy it was to get IP Tables to do NAT, I got a nice, simple solution up and running. I'll assume familiarity around the AWS service console screens and IP networking basics.

Get logged in and choose the AWS region/datacenter you want to work in. Nav to the VPC Dashboard and get started.

  1. Create a VPC. I like descriptive names, like that shown. All those AWS ids will drive you batty. Use a /16 private net segment, like that shown below Create VPC on block 10.0.0.0/16

  2. Create a /24 subnet, which will be your "pub" network for internet access. Be sure to put it on the VPC created above. Create 10.0.0.0/14 subnet

  3. Create another /24 as your private net. When done, you should have subnets after pri and pub created

  4. Create an Internet Gateway Create Internet Gateway

  5. Associate the gateway with your VPC Associate gateway with VPC

  6. Go to the Route Table page. Notice the VPC create already put a default table in. Auto created route table

  7. Rename that table as your public route table, that will route packets to the Internet Gateway Rename public route table

  8. Create another route table on your vpc for the private routing, between instances without a routeable public IP and the gateway NAT router. Create private route table

  9. That private subnet we create above is associated with the default route table, which we're using as public. Go back to the subnet section and associated the private subnet with the private route table. Change private subnet route table

  10. Now, back to the route tables. On the public route table, create a default route, 0.0.0.0/0, to the gateway. Add default pub route to igw

  11. If you go back to the subnet table, note that the public subnet now reflects that new route Public subnet has igw route

  12. Now we need Security Groups for the instances we'll create. For this project, a single SG that allows all traffic on the VPC, along with ssh from the outside. If I were creating a web cluster, I'd create another SG with the same, plus http and https for my webserver or load balancer. Security Group

  13. We also need a key pair, to protect login access to the NAT instance. That private key will download, guard it well, and get it ready to use with ssh. Create key pair

  14. The only other routing work is to associate a default route on the private net, i.e., in the private route table, with the NAT gateway. However, we don't have a NAT gateway instance yet, so...head to the EC2 dashboard and create an Ubuntu instance. (Micro will do fine for non-production work, but I plan to use this instance for other duty besides NAT, so I'm using t2.small.) Launch NAT instance

  15. Be sure to go through all the instance setup pages, especially the Instance Details. Get the right VPC and select your public subnet. VERY IMPORTANT: Change the "Auto-assign Public IP" value to "Enable". Instance Details

  16. Add the SG we created above to the instance... Add security group

  17. ...and add the key pair Select key pair

  18. When the NAT spins up, let's use an Elastic IP for it. Allocate a new EIP in the VPC Allocate elastic IP

  19. Select the instance, and associate that EIP with the NAT instance Associate elastic IP

  20. Another tricky bit: Disable Source/Destination check on the instance Disable S/D check

  21. Go back to the VPC dash, route tables. Select the private route table, and create a default route with dest as your NAT instance Private route table instance

  22. Ok, we're done with the AWS console stuff. Time to get on the NAT instance and do the final incantation to make it all work. Open a terminal, and using your public EIP

ssh -i ~/.ssh/slated/w-dev-2014.pem ubuntu@54.18.13.20

and once on the instance, confirm it has net access

curl http://google.com

And now, what makes the NAT and forwarding work (thank you iptables!):

echo '#!/bin/sh
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s 10.0.0.0/16 -j MASQUERADE
' | sudo tee /etc/network/if-pre-up.d/nat-setup
sudo chmod +x /etc/network/if-pre-up.d/nat-setup
sudo /etc/network/if-pre-up.d/nat-setup

Done! Well, except for using it...create an instance without a public IP, make sure it's on the private subnet of the VPC and has the all VPC SG assigned. You'll need to put your private key on the NAT instance to ssh to the new private node, but you should be good to go!