AWS CloudFormation template for a VPC with NAT

I had trouble finding a nice generic CloudFormation template that would take the complexity and pain out of setting up a VPC with NAT so I made one myself.  Enjoy:


  1. Thanks. Had been trying to figure out where to specify the security group for the nat instance; kept getting errors specifying a security group and Networkinterfaces..

  2. Hi,

    Why do the NAT Security Group Ingress rules refer the NatSG to itself? Why not just list the CIDR Blocks? Thanks - Chris

  3. I found it easier/simpler to allow open communication within the non-routable internal instances. Using the CIDR blocks would have probably worked too, but I don't know if there would be any issues when trying to use fancy ports or protocols that way.

  4. Thank you for the response. I was having issues with doing this. My private subnet instances could not access public subnet instances and internet. Vice versa a public subnet instance could not access the private subnet instances. I'm probably not doing something as you intended. In the end my ingress rules just use the VPC CIDR block notation and it allowed access between pub and priv subnet instances. Do you see any issues with this? Also, thank you for posting this. This VPC template is actually one of the best examples I found. Thanks again

  5. Hi Christopher, I may be misunderstanding your situation but it sounds like you're bypassing the NAT instance and allowing direct communication between the subnets which sort of defeats the purpose of NAT. At a glance, the setup above provides this type of architecture:

    Internet <--> public subnet <--> NAT instance <-|security firewall|-> private subnet instance <--> private subnet instance

  6. P.S. You access the private instances through the NAT (which serves as a jump host)

  7. I have been struggling with CloudFront and this helped immensely so thank you! I had one question about referencing and editing default items like security groups and routes. At the moment of VPC creation you don't have a variable for these default items so is it possible to modify / reference them.

  8. Sorry for the delay...

    You can use Parameters or references (e.g. { "Ref" : "PrivateSubnet" }) to reference dynamic items at design time

  9. I'm a bit confused about what you're doing with your NAT and security groups in this template. I see that you create a NatSecurityGroup which allows inbound SSH (22) and RDP (3389) from the ServerAccess CIDR range. You are also adding ingress rules to allow ping, ssh, rdp, http and https between any instances also in the NatSecurityGroup, but I don't understand why you would apply this to your NAT instance.

    The only service hosted on the NAT instance is SSH and it won't forward traffic to any instances in your public or private subnets unless you also configure some sort of port forwarding rules, which I don't see in this template.

    Also you seemed to suggest in the comments that the NAT limits traffic between the public and private subnets, but that's not really the way NATs work. All subnets within a VPC can communicate freely, they don't have to talk through a NAT or firewall - the purpose of a NAT is to provide *outbound* internet access to instances in the private subnet, since those instances cannot access the internet directly via the Internet gateway the way that instances in the public subnet can.

    If you want to limit traffic between subnets in the same VPC, you would have to use Network ACLs, but that can add a lot of complexity, since ACLs are not stateful and so you have to create both inbound and outbound rules for all of your traffic.

    Am I misunderstanding your intention with the NAT?

  10. Hi,

    Great script, however I having one issue, after deploying I have to go console and change security group from custom IP to Anywhere and then it works. I'm leaving Cidip as
    Any idea what this is happening?

  11. Hi Andrew,

    Sorry for the confusion. I'm using the NAT instance also as a jump host (, which has a separate security role from a basic NAT's function. With the NAT instance's dual role as a security-conscientious jump host, I'm explicitly allowing certain port access to certain IPs. From the NAT (a.k.a. jump host) I can access any port on any of the private subnet instances. The magic that makes this happen in the template is the "NAT" line that says:

    "GroupSet" : [{ "Ref" : "NatSecurityGroup" }],

    And yes, using Network ACLs would be appropriate (albeit complex, as you noted) if I wanted to restrict access between the subnet instances but in my model I just use the non-routable 10.x IP range to prevent Internet snooping and focus all my access restriction efforts on the NAT/jump host instance.

    Hope that helps clarify things!

  12. Hi Unknown, I'm not sure I understand. I don't see a reference to "Cidip" in my template. Did you mean the "ServerAccess" value or one of the values in the "SubnetConfig" section?

  13. Very useful template, thanks!

  14. Thanks for providing this useful AWS Cloud formation template. Super helpful.

    Best Regards,
    CourseIng - AWS Online Training in Hyderabad

  15. Nice blog! Thanks for providing your information AWS Online Training


Post a Comment

Keep it clean and professional...

Popular Posts