Configure and Verify Access Control Lists (ACLs)

Configure and verify access control lists

Imagine a busy office building with a security guard at the front desk. The guard has a list of rules: “Allow employees with a badge. Deny visitors without an appointment. Allow delivery staff only between 9 AM and 5 PM.” Every person who walks in is checked against this list, top to bottom, until a matching rule is found.

An Access Control List (ACL) does exactly this job inside a network device such as a Cisco router or switch. It is a list of rules that a router reads, in order, to decide whether to permit or deny a packet based on things like source IP address, destination IP address, protocol, or port number.

This article explains ACLs from first principles, shows you how to configure and verify them on Cisco IOS, explains the Linux equivalent, and gives you a Python script to simulate ACL logic. By the end, you will understand not just the commands, but why ACLs behave the way they do.

What Exactly Is an ACL?

An ACL is simply an ordered list of permit or deny statements. Each statement is called an Access Control Entry (ACE). When a packet arrives at an interface where an ACL is applied, the router compares the packet against each ACE from top to bottom. As soon as a match is found, the router applies that action (permit or deny) and stops checking further entries.

At the very end of every ACL, there is an implicit deny all statement. This means: if a packet does not match any rule you wrote, it is dropped by default. This single fact causes more real-world outages than almost anything else in networking — forgetting the implicit deny and blocking traffic you meant to allow.

Why ACLs Matter in Real Networks

ACLs serve three major purposes:

  1. Security filtering — blocking unwanted traffic (e.g., stopping the Finance VLAN from reaching the Guest Wi-Fi VLAN).
  2. Traffic classification — identifying “interesting traffic” for other features like NAT, QoS, or VPN encryption.
  3. Route filtering — controlling which routes are advertised or accepted by a routing protocol.

A real-world example: A company has a Guest Wi-Fi network. Guests should be able to reach the Internet but never touch the internal servers (192.168.10.0/24). An ACL on the router’s guest-facing interface enforces this boundary without needing a separate physical network.

Types of ACLs in Cisco IOS

ACL TypeNumber RangeFilters OnBest Placed
Standard1–99, 1300–1999Source IP address onlyClose to the destination
Extended100–199, 2000–2699Source IP, destination IP, protocol, portClose to the source
Named Standardip access-list standard NAMESource IPClose to destination
Named Extendedip access-list extended NAMESource, destination, protocol, portClose to source

Why placement matters: A standard ACL only sees the source address, so if you place it near the source, it may block traffic that was actually meant for a different destination too — it can’t tell the difference. Extended ACLs can be as specific as needed, so they should sit close to the traffic’s origin to stop unwanted packets as early as possible, saving bandwidth on the rest of the network.

How ACL Processing Works (Step by Step)

  1. Packet arrives at the interface.
  2. IOS checks if an ACL is applied inbound or outbound on that interface.
  3. If yes, the packet is compared to ACE #1. If it matches → action applied, stop.
  4. If not, move to ACE #2, and so on.
  5. If no ACE matches, the implicit deny any at the end drops the packet.
flowchart TD
    A[Packet Arrives at Interface] --> B{ACL Applied?}
    B -- No --> Z[Forward Packet Normally]
    B -- Yes --> C{Match ACE 1?}
    C -- Yes --> D[Apply Action: Permit/Deny]
    C -- No --> E{Match ACE 2?}
    E -- Yes --> D
    E -- No --> F{...more ACEs...}
    F -- No Match --> G[Implicit Deny Any: Drop Packet]

Wildcard Masks — The Part Everyone Finds Confusing

ACLs do not use subnet masks; they use wildcard masks, which work in reverse.

  • Subnet mask 255.255.255.0 means “these bits must match” for the network portion.
  • Wildcard mask 0.0.0.255 means “the first three octets must match exactly, ignore the last octet.”

Rule of thumb: wildcard = 255.255.255.255 - subnet mask

RequirementSubnet MaskWildcard Mask
Single host255.255.255.2550.0.0.0
/24 network255.255.255.00.0.0.255
/16 network255.255.0.00.0.255.255
Any address—any (shortcut for 0.0.0.0 255.255.255.255)

Configuring a Standard ACL on Cisco IOS

Scenario: Only allow the Admin PC (192.168.1.10) to Telnet/SSH into a router; deny everyone else.

Router(config)# access-list 10 permit host 192.168.1.10
Router(config)# access-list 10 deny any log

Router(config)# line vty 0 4
Router(config-line)# access-class 10 in

The log keyword is extremely useful — it makes the router generate a syslog message whenever this line is matched, which helps you see who is being blocked.

Configuring an Extended ACL on Cisco IOS

Scenario: Guest VLAN (192.168.20.0/24) can browse the web (HTTP/HTTPS) but cannot reach the internal server subnet (192.168.10.0/24).

Router(config)# ip access-list extended GUEST-RESTRICT
Router(config-ext-nacl)# deny ip 192.168.20.0 0.0.0.255 192.168.10.0 0.0.0.255
Router(config-ext-nacl)# permit tcp 192.168.20.0 0.0.0.255 any eq 80
Router(config-ext-nacl)# permit tcp 192.168.20.0 0.0.0.255 any eq 443
Router(config-ext-nacl)# deny ip any any log

Router(config)# interface GigabitEthernet0/1
Router(config-if)# ip access-group GUEST-RESTRICT in

Notice the order: the deny to internal servers comes first, before the general permit. If you reversed the order, guests could reach the servers via HTTP/HTTPS because the permit statement would match first.

Named ACLs and Editing with Sequence Numbers

Named ACLs are preferred in modern networks because you can insert or remove individual lines without deleting the whole ACL.

Router(config)# ip access-list extended GUEST-RESTRICT
Router(config-ext-nacl)# show
Router(config-ext-nacl)# 15 permit tcp 192.168.20.0 0.0.0.255 any eq 53

This inserts a new rule at sequence number 15, between existing lines 10 and 20, without disturbing them.

Verifying ACLs

Router# show access-lists
Router# show access-lists GUEST-RESTRICT
Router# show ip interface GigabitEthernet0/1
Router# show run | section access-list

show access-lists is the most important command — it also shows a match counter next to each line, telling you how many packets hit that rule. This is invaluable for troubleshooting.

Extended IP access list GUEST-RESTRICT
    10 deny ip 192.168.20.0 0.0.0.255 192.168.10.0 0.0.0.255 (34 matches)
    20 permit tcp 192.168.20.0 0.0.0.255 any eq www (152 matches)
    30 permit tcp 192.168.20.0 0.0.0.255 any eq 443 (980 matches)
    40 deny ip any any log (5 matches)

Common Mistakes and Troubleshooting

SymptomLikely CauseFix
All traffic blocked unexpectedlyForgot implicit deny anyAdd explicit permit statements as needed
ACL has no effectNot applied to interface, or applied to wrong directionCheck ip access-group direction (in/out)
Correct rule never matchesA broader rule earlier in the list already matchedReorder rules — specific before general
Can’t add a new rule in the middleUsing numbered ACL without gapsRecreate as named ACL, or use sequence numbers with gaps of 10
Router management locked outACL applied to VTY lines blocks admin’s own IPAlways test from console, never only from remote SSH session

Golden troubleshooting workflow:

  1. show access-lists — look at match counters, see which line is firing.
  2. show ip interface <intf> — confirm the ACL is actually applied and in the right direction.
  3. show run — confirm the ACL contents match your intent.
  4. Use log keyword to capture matched source/destination IPs in show logging.

ACLs on Linux (iptables / nftables)

Linux uses a similar concept called iptables (older) or nftables (modern). The same “top to bottom until match” logic applies.

# Allow SSH only from the admin host, drop all other SSH attempts
sudo iptables -A INPUT -p tcp -s 192.168.1.10 --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j DROP

# View the rules with packet/byte counters, similar to "show access-lists"
sudo iptables -L INPUT -v -n --line-numbers

The equivalent modern nft syntax:

sudo nft add rule inet filter input tcp dport 22 ip saddr 192.168.1.10 accept
sudo nft add rule inet filter input tcp dport 22 drop
sudo nft list ruleset

Simulating ACL Logic in Python

Understanding ACL matching logic is easier if you build a tiny simulator. This helps engineers reason about “first match wins” behavior before touching real hardware.

import ipaddress

# Each rule: (action, source_network)
acl = [
    ("deny", ipaddress.ip_network("192.168.20.0/24")),
    ("permit", ipaddress.ip_network("0.0.0.0/0")),
]

def check_acl(src_ip):
    ip = ipaddress.ip_address(src_ip)
    for action, network in acl:
        if ip in network:
            return action
    return "deny"  # implicit deny any

test_ips = ["192.168.20.5", "10.0.0.1", "8.8.8.8"]
for ip in test_ips:
    print(f"{ip}: {check_acl(ip)}")

Output:

192.168.20.5: deny
10.0.0.1: permit
8.8.8.8: permit

This mirrors exactly how Cisco IOS evaluates an ACL — first match wins, and there’s an implicit deny at the end.

Best Practices for ACLs

  • Always place more specific rules before general rules.
  • Use named ACLs with descriptive names (e.g., GUEST-TO-INTERNET) instead of numbers.
  • Add a final explicit deny ip any any log line, even though it’s implicit — it gives you visibility via logging.
  • Document each ACL with remark lines: Router(config-ext-nacl)# remark Block guest access to internal servers
  • Place extended ACLs close to the source, standard ACLs close to the destination.
  • Always test management-plane ACLs (VTY, SSH) from a console session first to avoid locking yourself out.
  • Use sequence numbers with gaps (10, 20, 30) so you can insert rules later.
  • Periodically review show access-lists counters — a rule with zero hits for months might be obsolete.

Real-World Example: Segmenting a Small Business Network

A small business has three VLANs: Management (10.0.1.0/24), Staff (10.0.2.0/24), and Guest (10.0.3.0/24). The security policy is:

  • Guest can only reach the Internet.
  • Staff can reach the Internet and internal file server (10.0.1.50).
  • Only Management can SSH into network devices.
ip access-list extended MGMT-ONLY-SSH
 permit tcp 10.0.1.0 0.0.0.255 any eq 22
 deny tcp any any eq 22 log
 permit ip any any

ip access-list extended GUEST-POLICY
 deny ip 10.0.3.0 0.0.0.255 10.0.1.0 0.0.0.255
 deny ip 10.0.3.0 0.0.0.255 10.0.2.0 0.0.0.255
 permit ip 10.0.3.0 0.0.0.255 any

This design uses layered ACLs: one protects the management plane, another segments guest traffic from internal resources — a pattern used in real enterprise and campus networks every day.

Conclusion

ACLs are one of the most foundational tools in networking — they underpin firewalling, NAT translation selection, VPN interesting traffic, QoS classification, and route filtering. The core idea is simple: an ordered list of rules, evaluated top-down, with an implicit deny at the end. Once you internalize wildcard masks and the “first match wins” principle, ACLs become predictable and powerful rather than confusing.

References

  1. Cisco IOS IP Access List documentation — https://www.cisco.com/c/en/us/support/docs/ip/access-lists/26448-ACLsamples.html
  2. Cisco Configuring IP Access Lists — https://www.cisco.com/c/en/us/support/docs/security/ios-firewall/23602-confaccesslists.html
  3. iptables man page — https://man7.org/linux/man-pages/man8/iptables.8.html
  4. nftables Wiki — https://wiki.nftables.org/
  5. RFC 791 – Internet Protocol — https://datatracker.ietf.org/doc/html/rfc791
  6. Cisco Named Access Control Lists — https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/sec_data_acl/configuration/xe-16/sec-data-acl-xe-16-book.html
  7. Python ipaddress module documentation — https://docs.python.org/3/library/ipaddress.html
Total
2
Shares

Leave a Reply

Previous Post
Describe the capabilities and function of TFTP/FTP in the network

Describe the Capabilities and Function of TFTP/FTP in the Network

Next Post
How to Configure device access control using local passwords

How to Configure Device Access Control Using Local Passwords

Related Posts