ACLs Explained: How a Router Decides Allow or Deny
Every router and firewall answers the same question millions of times a day: should this packet be allowed through, or dropped? The answer comes from an access control list — a written checklist the device reads from the top, one line at a time, stopping at the first line that matches. Understand that one rule and the rest of ACLs falls into place.
What is an ACL in networking?
Here is the whole answer in a few sentences. An ACL — short for access control list — is a list of written rules stored on a router, switch or firewall. Every packet that reaches the device is checked against the list from the top down. The first line that matches the packet decides its fate: permit lets it through, deny drops it. If no line matches at all, an invisible final line — the implicit deny — drops the packet anyway. That is an ACL. Everything else in this guide is detail built on those four sentences.
Picture a nightclub door with a clipboard. The bouncer does not improvise: there is a written list, checked in order. "Anyone from the guest list — in." "Anyone wearing trainers — out." "Everyone else — out." The list only works because it is read in order, and because the last line quietly covers anyone the earlier lines forgot. A router does exactly this, except the clipboard is checked for every packet, millions of times a second, and the "guest list" is written in IP addresses.
First match wins: the one rule that runs everything
Most rule systems people meet — a settings page, a spreadsheet filter — feel like all the rules apply at once. ACLs are the opposite. The order of the lines is the logic. A broad permit near the top silently overrides every careful deny written beneath it, and a deny near the top can block traffic a later permit was written to allow. When an ACL misbehaves, the cause is almost never a wrong line — it is a right line in the wrong place.
Two consequences follow. First, specific lines belong above general lines: the exception ("let this one server through") must be read before the blanket rule ("block everyone") or the exception never happens. Second, some lines can be dead on arrival — if an earlier, broader line already matches everything a later line describes, the later line's match counter will sit at zero forever. It is not broken; it is shadowed, and finding shadowed lines is most of what auditing an old ACL means.
The invisible last line: implicit deny
Every IPv4 ACL ends with a line you never typed: deny any — drop everything, from anywhere, to anywhere. (IPv6 lists add two invisible permits for neighbour discovery just before their final deny; the principle is identical.) Vendors build it in so that a list can never accidentally allow traffic its author forgot to mention. Access control fails closed.
That safety net has a famous sharp edge. The moment you apply even a one-line ACL to an interface — say, a single permit for one management host — the implicit deny starts applying to everything else: user traffic, routing updates, the lot. "I only added one permit line" has taken down more networks than any deny line ever written. The discipline it teaches: before applying a list, ask not only "what does this allow?" but "what does the invisible line now block?"
Wildcard masks: addresses written backwards
Each line names the traffic it matches with an address plus a wildcard mask. You already know subnet masks: 255.255.255.0 means "the first three octets are the network, the last is the host". A wildcard mask is that idea flipped bit by bit. Where the wildcard has a 0, the address bit must match exactly. Where it has a 1, the device does not care what the bit is. So 198.51.100.0 0.0.0.255 means: first three octets must be exactly 198.51.100, last octet can be anything — the 256 addresses of that /24, in one line.
Two special cases cover most real lists. Wildcard 0.0.0.0 means every bit must match — one exact host, often written with the keyword host. Wildcard 255.255.255.255 means nothing must match — every address, written as the keyword any. And because wildcard bits do not have to be tidy, a mask like 0.0.0.254 can match only the even-numbered hosts of a subnet — a trick that is occasionally brilliant and frequently just confusing to whoever inherits the config.
Standard vs extended: how much of the packet the list can see
Cisco IOS, the dialect most ACL teaching uses, has two classic flavours. A standard ACL (numbered 1–99 and 1300–1999, or named) looks at the source address only: "traffic from this network: yes or no". It is simple, and because it cannot see the destination, it is traditionally placed close to the destination — blocking a source everywhere because of one forbidden target would be collateral damage. An extended ACL (numbered 100–199 and 2000–2699, or named) sees the full picture: protocol, source, destination, and ports — "TCP from the office subnet to that one server, on port 443 only". Extended lists can sit close to the source, dropping unwanted traffic before it crosses the network. Modern practice overwhelmingly uses named ACLs of either flavour, because a name like GUEST-WIFI-IN survives an audit better than the number 107, and named lists let you insert and delete individual lines.
One more placement fact matters: an ACL does nothing sitting in the config. It has to be applied — to an interface, in a direction (in or out), or to a feature like VTY lines or NAT. Direction is part of the meaning: "in" filters packets as they arrive at that interface, before routing; "out" filters them as they leave. The same list applied in two places is two different policies.
Reading a real ACL, line by line
Here is a small extended list guarding one web server. The addresses are documentation ranges (RFC 5737) — stand-ins for real networks, safe to copy. The server is 203.0.113.25; the office network is 198.51.100.0/24.
access-list 101 permit tcp 198.51.100.0 0.0.0.255 host 203.0.113.25 eq 443
Read it as a sentence: permit — TCP traffic — from any host in 198.51.100.0/24 — to exactly the host 203.0.113.25 — on destination port 443 (HTTPS). Office staff can reach the server's secure website.
access-list 101 deny tcp any host 203.0.113.25
Deny — TCP — from anywhere else — to that same server — on any port. Because it sits below line 1, it only catches what line 1 missed: the rest of the world. The server's other ports, and everyone outside the office, are turned away here.
(invisible) deny ip any any
Nobody typed this line, but it is enforced: anything still unmatched — UDP, other destinations if this list were applied more broadly — is dropped. Three lines, and the policy is complete: office HTTPS in, everything else to this server out, leftovers dropped.
When ACLs go wrong: the four classic diseases
1. Shadowed rules. A later line that can never fire because an earlier line already covers it. Real example, from the sample list our analyzer ships with: permit tcp any any eq 80 near the top allows all web traffic — so a deny tcp 10.0.0.0 0.255.255.255 any eq 80 written below it, meant to block one network's web access, does nothing at all. The traffic sails through line 1 and the deny is never read. The config looks protected; it is not.
2. Redundant rules. A line whose match is already handled, with the same verdict, by an earlier line. Harmless to traffic, corrosive to humans: the list grows, nobody dares delete anything, and audits slow to a crawl.
3. The overly broad permit. permit ip any any — allow everything, everywhere — turns up at the end of tired lists "to make it work". It permits the intended traffic and everything else too, and it makes the implicit deny unreachable. Our analyzer flags it on sight, and so should you.
4. The forgotten implicit deny. Covered above: apply a fresh list to a live interface without accounting for the invisible line, and legitimate traffic — often the routing protocol or the management access you are working through — stops. The fix is a habit: write the permits for the traffic the interface already carries first, then the new restrictions.
Try it yourself
Paste the sample list from this guide into the free Network ACL Analyzer — check a Cisco ACL in your browser: it flags the deny tcp 10.0.0.0 0.255.255.255 any eq 80 line as shadowed by the earlier permit tcp any any eq 80, and the closing permit ip any any as dangerously broad. Then take the next step and run a whole multi-device config through the network config verifier, which checks ACLs alongside duplicate IPs and routing mismatches, and see the traffic an ACL is filtering in the first place with the Wireshark filter builder.
- An ACL (access control list) is an ordered list of permit and deny lines stored on a router, switch or firewall. Each line describes a kind of traffic — a protocol, a source address range, a destination, often a port — and says what to do with packets that match it.
- The whole behaviour follows from one rule: top-down, first match wins. The device compares each packet against line 1, then line 2, and stops at the first line that matches. A line below a broader matching line can never fire — engineers call it shadowed, and it is the most common ACL bug.
- Every IPv4 ACL ends with an invisible final line: deny everything. If no written line matches a packet, the implicit deny drops it. Forgetting that hidden line is why a brand-new ACL applied to an interface can cut off traffic nobody meant to block.
- Wildcard masks are subnet masks flipped: a 0 bit means 'this bit must match' and a 1 bit means 'do not care'. The wildcard 0.0.0.255 checks the first three octets and ignores the last, matching exactly the /24 range — which is why ACL lines read like addresses written backwards.