How to set up network ACL on Amazon Virtual Private Cloud?

dragos.luca picture dragos.luca · May 15, 2012 · Viewed 9.1k times · Source

I have set up an Amazon Virtual Private Cloud (VPC). Inside the VPC I have 2 networks in which I create instances. For security reasons I want to put some network access control lists (Network ACL) on those networks, besides the machines firewall. Following the Amazon example I have a public network (exposed to internet access) 10.0.0.0/24 and 3 private network 10.0.1.0/24, 10.0.2.0/24, 10.0.3.0/24. The traffic between them is routed.


So for the network 10.0.1.0/24 as ACL's I put this:

Inbound:
10.0.0.0/24 port 80 (HTTP)
10.0.0.0/24 port 22 (SSH)
10.0.2.0/24 port 3306 (MySql)
10.0.3.0/24 port 3306 (MySql)

Outbound
ALL ALL

For the networks 10.0.2.0/24 and 10.0.3.0/24:

Inbound 
10.0.1.0/24 port 3306 (MySql)

Outbound
ALL ALL

For the public network 10.0.0.0/24 in here I have an exposed load balancer, which is redirecting traffic to the private network 10.0.1.0/24, where an app is responding over HTTP:

Inbound
0.0.0.0/0 port 80 (HTTP)
0.0.0.0/0 port 443 (HTTPS)
0.0.0.0/0 port 22 (SSH)

Outbound
ALL ALL

The problem is, when I put those rules in action, all traffic freezes and the app is not available. What's happening? Am I doing something wrong?

Answer

Steffen Opel picture Steffen Opel · May 15, 2012

Update

Your rules are currently lacking an additional and likely relevant fragment related to the FAQ What are the differences between security groups in a VPC and network ACLs in a VPC?:

Security groups in a VPC specify which traffic is allowed to or from an Amazon EC2 instance. Network ACLs operate at the subnet level and evaluate traffic entering and exiting a subnet. Network ACLs can be used to set both Allow and Deny rules. Network ACLs do not filter traffic between instances in the same subnet. In addition, network ACLs perform stateless filtering while security groups perform stateful filtering. [emphasis mine]

This is addressed further in What is the difference between stateful and stateless filtering?:

Stateful filtering tracks the origin of a request and can automatically allow the reply to the request to be returned to the originating computer. [...]

Stateless filtering, on the other hand, only examines the source or destination IP address and the destination port, ignoring whether the traffic is a new request or a reply to a request. In the above example, two rules would need to be implemented on the filtering device: one rule to allow traffic inbound to the web server on tcp port 80, and another rule to allow outbound traffic from the webserver (tcp port range 49,152 through 65,535). [emphasis mine]

Now, you allow all outbound traffic already, so this doesn't apply as per the example, but the same issue applies the other way round as well, so e.g. for HTTP requests originating from your EC2 instances you'll need to have a corresponding inbound rule as outlined, see section Ephemeral Ports within Network ACLs for more details on this:

The client that initiates the request chooses the ephemeral port range. The range varies depending on the client's operating system. [...]

If an instance in your VPC is the client initiating a request, your network ACL must have an inbound rule to enable traffic destined for the ephemeral ports specific to the type of instance (Amazon Linux, Windows Server 2008, etc.).

In practice, to cover the different types of clients that might initiate traffic to public-facing instances in your VPC, you need to open ephemeral ports 1024-65535. [...]

Solution

Accordingly, section Recommended Rules for Scenario 2 within Appendix A: Recommended Network ACL Rules suggests the following inbound rule (OS dependent example) for your scenario:

Inbound:
0.0.0.0/0 port 49152-65535 (TCP)

To test whether this issue actually applies, you might simply include the entire ephemeral port range:

Inbound:
0.0.0.0/0 port 1024-65535 (TCP)

Initial Answer (obsolete)

For the public network 10.0.0.0/24 in here I have an exposed load balancer, which is redirecting trafic to the private network 10.0.1.0/24, where an app is responding over http

Your setup suggests you intend to terminate SSL on the load balancer as usual; given your increased security requirements you might actually have setup the Elastic Load Balancing for back-end HTTPS communication as well (see Architectural Overview) - you don't seem to have an ACL rule accommodating inbound HTTPS traffic to 10.0.1.0/24 though, so that would be the one missing in case:

Inbound:
10.0.0.0/24 port 80 (HTTP)
10.0.0.0/24 port 443 (HTTPS) // <= missing in your example currently!
10.0.0.0/24 port 22 (SSH)
10.0.2.0/24 port 3306 (MySql)
10.0.3.0/24 port 3306 (MySql)

Outbound
ALL ALL