Troubleshooting ACL Misconfigurations
Access Control Lists are among the most commonly misconfigured
elements in Cisco IOS networks — and among the hardest to diagnose
by intuition alone. A single misplaced entry, an inverted wildcard
mask, an ACL applied in the wrong direction, or a missing
permit statement can silently block legitimate traffic
while appearing correct in the running configuration. Unlike routing
failures, where the problem is usually absence of reachability, ACL
problems are often selective: some traffic passes, some
does not, and the pattern of what works versus what fails is the
primary clue. Understanding that clue requires knowing exactly how
IOS processes ACL entries — sequentially, top to bottom, first match
wins, with an implicit deny any at the end that is
invisible in the configuration.
This lab covers every common ACL misconfiguration category:
incorrect entry ordering where a broad rule shadows a specific one,
implicit deny blocking all traffic when no explicit
permit covers it, wrong application direction
(inbound when outbound was intended and vice versa), wrong interface
placement for standard ACLs, incorrect wildcard masks producing
unintended matches, and ACL interactions with NAT, routing protocols,
and management traffic. The primary diagnostic tools are
show ip access-lists (for hit counters that reveal
which entries are matching) and debug ip packet (for
real-time packet-level visibility when counters alone are not enough).
Before starting this lab ensure you are familiar with standard ACL syntax at Standard ACL Configuration, extended ACL syntax at Extended ACL Configuration, wildcard mask calculation at Wildcard Masks, and ACL application at Applying ACLs to Interfaces.
1. How IOS Processes ACLs — The Rules That Cause Most Bugs
ACL Processing Rules
| Rule | Behaviour | Common Mistake |
|---|---|---|
| Sequential top-down processing | IOS evaluates ACE entries from the first line to the last, in the order they appear. The moment a packet matches an entry, IOS takes the permit or deny action and stops — no further entries are checked | Placing a broad permit any or permit 0.0.0.0 255.255.255.255 before a specific deny — the permit matches first and the deny is never reached |
| First match wins — no fall-through | Once a matching entry is found, the action is final. IOS does not continue checking remaining entries for a better or more specific match | Writing a specific deny after a broad permit that already covers the same traffic — the specific deny is unreachable and always has a hit count of zero |
| Implicit deny all at the end | Every ACL has an invisible final entry: deny ip any any (extended) or deny any (standard). It does not appear in show run or show ip access-lists but is always evaluated if no earlier entry matches |
Writing an ACL that permits specific traffic but forgetting to permit everything else — all other traffic is silently dropped by the implicit deny |
| Inbound vs outbound direction | Inbound (ip access-group NAME in) filters packets arriving on the interface before they reach the routing process. Outbound (ip access-group NAME out) filters packets leaving the interface after the routing decision |
Applying an inbound ACL on the wrong interface — traffic that should be filtered on ingress is already inside the network before the ACL is evaluated. Or applying an outbound ACL when inbound was needed, blocking traffic in the wrong direction |
| Standard ACL placement | Standard ACLs match only on source IP address. They should be placed as close to the destination as possible — applying a standard ACL near the source may block traffic to all destinations, not just the intended one | Applying a standard ACL on the interface closest to the source — it blocks the traffic before it can reach any destination, not just the intended denied destination |
| Extended ACL placement | Extended ACLs match on source IP, destination IP, protocol, and port. They should be placed as close to the source as possible — this prevents denied traffic from consuming bandwidth traversing the network only to be dropped at the destination | Applying an extended ACL near the destination when it could have been applied near the source, wasting bandwidth on traffic that will ultimately be denied |
| No editing of numbered ACLs | With numbered ACLs, you cannot insert an entry in the middle or delete a specific entry — the entire ACL must be deleted and re-entered. Named ACLs support sequence number reordering and individual entry deletion | Attempting to fix a numbered ACL by adding an entry — the new entry appends to the end and may never be reached if a broader entry earlier in the list matches first |
| ACL does not affect router-originated traffic | An outbound ACL on an interface does not filter traffic that originated from the router itself (routing protocol updates, SSH sessions, ping from the router). It only filters forwarded traffic passing through the router | Applying an outbound ACL expecting it to block the router's own OSPF hello packets or SSH responses — the traffic bypasses the outbound ACL entirely |
ACL Packet Processing Flow
Packet arrives on interface (INBOUND direction)
│
▼
┌─────────────────────────────────────────┐
│ Is an inbound ACL applied? │
│ YES → evaluate ACL top to bottom │
│ First match: PERMIT → continue │
│ First match: DENY → drop packet │
│ No match: implicit deny → drop │
│ NO → continue to routing │
└─────────────────────────────────────────┘
│ (permitted or no inbound ACL)
▼
Routing table lookup — determine exit interface
│
▼
┌─────────────────────────────────────────┐
│ Is an outbound ACL applied on the │
│ exit interface? │
│ YES → evaluate ACL top to bottom │
│ First match: PERMIT → forward │
│ First match: DENY → drop packet │
│ No match: implicit deny → drop │
│ NO → forward packet │
└─────────────────────────────────────────┘
KEY FACTS:
─────────────────────────────────────────────────────────────
● Only ONE ACL can be applied per interface per direction
(one inbound, one outbound — two ACLs maximum per interface)
● Applying a second ACL in the same direction replaces the first
● Inbound ACL is evaluated BEFORE routing — the router does not
know the destination interface yet when inbound ACL runs
● Outbound ACL is evaluated AFTER routing — the router has already
decided to forward the packet on this interface
● Traffic sourced BY the router (OSPF, BGP, ping, SSH responses)
is NOT filtered by outbound ACLs on the same router
2. Lab Topology & Fault Scenarios
PC-A (10.10.10.10) Server-Farm (10.20.20.0/24)
| |
Gi0/0 (10.10.10.1) Gi0/1 (10.20.20.1)
\ /
[ NetsTuts_R1 ]
Gi0/2 (203.0.113.1)
|
Internet / ISP
Management: SSH to NetsTuts_R1 from 10.10.10.0/24
OSPF: running between all routers
DHCP: R1 serving 10.10.10.0/24 from Gi0/0
NAT: inside on Gi0/0 and Gi0/1, outside on Gi0/2
┌────────────────────────────────────────────────────────────────┐
│ Fault Scenarios Covered in This Lab │
├───┬────────────────────────────────────────────────────────────┤
│ 1 │ Implicit deny — ACL blocks all traffic after specific │
│ │ permits because no final permit any is present │
├───┼────────────────────────────────────────────────────────────┤
│ 2 │ Wrong direction — ACL applied inbound that should be │
│ │ outbound (and vice versa) │
├───┼────────────────────────────────────────────────────────────┤
│ 3 │ Shadowed entry — broad permit before specific deny means │
│ │ the deny is never reached │
├───┼────────────────────────────────────────────────────────────┤
│ 4 │ Incorrect wildcard mask — matching unintended hosts or │
│ │ missing intended hosts │
├───┼────────────────────────────────────────────────────────────┤
│ 5 │ Standard ACL wrong interface — applied near source, │
│ │ blocking traffic to all destinations │
├───┼────────────────────────────────────────────────────────────┤
│ 6 │ ACL blocking routing protocol (OSPF hellos denied) │
├───┼────────────────────────────────────────────────────────────┤
│ 7 │ ACL blocking management traffic (SSH denied by policy ACL) │
├───┼────────────────────────────────────────────────────────────┤
│ 8 │ ACL interaction with NAT — ACL evaluated before NAT │
│ │ translation on inbound, after translation on outbound │
└───┴────────────────────────────────────────────────────────────┘
3. Primary Diagnostic Tools
show ip access-lists — Hit Counters Reveal What Is Matching
NetsTuts_R1#show ip access-lists
Extended IP access list INBOUND-POLICY
10 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 80 (45 matches)
20 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 443 (12 matches)
30 deny tcp any 10.20.20.0 0.0.0.255 eq 23 (0 matches)
40 permit ip any any (0 matches)
Standard IP access list SSH-ACCESS
10 permit 10.10.10.0 0.0.0.255 (3 matches)
20 deny any (0 matches)
clear ip access-list counters [name] before testing to
get clean baselines. Hit counters reset to zero on router reload.
For a full view of where ACLs are applied, see
show running-config.
show ip interface — Confirm ACL Application and Direction
NetsTuts_R1#show ip interface gi0/0 GigabitEthernet0/0 is up, line protocol is up Internet address is 10.10.10.1/24 Broadcast address is 255.255.255.255 ... Inbound access list is INBOUND-POLICY Outbound access list is not set NetsTuts_R1#show ip interface gi0/1 GigabitEthernet0/1 is up, line protocol is up Internet address is 10.20.20.1/24 ... Inbound access list is not set Outbound access list is SERVER-OUTBOUND
show ip interface [intf] is the definitive command for
confirming which ACL is applied to which interface and in which
direction. Always run this on every relevant interface at the
start of ACL troubleshooting — a common error is assuming an ACL
is applied when it is not, or assuming it is applied inbound when
it is actually outbound. The "Inbound access list is not set" /
"Outbound access list is not set" lines are definitive — if an
ACL should be active and this line shows "not set," the ACL is
either not applied or applied to a different interface. See also
show ip interface
brief.
debug ip packet — Real-Time Packet Visibility
! ══════════════════════════════════════════════════════════ ! CRITICAL: Always use an ACL to limit debug output ! Unrestricted "debug ip packet" on a production router ! generates one debug line per forwarded packet and WILL ! crash the router under any meaningful traffic load ! ══════════════════════════════════════════════════════════ ! ── Step 1: Create a debug filter ACL ──────────────────── NetsTuts_R1(config)#ip access-list extended DEBUG-FILTER NetsTuts_R1(config-ext-nacl)# permit ip host 10.10.10.10 host 10.20.20.50 NetsTuts_R1(config-ext-nacl)# permit ip host 10.20.20.50 host 10.10.10.10 NetsTuts_R1(config-ext-nacl)#exit ! ── Step 2: Enable packet debug with the ACL filter ────── NetsTuts_R1#debug ip packet DEBUG-FILTER IP packet debugging is on for access list DEBUG-FILTER ! ── Step 3: Generate test traffic (ping from PC-A) ─────── ! ── PC-A pings 10.20.20.50 ──────────────────────────────── ! ── Step 4: Read the debug output ──────────────────────── *Oct 16 15:22:01.123: IP: s=10.10.10.10 (GigabitEthernet0/0), \ d=10.20.20.50, len 100, rcvd 4 *Oct 16 15:22:01.124: IP: s=10.10.10.10 (GigabitEthernet0/0), \ d=10.20.20.50, len 100, access denied ! ── Step 5: ALWAYS disable debug immediately after testing NetsTuts_R1#undebug all All possible debugging has been turned off ! ── Step 6: Remove the debug filter ACL ────────────────── NetsTuts_R1(config)#no ip access-list extended DEBUG-FILTER
debug ip packet output provides two critical pieces
of information: the ingress interface in parentheses
(confirming which interface the packet arrived on and therefore which
inbound ACL it encounters) and the disposition
(rcvd 4 means the packet was received and is being
processed; access denied confirms an ACL entry dropped
it). The number after rcvd is the next-hop path type
— rcvd 4 means normal unicast forwarding. Always
disable debug immediately after the test with
undebug all to prevent CPU overload on production
routers. For safer long-running diagnosis, use EEM applets with
action syslog instead of interactive debug.
show ip access-lists vs show access-lists
| Command | Shows | Use When |
|---|---|---|
show ip access-lists |
IPv4 ACLs only — all named and numbered IPv4 ACLs with hit counters | Primary ACL diagnostic command for IPv4 — use this for all standard troubleshooting |
show access-lists |
All ACLs on the router — IPv4, IPv6, and MAC ACLs | When you are unsure whether IPv6 ACLs may also be a factor, or to get a complete ACL inventory |
show ip access-lists [name/number] |
A single named or numbered ACL with all entries and hit counters | When you know which specific ACL to inspect — cleaner output than listing all ACLs |
show ip interface [intf] |
ACL application status per interface — inbound and outbound ACL names | Confirming which ACL is applied to which interface in which direction — always the second command after show ip access-lists |
clear ip access-list counters [name] |
Resets hit counters to zero without removing the ACL or its entries | Before generating test traffic — gives a clean baseline showing only test-traffic matches |
4. Fault 1 — Implicit Deny: All Unmatched Traffic Silently Dropped
Scenario
The security team applied an ACL on Gi0/0 to permit HTTP and HTTPS from the LAN to the server farm. After the ACL was applied, all other traffic from the LAN — DNS, ICMP, SSH, and OSPF — stopped working. HTTP and HTTPS to the server farm continue to work.
Diagnose
! ── Step 1: Confirm which ACL is applied and where ────────
NetsTuts_R1#show ip interface gi0/0 | include access list
Inbound access list is INBOUND-POLICY
Outbound access list is not set
! ── Step 2: Examine the ACL entries and hit counters ──────
NetsTuts_R1#show ip access-lists INBOUND-POLICY
Extended IP access list INBOUND-POLICY
10 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 80 (145 matches)
20 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 443 (67 matches)
← no further entries visible — implicit deny any any follows
! ── What is blocked by the implicit deny? ────────────────
! ── DNS (UDP 53): 10.10.10.x → 8.8.8.8 ──────────────── BLOCKED
! ── ICMP: 10.10.10.x → any ──────────────────── BLOCKED
! ── SSH: 10.10.10.x → 10.10.10.1 ───────────── BLOCKED
! ── OSPF hellos: 10.10.10.x → 224.0.0.5 ─────────────── BLOCKED
! ── DHCP renewals: 10.10.10.x → 255.255.255.255 ────────── BLOCKED
! ── Step 3: Confirm with debug ip packet ─────────────────
NetsTuts_R1(config)#ip access-list extended DEBUG-FILTER
NetsTuts_R1(config-ext-nacl)# permit ip 10.10.10.0 0.0.0.255 any
NetsTuts_R1(config-ext-nacl)# permit ip any 10.10.10.0 0.0.0.255
NetsTuts_R1(config-ext-nacl)#exit
NetsTuts_R1#debug ip packet DEBUG-FILTER
*Oct 16 15:33:02.441: IP: s=10.10.10.10 (GigabitEthernet0/0), \
d=8.8.8.8, len 72, access denied
*Oct 16 15:33:04.883: IP: s=10.10.10.10 (GigabitEthernet0/0), \
d=10.10.10.1, len 52, access denied
NetsTuts_R1#undebug all
deny ip any any does not appear in
show ip access-lists output — it is always present
but never visible. Any packet that does not match entries 10 or 20
hits this silent deny. The zero visible entries below line 20
confirm that nothing else is being permitted. The high match counts
on entries 10 and 20 (HTTP and HTTPS) confirm those are working
correctly — all other traffic is being dropped invisibly. See
Standard ACLs and
Wildcard Masks for ACL
fundamentals.
Fix
! ── Add a final permit ip any any to prevent implicit deny ─
! ── Using named ACL — can add entries by sequence number ──
NetsTuts_R1(config)#ip access-list extended INBOUND-POLICY
NetsTuts_R1(config-ext-nacl)# 30 deny tcp any 10.20.20.0 0.0.0.255 eq 23
NetsTuts_R1(config-ext-nacl)# 40 permit ip 10.10.10.0 0.0.0.255 any
NetsTuts_R1(config-ext-nacl)# 50 permit udp any any eq 53
NetsTuts_R1(config-ext-nacl)# 60 permit icmp 10.10.10.0 0.0.0.255 any
NetsTuts_R1(config-ext-nacl)#exit
! ── Verify the updated ACL ────────────────────────────────
NetsTuts_R1#show ip access-lists INBOUND-POLICY
Extended IP access list INBOUND-POLICY
10 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 80
20 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 443
30 deny tcp any 10.20.20.0 0.0.0.255 eq 23
40 permit ip 10.10.10.0 0.0.0.255 any
50 permit udp any any eq 53
60 permit icmp 10.10.10.0 0.0.0.255 any
! ── After fix: clear counters and re-test ─────────────────
NetsTuts_R1#clear ip access-list counters INBOUND-POLICY
NetsTuts_R1#show ip access-lists INBOUND-POLICY
Extended IP access list INBOUND-POLICY
10 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 80 (45 matches)
20 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 443 (22 matches)
30 deny tcp any 10.20.20.0 0.0.0.255 eq 23 (0 matches)
40 permit ip 10.10.10.0 0.0.0.255 any (312 matches)
50 permit udp any any eq 53 (0 matches)
60 permit icmp 10.10.10.0 0.0.0.255 any (0 matches)
permit ip 10.10.10.0 0.0.0.255 any) now
catches all traffic from the LAN subnet that was not already matched
by the specific HTTP/HTTPS entries or the Telnet deny. The
312 matches on line 40 confirm it is working — DNS, ICMP, SSH,
and all other LAN traffic is now permitted. Entries 50 and 60
show zero matches because entry 40 is already matching DNS and
ICMP — they are redundant but not harmful. If the policy requires
strict control, entries 50 and 60 could be removed and a more
refined permit structure used.
deny ip any any log
(with the log keyword so you can see what is being
dropped). If you want to permit all unmatched traffic, add
permit ip any any. Never rely on the implicit deny
without knowing exactly which traffic it will affect.
5. Fault 2 — Wrong Direction: Inbound When Outbound Was Intended
Scenario
The intent is to block Telnet (port 23) traffic from reaching the server farm (10.20.20.0/24). An ACL was applied inbound on Gi0/1 (the server-farm-facing interface). Now no traffic reaches the server farm at all — not just Telnet.
Diagnose
! ── Check ACL application on Gi0/1 ───────────────────────
NetsTuts_R1#show ip interface gi0/1 | include access list
Inbound access list is SERVER-POLICY
Outbound access list is not set
! ── Examine the ACL ───────────────────────────────────────
NetsTuts_R1#show ip access-lists SERVER-POLICY
Extended IP access list SERVER-POLICY
10 deny tcp any any eq 23 (0 matches)
20 permit tcp any 10.20.20.0 0.0.0.255 eq 80 (0 matches)
30 permit tcp any 10.20.20.0 0.0.0.255 eq 443 (0 matches)
! ── ALL entries show zero matches ────────────────────────
! ── Traffic to the server farm has zero hits on any line
! ── This means traffic is not reaching this ACL at all
! ── Think about the traffic flow: ────────────────────────
! ── PC-A (10.10.10.10) sends packets destined for 10.20.20.50
! ── Packet arrives on Gi0/0 (LAN interface)
! ── Router performs routing lookup → exit interface = Gi0/1
! ── If SERVER-POLICY is INBOUND on Gi0/1, it only filters
! ── packets ARRIVING FROM the server farm toward the router
! ── Traffic FROM PC-A going TO the server farm exits Gi0/1
! ── outbound → no inbound ACL applies
! ── Traffic FROM the server farm ARRIVING on Gi0/1 inbound
! ── → SERVER-POLICY is evaluated on return traffic
! ── This ACL is filtering traffic in the WRONG direction
Understanding Inbound vs Outbound Directions
Traffic flow: PC-A (10.10.10.10) → Server (10.20.20.50)
Gi0/0 [LAN side] NetsTuts_R1 Gi0/1 [Server-farm side]
──────────────── → → → (routing) → → → ────────────────
↑ ↑
Packet arrives HERE Packet exits HERE
as INBOUND on Gi0/0 as OUTBOUND on Gi0/1
To BLOCK this traffic (PC→Server):
✓ Apply ACL INBOUND on Gi0/0 (filter when it arrives from PC)
✓ Apply ACL OUTBOUND on Gi0/1 (filter when it is about to reach server)
✗ Apply ACL INBOUND on Gi0/1 ← WRONG: this filters server→router traffic
✗ Apply ACL OUTBOUND on Gi0/0 ← WRONG: this filters router→PC traffic
Traffic flow: Server (10.20.20.50) → PC-A (10.10.10.10) — RETURN TRAFFIC
Gi0/1 [Server-farm side] NetsTuts_R1 Gi0/0 [LAN side]
──────────────── → → → (routing) → → → ────────────────
↑ ↑
Return packet arrives HERE Return packet exits HERE
as INBOUND on Gi0/1 as OUTBOUND on Gi0/0
To BLOCK return traffic:
✓ Apply ACL INBOUND on Gi0/1 (filter return packets from server)
✓ Apply ACL OUTBOUND on Gi0/0 (filter return packets about to reach PC)
Fix
! ── Remove the incorrectly placed inbound ACL from Gi0/1 ──
NetsTuts_R1(config)#interface gi0/1
NetsTuts_R1(config-if)# no ip access-group SERVER-POLICY in
NetsTuts_R1(config-if)#exit
! ── Apply the ACL outbound on Gi0/1 (correct direction) ──
NetsTuts_R1(config)#interface gi0/1
NetsTuts_R1(config-if)# ip access-group SERVER-POLICY out
NetsTuts_R1(config-if)#exit
! ── Verify correct application ───────────────────────────
NetsTuts_R1#show ip interface gi0/1 | include access list
Inbound access list is not set
Outbound access list is SERVER-POLICY
! ── Clear counters and re-test ────────────────────────────
NetsTuts_R1#clear ip access-list counters SERVER-POLICY
! ── Test: PC-A pings and opens HTTP to 10.20.20.50 ───────
! ── Then check hit counters ───────────────────────────────
NetsTuts_R1#show ip access-lists SERVER-POLICY
Extended IP access list SERVER-POLICY
10 deny tcp any any eq 23 (0 matches) ← no Telnet attempted
20 permit tcp any 10.20.20.0 0.0.0.255 eq 80 (18 matches) ← HTTP working
30 permit tcp any 10.20.20.0 0.0.0.255 eq 443 (7 matches) ← HTTPS working
6. Fault 3 — Shadowed Entry: Broad Permit Before Specific Deny
Scenario
The security team intended to permit all traffic from the LAN
except Telnet to the server farm. The ACL was written with a broad
permit ip any any first, then a specific
deny tcp for Telnet. Telnet sessions to the server
farm are still succeeding — the deny is not working.
Diagnose
! ── Examine the ACL and its hit counters ──────────────────
NetsTuts_R1#show ip access-lists OUTBOUND-POLICY
Extended IP access list OUTBOUND-POLICY
10 permit ip any any (892 matches)
20 deny tcp any 10.20.20.0 0.0.0.255 eq 23 (0 matches)
! ── Entry 20 has ZERO matches ─────────────────────────────
! ── Entry 10 has 892 matches — every single packet ────────
! ── The "permit ip any any" on line 10 matches ALL traffic ─
! ── Telnet packets are IP traffic → they match line 10 ────
! ── IOS never reaches line 20 (first match wins) ──────────
! ── Line 20 is effectively unreachable — a dead entry ─────
! ── Confirm by trying Telnet to a server ─────────────────
! ── (Telnet from PC-A to 10.20.20.50 succeeds)
! ── Then re-check counters: still 0 matches on line 20 ───
NetsTuts_R1#show ip access-lists OUTBOUND-POLICY
Extended IP access list OUTBOUND-POLICY
10 permit ip any any (901 matches) ← counter increased (Telnet matched here)
20 deny tcp any 10.20.20.0 0.0.0.255 eq 23 (0 matches) ← still zero
deny entry that should be
actively blocking traffic — while traffic the deny should block
is clearly passing — is the classic signature of a shadowed entry.
The broad permit ip any any on line 10 is a superset
of all traffic, including Telnet. Since Telnet is IP traffic,
it matches line 10, gets permitted, and IOS never evaluates line
20. The deny on line 20 will never match a single packet as long
as line 10 exists above it.
Fix — Reorder Entries: Specific Before General
! ── WRONG order: broad permit before specific deny ────────
! ── Line 10: permit ip any any ← too broad, catches everything
! ── Line 20: deny tcp any ... eq 23 ← unreachable, never matches
! ── CORRECT order: specific deny before broad permit ──────
! ── For a named ACL: delete the entries and re-add in order
NetsTuts_R1(config)#ip access-list extended OUTBOUND-POLICY
! ── Delete the current entries ───────────────────────────
NetsTuts_R1(config-ext-nacl)# no 10
NetsTuts_R1(config-ext-nacl)# no 20
! ── Re-add in correct order: deny first, permit after ────
NetsTuts_R1(config-ext-nacl)# 10 deny tcp any 10.20.20.0 0.0.0.255 eq 23
NetsTuts_R1(config-ext-nacl)# 20 permit ip any any
NetsTuts_R1(config-ext-nacl)#exit
! ── Verify ───────────────────────────────────────────────
NetsTuts_R1#show ip access-lists OUTBOUND-POLICY
Extended IP access list OUTBOUND-POLICY
10 deny tcp any 10.20.20.0 0.0.0.255 eq 23
20 permit ip any any
! ── Clear counters, test Telnet (should fail) and HTTP ────
NetsTuts_R1#clear ip access-list counters OUTBOUND-POLICY
! ── After test ───────────────────────────────────────────
NetsTuts_R1#show ip access-lists OUTBOUND-POLICY
Extended IP access list OUTBOUND-POLICY
10 deny tcp any 10.20.20.0 0.0.0.255 eq 23 (4 matches) ← Telnet blocked
20 permit ip any any (237 matches) ← all else permitted
no access-list [number] to delete the entire ACL,
then re-enter all entries in the correct order — but be aware
this causes a brief period where no ACL is applied to the
interface.
Reordering Numbered ACLs — The Safe Method
! ── For NUMBERED ACLs: must delete entire list and re-enter
! ── Use "ip access-list resequence" to adjust numbering ───
! ── Step 1: Note current ACL (copy from show run) ─────────
NetsTuts_R1#show ip access-lists 110
Extended IP access list 110
10 permit ip any any
20 deny tcp any 10.20.20.0 0.0.0.255 eq 23
! ── Step 2: Delete the entire numbered ACL ────────────────
NetsTuts_R1(config)#no access-list 110
! ── Step 3: Re-enter in correct order ────────────────────
NetsTuts_R1(config)#access-list 110 deny tcp any 10.20.20.0 0.0.0.255 eq 23
NetsTuts_R1(config)#access-list 110 permit ip any any
! ── Note: the interface ip access-group binding remains ───
! ── after "no access-list" — re-applying is not needed ───
! ── But there is a brief window with no ACL protection ───
! ── SAFER: convert to named ACL, reorder, then switch ────
! ── Named ACLs support individual entry deletion/insertion
! ── Create equivalent named ACL in correct order ─────────
NetsTuts_R1(config)#ip access-list extended OUTBOUND-POLICY
NetsTuts_R1(config-ext-nacl)# 10 deny tcp any 10.20.20.0 0.0.0.255 eq 23
NetsTuts_R1(config-ext-nacl)# 20 permit ip any any
NetsTuts_R1(config-ext-nacl)#exit
! ── Swap the interface to the named ACL atomically ────────
NetsTuts_R1(config)#interface gi0/1
NetsTuts_R1(config-if)# no ip access-group 110 out
NetsTuts_R1(config-if)# ip access-group OUTBOUND-POLICY out
NetsTuts_R1(config-if)#exit
! ── Remove old numbered ACL ───────────────────────────────
NetsTuts_R1(config)#no access-list 110
7. Fault 4 — Incorrect Wildcard Mask: Wrong Hosts Matched
Scenario
The intent is to permit only host 10.10.10.10 to SSH into the router. A standard ACL is configured. After applying it, all hosts in 10.10.10.0/24 can SSH — not just 10.10.10.10. In a second example, an entry intended to permit the entire 10.20.20.0/24 subnet is accidentally only permitting a single host.
Diagnose — Wildcard Too Broad
! ── Examine the SSH access ACL ───────────────────────────
NetsTuts_R1#show ip access-lists SSH-ACCESS
Standard IP access list SSH-ACCESS
10 permit 10.10.10.0 0.0.0.255 (47 matches)
20 deny any (0 matches)
! ── Entry 10 permits the ENTIRE 10.10.10.0/24 subnet ─────
! ── Wildcard 0.0.0.255 means: match any value in the last
! ── octet → any host from 10.10.10.0 to 10.10.10.255
! ── But the intent was to permit ONLY host 10.10.10.10 ──
! ── To permit only a single host, the wildcard must be ───
! ── 0.0.0.0 (all octets must match exactly)
! ── Equivalent to using the "host" keyword ───────────────
! ── Confirm by checking which hosts are actually matching ─
! ── 47 matches means multiple hosts used SSH successfully ─
Wildcard Mask Quick Reference
| Intent | Address | Wildcard | IOS Shorthand | Matches |
|---|---|---|---|---|
| Single host | 10.10.10.10 | 0.0.0.0 | host 10.10.10.10 |
10.10.10.10 only |
| /24 subnet | 10.10.10.0 | 0.0.0.255 | — | 10.10.10.0 – 10.10.10.255 |
| /16 subnet | 10.10.0.0 | 0.0.255.255 | — | 10.10.0.0 – 10.10.255.255 |
| /28 subnet | 10.10.10.16 | 0.0.0.15 | — | 10.10.10.16 – 10.10.10.31 |
| Any host | 0.0.0.0 | 255.255.255.255 | any |
All IPv4 addresses |
| Odd hosts only | 0.0.0.1 | 0.0.0.254 | — | Any IP ending in an odd number (1, 3, 5…) |
Fix — Correct the Wildcard Mask
! ── Fix 1: Permit only host 10.10.10.10 (not the whole subnet)
NetsTuts_R1(config)#ip access-list standard SSH-ACCESS
NetsTuts_R1(config-std-nacl)# no 10
NetsTuts_R1(config-std-nacl)# 10 permit host 10.10.10.10
NetsTuts_R1(config-std-nacl)#exit
! ── Verify ───────────────────────────────────────────────
NetsTuts_R1#show ip access-lists SSH-ACCESS
Standard IP access list SSH-ACCESS
10 permit 10.10.10.10 (matches uses "host" — exact match only)
20 deny any
! ── Fix 2: Permit subnet when wildcard accidentally set to host
! ── Bad entry: permit 10.20.20.0 0.0.0.0 (matches only .0 — the
! ── network address, not any host in the subnet)
! ── Good entry: permit 10.20.20.0 0.0.0.255 (matches .0 to .255)
NetsTuts_R1(config)#ip access-list extended INBOUND-POLICY
NetsTuts_R1(config-ext-nacl)# no 40
NetsTuts_R1(config-ext-nacl)# 40 permit ip 10.20.20.0 0.0.0.255 any
NetsTuts_R1(config-ext-nacl)#exit
! ── Wildcard mask calculation: ───────────────────────────
! ── Subnet mask: 255.255.255.0
! ── Wildcard mask: 0.0.0.255 (invert the subnet mask)
! ── Network bits: match exactly (0 in wildcard = must match)
! ── Host bits: any value (1 in wildcard = don't care)
10.10.10.10 0.0.0.255 matches
10.10.10.0 – 10.10.10.255 (not just 10.10.10.10), because the
last octet is all "don't care." The correct mask for a single
host is 0.0.0.0 or the host keyword.
See Wildcard Masks for
full calculation guidance.
8. Fault 5 — Standard ACL Wrong Interface: Too Close to Source
Scenario
The intent is to block PC-A (10.10.10.10) from reaching only the server farm (10.20.20.0/24), while allowing PC-A to reach the Internet via Gi0/2. A standard ACL was applied inbound on Gi0/0 (the LAN interface, closest to PC-A). Now PC-A cannot reach the Internet either — both server farm and Internet access are blocked.
Diagnose
! ── Check where the standard ACL is applied ──────────────
NetsTuts_R1#show ip interface gi0/0 | include access list
Inbound access list is BLOCK-PC-A
Outbound access list is not set
NetsTuts_R1#show ip access-lists BLOCK-PC-A
Standard IP access list BLOCK-PC-A
10 deny 10.10.10.10 (38 matches)
20 permit any (5 matches)
! ── The ACL logic appears correct: deny host, permit rest ─
! ── But PC-A cannot reach the Internet (203.0.113.x) ─────
! ── DEBUG confirms all 10.10.10.10 traffic is denied ──────
NetsTuts_R1(config)#ip access-list extended DEBUG-FILTER
NetsTuts_R1(config-ext-nacl)# permit ip host 10.10.10.10 any
NetsTuts_R1(config-ext-nacl)#exit
NetsTuts_R1#debug ip packet DEBUG-FILTER
*Oct 16 15:55:01.221: IP: s=10.10.10.10 (GigabitEthernet0/0), \
d=8.8.8.8, len 60, access denied
*Oct 16 15:55:01.224: IP: s=10.10.10.10 (GigabitEthernet0/0), \
d=203.0.113.50, len 60, access denied
NetsTuts_R1#undebug all
Fix — Move Standard ACL Close to the Destination
! ── Remove ACL from Gi0/0 (wrong placement) ──────────────
NetsTuts_R1(config)#interface gi0/0
NetsTuts_R1(config-if)# no ip access-group BLOCK-PC-A in
NetsTuts_R1(config-if)#exit
! ── Apply outbound on Gi0/1 (server-farm interface) ──────
! ── Now: only traffic EXITING toward the server farm
! ── is checked — Internet traffic exits Gi0/2
! ── and is not affected by this ACL at all
NetsTuts_R1(config)#interface gi0/1
NetsTuts_R1(config-if)# ip access-group BLOCK-PC-A out
NetsTuts_R1(config-if)#exit
! ── Verify placement ─────────────────────────────────────
NetsTuts_R1#show ip interface gi0/0 | include access list
Inbound access list is not set
Outbound access list is not set
NetsTuts_R1#show ip interface gi0/1 | include access list
Inbound access list is not set
Outbound access list is BLOCK-PC-A
! ── Clear counters and re-test ────────────────────────────
NetsTuts_R1#clear ip access-list counters BLOCK-PC-A
! ── Test 1: PC-A tries to reach server farm ──────────────
! ── Test 2: PC-A tries to reach Internet ─────────────────
NetsTuts_R1#show ip access-lists BLOCK-PC-A
Standard IP access list BLOCK-PC-A
10 deny 10.10.10.10 (12 matches) ← server farm access blocked ✓
20 permit any (31 matches) ← all other traffic via Gi0/1 permitted ✓
! ── PC-A can now reach the Internet (Gi0/2 has no ACL) ───
9. Fault 6 — ACL Blocking OSPF: Routing Protocol Traffic Denied
Scenario
After applying an extended ACL to filter inbound traffic on Gi0/0, the OSPF neighbour relationship with the remote router drops. The ACL was written to block specific TCP flows but inadvertently also blocks OSPF hello packets.
Diagnose
! ── OSPF neighbour is down ───────────────────────────────
NetsTuts_R1#show ip ospf neighbor
! ── (empty output — no neighbours) ───────────────────────
! ── Check recent syslog for OSPF neighbour down message ──
NetsTuts_R1#show logging | include OSPF
*Oct 16 16:01:22: %OSPF-5-ADJCHG: Process 1, Nbr 10.10.10.2 on \
GigabitEthernet0/0 from FULL to DOWN, Neighbor Down: Dead timer expired
! ── Examine the ACL on Gi0/0 ─────────────────────────────
NetsTuts_R1#show ip access-lists INBOUND-POLICY
Extended IP access list INBOUND-POLICY
10 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 80 (220 matches)
20 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 443 (89 matches)
30 deny tcp any any eq 23 (0 matches)
40 permit ip 10.10.10.0 0.0.0.255 any (1450 matches)
← no permit for OSPF multicast (224.0.0.5, 224.0.0.6)
! ── OSPF uses IP protocol 89 (not TCP/UDP)
! ── OSPF hellos sent to multicast 224.0.0.5
! ── Source: the neighbour's IP (10.10.10.2)
! ── Entry 40 permits 10.10.10.0/24 → matches 10.10.10.2 ─
! ── BUT: OSPF destination is 224.0.0.5 (multicast) ───────
! ── Entry 40: permit ip 10.10.10.0 0.0.0.255 any
! ── source: 10.10.10.0/24 ✓ (10.10.10.2 matches)
! ── destination: any ✓ (224.0.0.5 matches "any")
! ── So OSPF SHOULD be permitted by entry 40... ────────────
! ── Check if there is a deny BEFORE entry 40 ─────────────
! ── Check the full ACL more carefully:
NetsTuts_R1#show ip access-lists INBOUND-POLICY
Extended IP access list INBOUND-POLICY
10 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 80
20 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 443
30 deny tcp any any eq 23
35 deny ip any 224.0.0.0 0.0.0.255 ← !! denies all multicast
40 permit ip 10.10.10.0 0.0.0.255 any
! ── Entry 35 denies ALL traffic destined for 224.0.0.x ───
! ── OSPF hellos go to 224.0.0.5 → matched by entry 35 ───
! ── They are denied BEFORE reaching entry 40 ─────────────
any) and are destined for 224.0.0.5 (matching entry
35's destination 224.0.0.0 0.0.0.255). The fix is to
add explicit permits for OSPF before the multicast deny. For OSPF
configuration and neighbour troubleshooting, see
OSPF Single-Area Configuration
and show logging.
Fix
! ── Insert a permit for OSPF BEFORE the multicast deny ───
NetsTuts_R1(config)#ip access-list extended INBOUND-POLICY
! ── Add entry 33 (between 30 and 35) — permits OSPF ──────
NetsTuts_R1(config-ext-nacl)# 33 permit ospf any host 224.0.0.5
NetsTuts_R1(config-ext-nacl)# 34 permit ospf any host 224.0.0.6
NetsTuts_R1(config-ext-nacl)# 36 permit ospf any any
NetsTuts_R1(config-ext-nacl)#exit
! ── Verify OSPF neighbour re-establishes ─────────────────
! ── (wait up to 40 seconds for dead timer / hello interval)
NetsTuts_R1#show ip ospf neighbor
Neighbor ID Pri State Dead Time Address Interface
10.10.10.2 1 FULL/DR 00:00:35 10.10.10.2 GigabitEthernet0/0
! ── Verify the updated ACL ────────────────────────────────
NetsTuts_R1#show ip access-lists INBOUND-POLICY
Extended IP access list INBOUND-POLICY
10 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 80 (258 matches)
20 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 443 (91 matches)
30 deny tcp any any eq 23 (0 matches)
33 permit ospf any host 224.0.0.5 (12 matches) ← OSPF hellos passing ✓
34 permit ospf any host 224.0.0.6 (3 matches) ← DR/BDR hellos passing ✓
35 deny ip any 224.0.0.0 0.0.0.255 (0 matches)
36 permit ospf any any (0 matches) ← fallback (never reached)
40 permit ip 10.10.10.0 0.0.0.255 any (1672 matches)
10. Fault 7 — ACL Blocking Management: SSH Denied by Policy ACL
Scenario
An inbound ACL on Gi0/2 (the Internet-facing WAN interface) was applied to block inbound traffic from the Internet. After applying it, the NOC team can no longer SSH to the router from the 10.10.10.0/24 LAN — even though SSH arrives on Gi0/0 (LAN side), not Gi0/2.
Diagnose
! ── Check which interfaces have ACLs applied ─────────────
NetsTuts_R1#show ip interface gi0/0 | include access list
Inbound access list is INBOUND-POLICY
Outbound access list is not set
NetsTuts_R1#show ip interface gi0/2 | include access list
Inbound access list is WAN-INBOUND
Outbound access list is not set
! ── Examine the LAN-side inbound ACL ─────────────────────
NetsTuts_R1#show ip access-lists INBOUND-POLICY
Extended IP access list INBOUND-POLICY
10 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 80
20 permit tcp 10.10.10.0 0.0.0.255 10.20.20.0 0.0.0.255 eq 443
30 deny tcp any any eq 23
40 permit ip 10.10.10.0 0.0.0.255 any
! ── Does the LAN ACL permit SSH from 10.10.10.x? ─────────
! ── Entry 40: permit ip 10.10.10.0 0.0.0.255 any
! ── SSH (TCP 22) from 10.10.10.10 to 10.10.10.1 should match
! ── But what is the DESTINATION of the SSH packet? ────────
! ── SSH to router management IP: 10.10.10.1 (Gi0/0 IP)
! ── The packet arrives INBOUND on Gi0/0 ──────────────────
! ── INBOUND ACL on Gi0/0 is applied to ARRIVING packets ──
! ── The SSH packet source is 10.10.10.10 (matches entry 40)
! ── The SSH packet destination is 10.10.10.1 (router itself)
! ── Entry 40 permits this → should work...
! ── Check VTY line access class ──────────────────────────
NetsTuts_R1#show run | section line vty
line vty 0 4
access-class SSH-ACCESS in
transport input ssh
! ── Check the VTY access-class ACL ───────────────────────
NetsTuts_R1#show ip access-lists SSH-ACCESS
Standard IP access list SSH-ACCESS
10 permit 10.10.10.0 0.0.0.255 (0 matches) ← should match but zero hits
20 deny any
! ── Zero matches on the permit entry despite attempts ─────
! ── Re-check: what IP is the SSH client using to connect? ─
! ── The NOC uses SSH to 10.10.10.1 (Gi0/0 IP) ────────────
! ── But the ACL SSH-ACCESS has permit 10.10.10.0 0.0.0.255 ─
! ── This matches the SOURCE address of the SSH client ─────
! ── The source is 10.10.10.10 → DOES match the permit ─────
! ── Something else must be denying it — check all ACLs ───
NetsTuts_R1#show ip access-lists
Extended IP access list INBOUND-POLICY
...
30 deny tcp any any eq 23 (0 matches) ← denies Telnet (port 23)
...
! ── WAIT — is entry 30 blocking SSH? ─────────────────────
! ── "deny tcp any any eq 23" — port 23 is TELNET ─────────
! ── SSH is port 22 — this should NOT block SSH
! ── But let's check: was this meant to be port 22?
! ── Let's look at what port SSH actually uses:
NetsTuts_R1#show run | include access-list.*22
access-list 110 deny tcp any any eq 22 ← a NUMBERED ACL also exists!
! ── There is a SECOND ACL (numbered 110) blocking SSH ─────
NetsTuts_R1#show ip access-lists 110
Extended IP access list 110
deny tcp any any eq 22 (8 matches) ← 8 SSH attempts blocked!
permit ip any any
! ── Check if this numbered ACL is applied anywhere ────────
NetsTuts_R1#show ip interface gi0/0 | include access
Inbound access list is INBOUND-POLICY
Outbound access list is not set
NetsTuts_R1#show ip interface gi0/2 | include access
Inbound access list is WAN-INBOUND
Outbound access list is not set
! ── Access-list 110 is not applied to any interface ───────
! ── But it has 8 matches — how? ───────────────────────────
! ── VTY LINE can have its own access-class independent ────
! ── of interface ACLs. Check: ────────────────────────────
NetsTuts_R1#show run | section line vty
line vty 0 4
access-class 110 in ← numbered ACL 110 applied to VTY lines!
transport input ssh
access-class
on the VTY lines, not on a physical interface. A VTY
access-class ACL filters management connections
(SSH, Telnet) to the router itself, independent of interface
ACLs. The numbered ACL 110 has a deny tcp any any eq 22
as its first entry — blocking all SSH connections. The 8 hit count
confirms the SSH attempts were reaching this ACL and being denied.
For SSH and VTY configuration, see
SSH Configuration and
Login Security
& Brute-Force Protection.
Fix
! ── Remove the incorrect VTY access-class ────────────────
NetsTuts_R1(config)#line vty 0 4
NetsTuts_R1(config-line)# no access-class 110 in
NetsTuts_R1(config-line)# access-class SSH-ACCESS in
NetsTuts_R1(config-line)#exit
! ── Fix or remove numbered ACL 110 ───────────────────────
NetsTuts_R1(config)#no access-list 110
! ── Verify SSH works from LAN ─────────────────────────────
NetsTuts_R1#show ip access-lists SSH-ACCESS
Standard IP access list SSH-ACCESS
10 permit 10.10.10.0 0.0.0.255 (3 matches) ← SSH sessions now matching ✓
20 deny any (0 matches)
11. Fault 8 — ACL and NAT Interaction: Address Translation Timing
Scenario
An inbound ACL on Gi0/2 (WAN/Internet interface) is intended to block all traffic from the Internet except return traffic to established sessions and traffic destined for the DMZ server at 203.0.113.10 (the public IP of a server). The ACL permits 203.0.113.10 specifically, but the DMZ server's real (post-NAT) address is 10.20.20.50. Traffic from the Internet to 203.0.113.10 is being blocked even though the ACL has a permit for that address.
NAT and ACL Processing Order
INBOUND packet on Gi0/2 (outside/WAN interface):
─────────────────────────────────────────────────────────────
Step 1: Inbound ACL evaluated ← uses PRE-NAT address
(Internet source IP, PUBLIC destination IP 203.0.113.10)
Step 2: NAT translation applied ← 203.0.113.10 → 10.20.20.50
Step 3: Routing decision made
Step 4: Outbound ACL evaluated (if any on exit interface)
KEY: For INBOUND packets on the OUTSIDE interface:
ACL is evaluated BEFORE NAT translation
→ ACL must use the PUBLIC (pre-NAT) address
→ Do NOT use the private (post-NAT) internal address in the ACL
OUTBOUND packet on Gi0/2 (outside/WAN interface):
─────────────────────────────────────────────────────────────
Step 1: Routing decision made
Step 2: NAT translation applied ← 10.10.10.10 → 203.0.113.x (PAT)
Step 3: Outbound ACL evaluated ← uses POST-NAT address
(PUBLIC source IP after PAT, Internet destination IP)
KEY: For OUTBOUND packets on the OUTSIDE interface:
ACL is evaluated AFTER NAT translation
→ ACL sees the PUBLIC (post-NAT) source address
→ Do NOT use the private (pre-NAT) internal address in outbound ACL
Diagnose
! ── Check the WAN inbound ACL ────────────────────────────
NetsTuts_R1#show ip access-lists WAN-INBOUND
Extended IP access list WAN-INBOUND
10 permit tcp any host 203.0.113.10 eq 80 (0 matches) ← zero hits!
20 permit tcp any host 203.0.113.10 eq 443 (0 matches) ← zero hits!
30 deny ip any any (47 matches) ← everything denied
! ── The permit entries for 203.0.113.10 have zero matches ─
! ── Entry 30 (deny any any) has 47 matches ───────────────
! ── Traffic to 203.0.113.10 is being denied ──────────────
! ── Verify ACL is applied correctly ──────────────────────
NetsTuts_R1#show ip interface gi0/2 | include access list
Inbound access list is WAN-INBOUND ← correct interface and direction
! ── Check NAT static mapping for the DMZ server ──────────
NetsTuts_R1#show ip nat translations | include 203.0.113.10
Pro Inside global Inside local Outside local Outside global
tcp 203.0.113.10:80 10.20.20.50:80 --- ---
tcp 203.0.113.10:443 10.20.20.50:443 --- ---
! ── NAT is correctly translating 203.0.113.10 → 10.20.20.50
! ── ACL is using correct PUBLIC address 203.0.113.10 ──────
! ── INBOUND on WAN interface: ACL evaluated BEFORE NAT ───
! ── So why is entry 10 (permit 203.0.113.10) not matching? ─
! ── Check if 203.0.113.10 is actually the destination ─────
! ── or if traffic arrives with a DIFFERENT destination ─────
NetsTuts_R1(config)#ip access-list extended DEBUG-FILTER
NetsTuts_R1(config-ext-nacl)# permit ip any host 203.0.113.10
NetsTuts_R1(config-ext-nacl)# permit ip any host 203.0.113.1
NetsTuts_R1(config-ext-nacl)#exit
NetsTuts_R1#debug ip packet DEBUG-FILTER
*Oct 16 16:44:01.334: IP: s=1.2.3.4 (GigabitEthernet0/2), \
d=203.0.113.10, len 60, access denied
! ── The destination IS 203.0.113.10 — the ACL should match ─
! ── But it is being denied (entry 30 matched, not entry 10)
! ── Re-examine the ACL more carefully ────────────────────
NetsTuts_R1#show ip access-lists WAN-INBOUND
Extended IP access list WAN-INBOUND
5 deny ip any host 203.0.113.10 (47 matches) ← HIDDEN entry at seq 5!
10 permit tcp any host 203.0.113.10 eq 80 (0 matches)
20 permit tcp any host 203.0.113.10 eq 443 (0 matches)
30 deny ip any any (0 matches)
deny ip any host
203.0.113.10 — is matching all traffic to the DMZ server
before entries 10 and 20 have a chance to permit HTTP/HTTPS.
This entry denies all IP traffic to 203.0.113.10 (not just
specific protocols), so HTTP and HTTPS traffic is caught here
and denied. This is both a shadowed-entry problem and an entry
that was apparently added without reviewing the existing ACL
first. The key diagnostic lesson: always run
show ip access-lists [name] with the full output
before concluding which entry should be matching — there may be
lower-numbered sequence entries that are not visible with a
partial display. For NAT configuration, see
Static NAT
Configuration and
Dynamic NAT &
PAT Configuration.
Fix
! ── Remove the incorrect broad deny at sequence 5 ─────────
NetsTuts_R1(config)#ip access-list extended WAN-INBOUND
NetsTuts_R1(config-ext-nacl)# no 5
NetsTuts_R1(config-ext-nacl)#exit
! ── Verify the fixed ACL ─────────────────────────────────
NetsTuts_R1#show ip access-lists WAN-INBOUND
Extended IP access list WAN-INBOUND
10 permit tcp any host 203.0.113.10 eq 80
20 permit tcp any host 203.0.113.10 eq 443
30 deny ip any any
! ── Clear counters and re-test ────────────────────────────
NetsTuts_R1#clear ip access-list counters WAN-INBOUND
! ── After Internet client connects to 203.0.113.10:80 ────
NetsTuts_R1#show ip access-lists WAN-INBOUND
Extended IP access list WAN-INBOUND
10 permit tcp any host 203.0.113.10 eq 80 (11 matches) ← DMZ HTTP ✓
20 permit tcp any host 203.0.113.10 eq 443 (4 matches) ← DMZ HTTPS ✓
30 deny ip any any (83 matches) ← other blocked ✓
12. Complete ACL Troubleshooting Workflow
! ══════════════════════════════════════════════════════════ ! STEP 1: Identify symptoms — what traffic is affected? ! ══════════════════════════════════════════════════════════ ! ── Is ALL traffic blocked, or only specific traffic? ! ── Does the failure happen in one direction only? ! ── Did the problem start after an ACL was applied/changed? ! ── What is the source IP, destination IP, and port/protocol? ! ══════════════════════════════════════════════════════════ ! STEP 2: Find all ACLs applied on the relevant path ! ══════════════════════════════════════════════════════════ NetsTuts_R1#show ip interface gi0/0 | include access list NetsTuts_R1#show ip interface gi0/1 | include access list NetsTuts_R1#show ip interface gi0/2 | include access list ! ── Check VTY lines for access-class ───────────────────── NetsTuts_R1#show run | section line vty ! ══════════════════════════════════════════════════════════ ! STEP 3: Examine each ACL — read entries AND hit counters ! ══════════════════════════════════════════════════════════ NetsTuts_R1#show ip access-lists ! ── Look for: zero matches on permit entries that should be active ! ── Look for: high match counts on deny entries ! ── Look for: entries missing (implicit deny at end) ! ── Look for: entries in wrong order (broad before specific) ! ── Look for: wildcard masks that are too broad or too narrow ! ══════════════════════════════════════════════════════════ ! STEP 4: Clear counters, generate specific test traffic, ! re-read counters to trace the exact matching path ! ══════════════════════════════════════════════════════════ NetsTuts_R1#clear ip access-list counters ! ── Generate test traffic (ping, curl, SSH attempt from test host) NetsTuts_R1#show ip access-lists ! ── Which entry's counter incremented? → that is what matched ! ══════════════════════════════════════════════════════════ ! STEP 5: Use debug ip packet with a filter ACL if counters ! are insufficient to pinpoint the problem ! ══════════════════════════════════════════════════════════ NetsTuts_R1(config)#ip access-list extended DEBUG-FILTER NetsTuts_R1(config-ext-nacl)# permit ip host [src] host [dst] NetsTuts_R1(config-ext-nacl)# permit ip host [dst] host [src] NetsTuts_R1(config-ext-nacl)#exit NetsTuts_R1#debug ip packet DEBUG-FILTER ! ── Generate test traffic, read debug output ! ── "access denied" = dropped by ACL ! ── "rcvd 4" = forwarded normally NetsTuts_R1#undebug all NetsTuts_R1(config)#no ip access-list extended DEBUG-FILTER ! ══════════════════════════════════════════════════════════ ! STEP 6: Fix the ACL — reorder, add missing entries, ! correct wildcards, fix direction or interface ! ══════════════════════════════════════════════════════════ ! ── Named ACLs: delete and re-insert individual entries ─── ! ── Numbered ACLs: delete entire ACL and re-enter ───────── ! ══════════════════════════════════════════════════════════ ! STEP 7: Verify the fix ! ══════════════════════════════════════════════════════════ NetsTuts_R1#clear ip access-list counters ! ── Re-generate test traffic NetsTuts_R1#show ip access-lists ! ── Confirm expected entries are now matching (non-zero counts) ! ── Confirm blocked traffic entries are matching deny lines ! ── Confirm no unexpected implicit deny matches
13. ACL Troubleshooting Quick Reference
| Symptom | Diagnostic Finding | Root Cause | Fix |
|---|---|---|---|
| All traffic blocked after ACL applied — only specific flows work | show ip access-lists: ACL has only specific permits, no broad permit at the end. Implicit deny not visible |
Missing explicit permit for all other traffic — implicit deny at ACL end blocking everything not explicitly permitted | Add permit ip any any (or specific permits for needed protocols) as the final explicit entry. Add deny ip any any log if all-deny is intentional but logging is needed |
| ACL entries have zero matches despite traffic flowing | All ACE entries show 0 matches even for traffic that should be matching. Traffic is passing or being dropped but counters never increment | ACL is applied to the wrong interface or wrong direction — the traffic being tested never passes through this ACL | Run show ip interface [intf] | include access list on every interface in the traffic path. Confirm the ACL is on the correct interface and in the correct direction (in vs out) |
| Specific deny rule not working — blocked traffic passes through | Deny ACE shows 0 matches. Traffic that should be denied continues to pass. A higher-numbered permit ACE has a very high match count | Broad permit entry earlier in the ACL matches the traffic before the specific deny is evaluated — shadowed entry. First-match-wins means the deny is unreachable | Reorder ACL: specific deny entries must appear before any broad permit that could match the same traffic. For named ACLs, delete and re-insert with correct sequence numbers. For numbered ACLs, delete and re-enter the entire list |
| Wrong subnet or host being blocked/permitted | Debug shows unexpected source or destination addresses being matched. Traffic from unintended hosts is being permitted or denied | Incorrect wildcard mask — too broad (e.g., 0.0.0.255 when 0.0.0.0 was intended for a single host) or too narrow (0.0.0.0 when 0.0.0.255 was needed for a subnet) | Verify wildcard by calculating the address range it produces. Correct with no [seq] and re-enter with correct wildcard. Use host [ip] for single hosts, calculate subnet wildcard as inverse of subnet mask |
| Standard ACL blocks more traffic than intended | Traffic to unintended destinations is also being blocked. Standard ACL is applied close to the traffic source | Standard ACLs match only source IP — applied near the source, they block traffic to ALL destinations, not just the intended target | Move standard ACL to the interface closest to the destination. Remove from source-side interface with no ip access-group [name] [in|out] and apply on the destination-side interface in the appropriate direction |
| Routing protocol (OSPF/EIGRP) neighbour drops after ACL applied | show ip ospf neighbor: no neighbours. show logging: ADJCHG dead timer expired. show ip access-lists: routing protocol multicast addresses hit a deny entry |
ACL blocking routing protocol traffic — OSPF/EIGRP multicast destinations (224.0.0.5, 224.0.0.6, 224.0.0.10) matched by a deny entry before a routing protocol permit | Add explicit permits for the routing protocol before the deny that is matching it: permit ospf any any and/or permit eigrp any any. Use sequence numbers to insert these permits before the problematic deny entry |
| SSH to router blocked despite correct interface ACL | Interface ACL permits SSH. VTY access-class ACL found via show run | section line vty. VTY ACL has a deny entry for SSH (port 22) |
VTY access-class is filtering management connections independently of interface ACLs. A separate VTY ACL (often numbered) is blocking SSH |
Examine and correct the VTY access-class ACL. Ensure the ACL permits the management source subnet with permit [source] [wildcard] before any deny entries |
| Inbound WAN ACL blocking NAT traffic to internal server | ACL permit entry for public server IP has zero matches. Debug shows traffic with correct destination is being denied by implicit deny or earlier deny entry | Either: (1) a hidden lower-sequence deny entry is matching before the permit; or (2) the ACL uses the private (post-NAT) address instead of the public (pre-NAT) address — for inbound WAN ACLs, ACL is evaluated before NAT translation | Verify full ACL with show ip access-lists [name]. Remove any unexpected deny entries. For NAT, confirm the ACL uses the public (outside) IP address — the address as it appears in the packet before NAT translates it |
Key Points & Exam Tips
- show ip access-lists with hit counters is the most important ACL diagnostic command. Zero matches on a permit entry that should be active means traffic is either not reaching this ACL (wrong interface/direction) or a higher-priority entry is matching it first. High match counts on an unexpected deny entry reveals what is being blocked.
- The implicit deny any at the end of every ACL is invisible in
show ip access-listsandshow run, but it is always there and always active. Every ACL without an explicit final permit will drop all traffic not matched by an earlier permit. When debugging, consider the implicit deny as a real entry — it counts all packets that fall through. - First match wins — no fall-through. Once an ACE matches a packet, the action is final. A specific deny placed after a broad permit will never be reached. The order of entries is the most common source of ACL bugs — always verify that specific entries appear before general entries.
- show ip interface [intf] | include access list is the definitive command for confirming which ACL is applied to which interface in which direction. Also use
show running-config | section line vtyto check VTY access-class ACLs. - Inbound ACL direction: filters packets arriving on the interface, before routing. Outbound ACL direction: filters packets leaving the interface, after routing. An inbound ACL on the server-farm interface filters return traffic (server to router), not forward traffic (client to server).
- Standard ACLs match source IP only — place them close to the destination. Extended ACLs match source IP, destination IP, protocol, and port — place them close to the source. Placing a standard ACL near the source blocks traffic to ALL destinations, not just the intended one.
- Wildcard mask errors are silent:
10.10.10.10 0.0.0.255looks like a host entry but actually matches the entire /24 subnet. Verify every wildcard by calculating the lowest and highest addresses it covers. Use thehostkeyword for single hosts and invert the subnet mask for subnets. - ACLs do not filter traffic originated by the router itself when applied outbound on the same router. An outbound ACL on Gi0/0 will not block OSPF hellos generated by the router's own OSPF process — it only filters forwarded traffic passing through the router.
- For NAT interaction: on the outside (WAN) interface inbound, ACL is evaluated before NAT translation — use the public (pre-NAT) address. On the outside interface outbound, ACL is evaluated after NAT translation — use the public (post-NAT) address. Using the private address in a WAN interface ACL will never match.
- On the exam: know the implicit deny behaviour, the first-match-wins rule, the difference in placement rules for standard vs extended ACLs, how to read hit counters to identify shadowed or misdirected ACEs, and the direction semantics of inbound vs outbound application.