Ravindra BagaleCourses & study guides मराठी Track your progress

Chapter 15: Amazon VPC — Subnets, Route Tables, NACL, NAT Gateway and Bastion Host

15.7 Network ACL: inbound and outbound rules, rule numbers and blocking an IP

A security guard stands at the entrance of the wing. He has a list of rules – he reads them in order and applies the first rule that matches. And this guard is forgetful: a person who went in is checked again when coming out. That is stateless. Note – technically, the NACL checks every packet at the boundary of the subnet.

A network ACL (NACL) is a firewall at the subnet level. It has inbound and outbound rules, and each rule either allows or denies traffic.

  • Every subnet is associated with exactly one network ACL; one network ACL can serve many subnets.
  • The default network ACL of a VPC allows all inbound and all outbound traffic.
  • A custom network ACL denies all inbound and outbound traffic until you add rules.
  • Each rule has a number from 1 to 32766. Rules are evaluated from the lowest number upwards, and the first matching rule wins; higher rules are not checked.
  • The last rule, shown as *, denies anything that matched no numbered rule. You cannot delete it.
  • Network ACLs are stateless: a reply is checked again as new traffic, so return traffic needs its own rule.
  • Rules are checked when traffic enters or leaves the subnet, not between instances inside the same subnet.
  • Quota: 20 inbound and 20 outbound rules per network ACL by default (adjustable up to 40 each).
A network ACL blocking one IP address with a low rule number Two requests arrive at the network ACL of the public subnet. The request from 203.0.113.25 matches rule 90, Deny, and is dropped at the subnet edge. The request from 198.51.100.7 does not match rule 90, matches rule 100, Allow HTTP, and reaches the web server. Rules are checked from the lowest number and the first match wins. 203.0.113.25 (example) 198.51.100.7 (example) Network ACL web-public-1a Nginx Inbound 90 All traffic 203.0.113.25/32 DENY Inbound 100 HTTP 80 0.0.0.0/0 ALLOW * All DENY rule 90 matched → dropped HTTP :80 HTTP :80

The network ACL checks rules from the lowest number. The request from 203.0.113.25 matches rule 90 Deny and is dropped at the subnet edge. The request from 198.51.100.7 skips rule 90, matches rule 100 Allow and reaches Nginx. Both addresses are documentation examples.

Why ephemeral ports 1024–65535 are needed

When a browser opens http://<WEB_PUBLIC_IP>, it connects from a random high source port (for example 52814) to port 80. The server's reply goes back to port 52814. That random port is an ephemeral port. Linux clients use 32768–60999, Windows clients 49152–65535, and a NAT gateway uses 1024–65535. So AWS suggests allowing 1024–65535:

  • outbound, for replies to visitors who connected to your servers,
  • inbound, for replies to connections your servers started (for example yum downloading updates).

Forget this, and the request arrives but the reply is dropped. A security group never needs this, because it is stateful.

Example: a custom network ACL for the public subnet

Inbound rules:

Rule # Type Protocol Port range Source Allow / Deny
90 All traffic All All 203.0.113.25/32 (documentation example of a bad IP) Deny
100 HTTP TCP 80 0.0.0.0/0 Allow
110 HTTPS TCP 443 0.0.0.0/0 Allow
120 SSH TCP 22 198.51.100.7/32 (documentation example of your IP) Allow
130 Custom TCP TCP 1024–65535 0.0.0.0/0 Allow
* All traffic All All 0.0.0.0/0 Deny

Outbound rules:

Rule # Type Protocol Port range Destination Allow / Deny
100 HTTP TCP 80 0.0.0.0/0 Allow
110 HTTPS TCP 443 0.0.0.0/0 Allow
120 Custom TCP TCP 1024–65535 0.0.0.0/0 Allow
130 SSH TCP 22 10.0.0.0/16 Allow
140 Custom TCP TCP 9000 10.0.2.0/24 Allow
* All traffic All All 0.0.0.0/0 Deny

Rule 90 is checked before rule 100, so the blocked address is dropped even though rule 100 allows port 80 for everyone. Outbound rules 130 and 140 let the bastion reach the private servers on SSH and let Nginx reach PHP-FPM on port 9000. The addresses 203.0.113.0/24 and 198.51.100.0/24 are reserved for documentation, so they are safe examples; use real addresses in your own rules.

How do I block one IP address or a whole range?

Security groups have no deny rules, so blocking is a network ACL job. The quickest way is to add a deny rule with a lower number than the allow rule to the network ACL that is associated with the subnet:

  1. VPC → Subnets → select web-public-1a → Network ACL tab → click the ACL ID.
  2. Inbound rules → Edit inbound rules → Add new rule.
  3. Rule number 90, Type All traffic, Source 203.0.113.25/32, Allow/Deny Deny.
  4. For a whole range, add another rule, for example Rule number 80, Source 203.0.113.0/24, Deny.
  5. Save changes. The change applies to every subnet using this ACL after a short time.
aws ec2 create-network-acl-entry --network-acl-id acl-0123456789abcdef0 --ingress \
  --rule-number 90 --protocol -1 --cidr-block 203.0.113.25/32 --rule-action deny

/32 means exactly one address; /24 blocks 256 addresses. A deny rule with a number higher than the allow rule (for example 200 after an allow-all rule 100) does nothing, because rule 100 matches first. Because every packet is checked, even an already open connection from the blocked address stops working.

Ravindra Bagale's Tip

Many students create a custom NACL, allow inbound 80, and the website times out. The reason: the NACL is stateless – replies need an outbound 1024-65535 rule. A security group doesn't need this, a NACL does. If the site went down after you changed the NACL, check the ephemeral ports rule first.

Ravindra Bagale's Tip

To block an IP, keep the deny rule's number lower than the allow rule – 90 before 100. Many students give the deny rule number 200 and then say "it doesn't block", because rule 100 matches first. And if you block your own IP by mistake, SSH goes too – remove the rule from the console. Remember the order.

Lab

Chala, find your own public IP with curl -s https://checkip.amazonaws.com. Add inbound rule 90, Deny, <YOUR_IP>/32 to the network ACL of the web server's subnet, and watch the web page time out in your browser (mobile data on your phone still works). Then delete rule 90 and refresh.