Network ACL Rule Priority Conflict – Fix in 3 Steps

Network & Connectivity Intermediate 👁 11 views 📅 Jun 14, 2026

Network ACL rules in AWS or similar cloud platforms stop traffic when priorities overlap. Here's how to find and fix it fast.

The 30-Second Fix – Check Rule Numbers

Network ACLs process lowest rule number first. If you've got an allow rule at 100 and a deny rule at 200, the allow wins. But swap them — deny at 50, allow at 150 — and the deny blocks everything. That's your conflict.

Log into your cloud console (AWS, Azure, GCP — doesn't matter, they all work the same way). Open the Network ACL associated with your subnet. Look for rule numbers that overlap in the same direction (inbound or outbound). Every rule must have a unique number. If you see two rules with the same number, the ACL won't even apply — it'll error out silently.

Here's the quick check: list all rules, sort by number. If the rule you want to allow traffic has a higher number than a deny rule covering the same IP range and port, that's your culprit. Fix it by renumbering the allow rule to a lower number than the deny. Simple example:

Inbound rules (current):
100  Allow  10.0.1.0/24  TCP/443
200  Deny   10.0.1.0/24  TCP/443   ← This rule never runs

Fix:
50   Allow  10.0.1.0/24  TCP/443
100  Deny   10.0.1.0/24  TCP/443

Change the rule number in the console or using the API. Test traffic. If it works, you're done. If not, move to the moderate fix.

The 5-Minute Fix – Reorder and Audit Rule Boundaries

If renumbering didn't help, you've got a subtler conflict. The standard gap is 100 (rule 100, 200, 300). That's fine for most setups, but when you start adding rules in between — say rule 150 — you can accidentally create overlapping scopes. Or worse, a deny rule with a broad IP range (like 0.0.0.0/0) at a low number blocks everything you tried to allow at a higher number.

Here's the process:

  1. Export all ACL rules to a CSV or text file. In AWS, use the CLI: aws ec2 describe-network-acls --network-acl-ids acl-xxxxxxxx. This gives you every rule with its number, protocol, port range, and CIDR.
  2. Check for overlapping CIDR blocks. A deny rule for 10.0.0.0/16 at rule 50 will block traffic from 10.0.1.0/24 even if you allow it at rule 100. The more specific range doesn't matter — only rule number does. You need to move the allow rule below the deny in number order.
  3. Test with a packet capture tool like tcpdump on an EC2 instance. Run sudo tcpdump -i eth0 port 443 while trying to connect. If you see SYN packets arriving but no SYN-ACK going out, the outbound ACL is blocking. Check both inbound and outbound rules — people forget outbound rules all the time.
  4. Fix the ordering: Plan a new rule numbering scheme. Use gaps of 10 or 20 (10, 20, 30) so you can insert rules later without renumbering everything. Apply the changes. Re-test.

Still broken? Move to the advanced fix.

The 15+ Minute Fix – Full ACL Audit and Static Analysis

At this point, you've verified rule numbers and CIDR boundaries. The conflict is likely buried in a combination of multiple ACLs, subnet associations, or ephemeral ports. Here's how to dig it out.

Step 1: Check Subnet-to-ACL Mappings

A subnet can only be associated with one ACL at a time. If you've got multiple subnets with different ACLs, traffic between them might hit conflicting rules. For example, subnet A has an ACL allowing 10.0.2.0/24 outbound, but subnet B's ACL denies 10.0.1.0/24 inbound. That mismatch can look like a priority conflict but it's really a subnet boundary issue.

List all subnet associations for the ACL in question:

aws ec2 describe-network-acls --query 'NetworkAcls[].Associations[]'

If a subnet isn't explicitly associated, it uses the default VPC ACL (which allows all traffic). That can override your custom ACL if the subnet's default ACL is accidentally left in place. Always explicitly associate each subnet with the ACL you intend.

Step 2: Trace Ephemeral Port Rules

This is the #1 hidden ACL conflict. For TCP/UDP traffic, the return path uses ephemeral ports (1024-65535). Your outbound rules must allow traffic from your resource on its source port AND to the ephemeral range on the return. Many setups only allow return traffic on the specific port (e.g., 443). That won't work.

Standard ephemeral rule for outbound:

100  Allow  0.0.0.0/0  TCP/1024-65535  (source port range on response)

If you have a deny rule covering that port range at a lower number, the response gets dropped. For example:

50   Deny   10.0.0.0/8  TCP/1024-65535
100  Allow  0.0.0.0/0   TCP/1024-65535

The deny at rule 50 blocks responses from any IP in the 10.0.0.0/8 range. Fix: remove or renumber the deny rule so it doesn't apply to ephemeral ports. Or use a more specific deny rule that excludes the port range you need.

Step 3: Static Analysis with a Script

Write a quick Python script to parse your ACL rules and detect overlaps. Here's a minimal version:

import ipaddress
from collections import defaultdict

rules = [
    (50, 'deny', '10.0.0.0/16', 'TCP', '443'),
    (100, 'allow', '10.0.1.0/24', 'TCP', '443'),
]

cidr_rules = defaultdict(list)
for num, action, cidr, proto, port in rules:
    cidr_rules[proto+port].append((num, action, ipaddress.ip_network(cidr)))

for key, group in cidr_rules.items():
    group.sort()  # sorted by rule number
    for i, (num, action, net) in enumerate(group):
        for j, (num2, action2, net2) in enumerate(group[i+1:]):
            if net.overlaps(net2) and action != action2:
                print(f"Conflict: Rule {num} ({action}) overlaps with rule {num2} ({action2}) on {key}")

Run this against your full rule set. It'll flag every numeric overlap. Fix the ones where the lower-numbered rule is deny and the higher-numbered rule is allow, or vice versa in the wrong direction.

Step 4: Apply and Verify

Update the ACL rules. In AWS, you replace the entire rule set (you can't edit rules in place — you delete and recreate). Use the CLI or SDK. After applying, run connectivity tests from all affected resources. Use nc -vz target-ip 443 from a test instance to confirm the fix.

If you're still stuck after this, it's not an ACL conflict — look at security groups, routing tables, or the OS firewall. But 95% of the time, this process nails it.

Was this solution helpful?