A router, left to itself, forwards everything it receives. It has no opinions about traffic: if it has a route, it sends the packet on. The access list is the mechanism by which we give it, for the first time, the right to say no. It is also the language in which traffic is described on Cisco equipment - the same lists reappear later in NAT, in quality of service and in route filtering. This lecture starts from nothing: what a rule is, how a list is read, why the order of the lines decides everything, and why the mask used here is the other way round from everything you have learnt so far.
1Recap4 min
- A router makes a decision for each individual packet, on the basis of the routing table.
- The decision is made by longest prefix match: the most specific route wins.
- A packet with no route is discarded. The router neither keeps it nor guesses.
- The router decapsulates the frame, reads the IP header, then re-encapsulates the packet in a new frame on the outgoing interface.
- Routing must be configured in both directions - otherwise the answer has no way back.
The last point returns today, in a new and far more unpleasant form: it is not only routing that must be thought about in both directions, but filtering as well. A list that correctly permits the outbound traffic but forgets the return traffic produces exactly the same symptom - "it does not work" - for an entirely different reason.
Learning outcomes
- Explain what an ACL is and what it can identify in a packet
- Walk mentally through a list of rules and say exactly what happens to a given packet
- Calculate a wildcard mask and say what range of addresses it covers
- Choose between a standard and an extended list and know where each is placed
- Write named lists and edit a single line without rewriting everything
- Permit return traffic without opening the network from the outside
- Troubleshoot a list using the match counter
2The definition of an access list8 min
Imagine the router has, on every door, a sheet of paper with sentences of the form: "if the packet looks like this → let it through" or "if the packet looks like this → discard it".
Each sentence therefore has two parts: a criterion (what the packet looks like) and
an action (permit or deny). One sentence is called a rule or
an ACE (Access Control Entry). The whole sheet is called an access list, or
ACL.
That is all. The rest of the lecture is about how the criteria are written, in what order the sentences are read, and which of the doors the sheet is stuck to.
The last sentence deserves emphasis, because it is the source of the first confusion in the laboratory: a list written in the configuration and not applied to any interface filters absolutely nothing. It is merely text. Applying it is done separately, with a second command.
Filtering is not the only use
On Cisco equipment, an ACL is the standard way of answering the question "which traffic are we talking about?". That is why you will meet it in places that have nothing to do with security:
| Use | What the list does there | Where it appears in the course |
|---|---|---|
| Filtering | decides what passes and what does not - the only case in which deny actually discards packets | today's lecture |
| NAT | identifies the internal addresses allowed to be translated | lecture 9 |
| QoS | identifies the traffic that receives priority in the queues | lecture 4 (802.1p) |
| Device access | which addresses may open an SSH session on the router | section 12 |
| Route filtering | which routing updates are accepted from neighbours | lecture 10 |
| VPN | which "interesting" traffic triggers the building of the encrypted tunnel | lecture 9 |
permit does not mean "let it through" but "this is
the traffic I am talking about". And deny discards nothing - it merely excludes the
traffic from the selection. The same syntax, with an entirely different meaning of the words.What a list can "see" in a packet
The criteria available cover layers 3 and 4 of the OSI model - exactly the headers the router reads anyway:
| Layer | Criterion | Example of how it is written |
|---|---|---|
| 3 | source IP address | host 192.168.1.7 |
| 3 | destination IP address | 10.0.0.0 0.0.0.255 |
| 3 | the encapsulated protocol | ip, icmp, ospf, gre |
| 4 | the source or destination port | eq 80, range 20 21 |
| 4 | the ICMP message type | echo, echo-reply |
| 4 | the state of the TCP connection (approximately) | established |
What a classic ACL cannot see: the user's name, the content of the page requested, the domain name, the fact that a file contains a virus. All of these are at layers 5–7 and require a different kind of equipment.
3A router with ACLs, or a dedicated firewall?6 min
The question arises the moment somebody realises that a router can filter: if it can, why do we still buy firewalls? The answer is that they do different things, and the difference is not one of quality but of role.
- Its main function is routing; filtering is a supplement
- Decisions based on layers 3 and 4
- Stateless: every packet is judged in isolation, as though it were the first
- It costs nothing extra - the equipment is already there
- Perfect for simple filters and for protecting the device itself
- Its main function is filtering; it can route, but only to a limited extent
- Decisions based on layers 3–7, with content inspection
- Stateful: it remembers open sessions and accepts the replies automatically
- Hardware encryption, serious logging, a management interface
- Essential at the edge of any network that exposes services
An ACL costs latency and load on the router's processor: every packet must be compared, in the worst case, with every rule in the list. On a small router, a 300-line list applied to the Internet interface is noticeable.
Where publicly exposed services go
The classic architecture places a firewall between the edge router and the internal network and moves the public services - web server, mail server - into a separate zone called the DMZ (Demilitarised Zone).
4How a list of rules is read10 min
This is the section which, if it is properly understood, makes the rest of the lecture almost trivial. There are three sentences.
2. At the first match the action is applied, and the rest of the list is not read.
3. If no rule matches,
deny any applies - an invisible rule, present
automatically at the end of every list.
The professional habit: on remote equipment, apply the list with a
reload in 5 scheduled
beforehand. If you lock yourself out, the router reboots in five minutes with the old configuration.
If all goes well, cancel the reboot with reload cancel.The order of evaluation, as an exercise
5Where a list is applied10 min
A list that has merely been written does nothing. For it to take effect, it must be tied to a precise place, and that place has three coordinates.
| Coordinate | What it means | Values |
|---|---|---|
| routed protocol | which family of addresses it applies to | IPv4, IPv6 |
| interface | which door of the router the sheet is stuck to | Gi0/0, Se0/1/0, VLAN 10… |
| direction | the traffic coming in or the traffic going out | in, out |
This is the source of half the mistakes in the laboratory. in and out
do not refer to your network but to the router.
in = the traffic that enters the router through that interface, coming from
the cable.
out = the traffic that leaves the router through that interface, heading for
the cable.
So the same packet, travelling from the LAN to the Internet, is in on the interface
facing the LAN and out on the interface facing the Internet. You may choose to stop it
in either of those two places - but they are different places, with different effects.
The exception: if a single rule must apply to traffic arriving from several ingress interfaces, one
out list on the egress interface replaces three or four in lists.A router with 2 interfaces runs dual stack (IPv4 and IPv6). What is the maximum number of filtering ACLs that can be applied simultaneously?
See the solution
The general rule: on one interface, for one routed protocol and one direction, there can be a single active list.
So: 2 interfaces × 2 routed protocols × 2 directions = 8 lists.
The practical corollary: if you apply a second list to the same interface, direction and protocol, it is not added to the first - it replaces it, silently. One more reason to use named lists, where adding a rule happens inside the existing list.
6The wildcard mask12 min
Here you have to unlearn something. In an access list, addresses are not accompanied by a network mask but by a wildcard mask, and its rule is exactly the reverse.
A 1 bit means "ignore this bit, it can be anything".
In a network mask, 1 means "the network part" - that is, the fixed part. In a wildcard, the fixed part is marked with 0.
The memory trick: in a wildcard, 1 = wild = free = anything. The digit 1 looks like an exclamation mark: "I do not care!".
And for the ordinary cases there is an arithmetic shortcut: wildcard = 255.255.255.255 minus the mask. Subtract byte by byte:
A wildcard can, however, do things a network mask cannot. A mask requires its 1 bits to be contiguous, from the left. A wildcard has no such restriction: we can leave a 0 bit in the last position and thereby select only the even addresses of a network. It is rarely used, but it explains why the two are not the same thing with the signs swapped.
Start from what is already in the box: 172.16.8.0 0.0.7.255 covers eight consecutive
class C networks, from 172.16.8.0 to 172.16.15.255. Look at the binary representation:
the three free bits in the third byte produce exactly 2³ = 8 combinations.
Then try three things:
- wildcard
0.0.0.0over10.1.1.7- a single address, the equivalent ofhost; - wildcard
0.0.0.1over11.2.2.90- exactly two addresses, .90 and .91; this is the trick by which two rules become one; - wildcard
255.255.255.255over any address - absolutely everything, the equivalent ofany.
The keywords that shorten the writing
| Keyword | Full equivalent | Meaning |
|---|---|---|
any | 0.0.0.0 255.255.255.255 | any address |
host X | X 0.0.0.0 | exactly the address X |
| an address written on its own | X 0.0.0.0 | also exactly the address X, in standard lists |
Calculator: from prefix to wildcard and back
Choose /22 and read the result: the wildcard is 0.0.3.255, that is, four class C
networks. Choose /30 - the case of links between routers - and you get 0.0.0.3: four
addresses, of which two are usable.
Write the criterion that selects only the subnets 192.168.16.0/24 through 192.168.19.0/24, in a single line.
See the solution
These are four consecutive class C networks, hence a block of 4 × 256 = 1024 addresses, that is, a /22.
Checking the alignment: 16 divided by 4 leaves remainder 0, so the block is aligned and can be written as a single prefix. (Had we started from .17, it could not have been.)
The wildcard for /22 is 0.0.3.255. The criterion is written:
Check: the third byte has its last two bits free, so it takes the values 16, 17, 18, 19. Exactly what we wanted.
7Standard lists10 min
| Type | Identified by | Criteria | Where it is placed |
|---|---|---|---|
| Standard | numbers 1–99 and 1300–1999 | the source address alone | as close as possible to the destination |
| Extended | numbers 100–199 and 2000–2699 | source, destination, protocol, port | as close as possible to the source |
| Named | a name chosen by the administrator | standard or extended | according to its type |
A standard list answers one question only: where does the packet come from? It can say nothing about destination, protocol or port. That is little - but it is enough for the frequent case "this host is not allowed into that segment".
R(config)# access-list 50 deny host 172.16.1.1
│ │ │
│ │ └── the criterion: which source
│ └─────── the action: permit or deny
└─────────── the list number (1-99 => standard)
R(config)# access-list 50 remark block the problem host R(config)# access-list 50 deny host 172.16.1.1 R(config)# access-list 50 permit 172.16.0.0 0.0.255.255 R(config)# interface fastEthernet 0/1 R(config-if)# ip access-group 50 in
permit 172.16.0.0
0.0.255.255 - because it is part of that network - it would be accepted, and the
deny rule would never be checked at all.The more specific rule must always sit above the more general one. This is the one golden rule of access lists.
Why a standard list is placed near the destination
8Extended lists12 min
An extended list answers four questions at once: from where, to where, with which protocol and on which port. The price is a longer syntax and the obligation not to get the order of the arguments wrong.
access-list 101 deny tcp host 172.16.6.1 192.168.1.0 0.0.0.255 eq 23
│ │ │ │ │ │
│ │ │ │ │ └ destination port
│ │ │ │ └──── destination + wildcard
│ │ │ └───────────────── source (here: a single host)
│ │ └────────────────────────── the protocol: ip, tcp, udp, icmp...
│ └─────────────────────────────── the action
└──────────────────────────────────── the number (100-199 => extended)
deny tcp A B eq 80 means "from A to B,
port 80 of B". If you swap A and B, the list is syntactically correct and completely
useless.And if you want to filter by source port, that is written immediately after the source:
permit tcp any eq 80 192.168.0.0 0.0.0.255 means "from any web server, to our
network".Common protocols and ports
| Service | Protocol | Port | IOS keyword |
|---|---|---|---|
| Web | TCP | 80 | eq www or eq 80 |
| Secure web | TCP | 443 | eq 443 |
| SSH | TCP | 22 | eq 22 |
| Telnet | TCP | 23 | eq telnet |
| FTP (control) | TCP | 21 | eq ftp |
| DNS | UDP (and TCP) | 53 | eq domain |
| DHCP | UDP | 67, 68 | eq bootps / eq bootpc |
| Ping | ICMP | - | echo, echo-reply |
The operators available for ports: eq (equal), neq (not equal),
lt (less than), gt (greater than) and range 20 21 (a closed
interval).
! permit all IP traffic from a single host, to any destination access-list 101 permit ip host 10.0.0.1 any ! stop all traffic originating in the 10.0.0.0/24 network access-list 101 deny ip 10.0.0.0 0.0.0.255 any ! stop Telnet from one particular host to one particular network access-list 101 deny tcp host 172.16.6.1 192.168.1.0 0.0.0.255 eq 23 ! permit Telnet from every host in a network, to anywhere access-list 101 permit tcp 172.16.6.0 0.0.0.255 any eq telnet
Interactive evaluator
Edit the list in the box above and watch the verdicts change. Three observations are worth making carefully.
The first. Rule 4, deny ip host 192.168.10.66 any, appears to block the problem
host - but the table shows that its packet is permitted, by rule 3. The reason is the order:
permit icmp 192.168.10.0 0.0.0.255 any matches first, and the rest of the list is never
checked. Move rule 4 above rule 3 and watch the verdict change. This is, in two lines, the entire trap
of access lists: a correct rule, placed too low, does not exist.
The second. The last packet, coming from another network, matches no rule and falls onto the
implicit deny - although nobody wrote that line anywhere.
The third. Delete the last line, permit ip 192.168.10.0 0.0.0.255 any, and look
at how many packets remain permitted. It is the practical demonstration that a list without a final
permit line is a wall.
Where an extended list is placed
An extended list describes both source and destination precisely, so there is no risk of collateral damage. In that case it is more efficient to stop the traffic as early as possible, so that it does not waste bandwidth crossing the network for nothing.
9Named lists and editing them7 min
Numbered lists have two serious drawbacks, and it is the second that hurts.
- It is called "254" - in six months nobody remembers what it does
- A single line cannot be deleted.
no access-list 254deletes the whole list - New rules are necessarily added at the end - hence below the general
permit - A change means: delete everything, rewrite everything, and hope you forgot nothing
- It is called
DMZ_FILTER_IN- the name says what it does - Each rule has a sequence number, and
no 30deletes rule 30 alone - A new rule can be inserted between others, by giving it an intermediate number
- It is the mandatory form for reflexive lists and for IPv6
IOS numbers the rules automatically 10, 20, 30… precisely to leave room between them. If later you need a rule between 10 and 20, you give it the number 15 and it sits exactly there.
Had they been numbered one by one, there would be nowhere left to insert anything - and you would
have to renumber the list with ip access-list resequence.
R(config)# ip access-list extended LAN_FILTER_IN R(config-ext-nacl)# 20 permit ip any any ! we realise two rules are missing, and they must come BEFORE R(config-ext-nacl)# 5 permit icmp host 10.0.0.1 any R(config-ext-nacl)# 10 deny icmp any any ! the rule on line 5 had the wrong address: we delete just that one R(config-ext-nacl)# no 5 R(config-ext-nacl)# 5 permit icmp host 10.0.0.2 any ! applying it to the interface - the same as with numbered lists R(config)# interface fastEthernet 0/1 R(config-if)# ip access-group LAN_FILTER_IN in
show running-config into a text editor, change it there, test it mentally, then delete
the old list and paste the new version in a single operation. That way the network never spends a
moment with a half-written list.10Lists that take context into account9 min
The problem of return traffic
We want our hosts to browse the web, but nobody outside to be able to initiate a connection towards them. It sounds simple. It is not.
An ACL sees packets, not connections. When the web server answers, its packet comes from the outside, towards our network - exactly like a packet sent by an attacker.
The router does not remember that we asked first. Every packet is judged as though it were the first in the world. So any rule that lets the answer in lets the attack in too.
This is the definition of stateless, and it is the fundamental difference from a firewall.
The minimal solution: established
The established option matches TCP packets that have the ACK or RST bit
set - that is, those belonging to a conversation already under way. The first packet of a new
connection, the one with SYN alone, has no ACK, so it does not match and is stopped.
R0(config)# ip access-list extended HTTP_OUT R0(config-ext-nacl)# 10 permit tcp 192.168.0.0 0.0.0.255 any eq www R0(config)# ip access-list extended HTTP_IN R0(config-ext-nacl)# 10 permit tcp any eq www 192.168.0.0 0.0.0.255 established R0(config)# interface fa1/0 R0(config-if)# ip access-group HTTP_OUT out R0(config-if)# ip access-group HTTP_IN in
Notice the structure of the second rule: the source is any eq www - any web server -
and the destination is our network. It is the mirror of the first rule, with source and destination
swapped, plus the magic word at the end.
- It checks the ACK and RST bits alone - an attacker can fabricate a packet with ACK set, with no connection existing at all
- It works for TCP only; UDP and ICMP have no control bits, so they have no equivalent
- It cannot cope with applications that negotiate ports dynamically (active FTP, SIP, online games)
Reflexive lists
A reflexive ACL builds the return rules dynamically, from the sessions observed on the way out. When an internal host opens a connection, the router automatically creates the inverse rule, temporarily - and deletes it when the session ends or times out.
They are defined only through named extended lists and use two keywords: reflect,
which marks the traffic to be tracked, and evaluate, which applies the rules generated
from it.
R0(config)# ip access-list extended OUTBOUND R0(config-ext-nacl)# 10 permit tcp 192.168.0.0 0.0.0.255 any eq www reflect HTTP_TRAFFIC R0(config-ext-nacl)# 20 permit icmp 192.168.0.0 0.0.0.255 any reflect ICMP_TRAFFIC R0(config)# ip access-list extended INBOUND R0(config-ext-nacl)# 10 evaluate HTTP_TRAFFIC R0(config-ext-nacl)# 20 evaluate ICMP_TRAFFIC R0(config)# interface fastEthernet 1/0 R0(config-if)# ip access-group OUTBOUND out R0(config-if)# ip access-group INBOUND in
This is the first real step towards a stateful firewall: the router no longer judges each packet in
isolation but remembers which sessions were initiated from inside. Unlike established, it
works for UDP and ICMP as well, because it relies on the pair of addresses and ports rather than on
TCP bits.
Time-based lists
Sometimes the rule depends not on the traffic but on the clock: access permitted only during working hours, backups permitted only at night.
R(config)# time-range WORKING_HOURS R(config-time-range)# periodic Monday Tuesday Wednesday Thursday Friday 9:00 to 18:00 R(config)# ip access-list extended ACL_SCHEDULE R(config-ext-nacl)# 10 permit tcp any 192.168.1.0 0.0.0.255 eq telnet time-range WORKING_HOURS R# show time-range
11Verification, logging, remarks6 min
Three mechanisms make the difference between an ACL that has been written and an ACL that is understood.
Remarks - remark, up to 100 characters - explain the intention behind
each group of rules, not their syntax. In six months, when somebody else reads the configuration, a
remark is worth ten minutes of reconstructing the reasoning.
Logging - the keyword log at the end of a rule - generates a message containing
the list number, the action, the source address and the packet count. The message appears at the first
matching packet and then every 5 minutes, a mechanism designed precisely so as not to flood the
logs.
show access-lists and look at the number in brackets beside each rule.Zero matches on a rule that ought to be catching traffic means the traffic is not getting there: either the list is on the wrong interface, or in the wrong direction, or a rule above it has already caught the traffic. In the terminal example, rule 40 has 0 matches - and it is exactly the case discussed earlier, where rule 30 catches the traffic before it.
Many matches on a
deny you were not expecting means you are filtering something
you did not mean to. Both situations show up in three seconds.12Protecting access to the device5 min
So far we have filtered traffic that passes through the router. The last application is different: we filter the traffic that stops at the router - the management sessions.
A router reachable by SSH from anywhere on the Internet is one password away from a disaster. The
standard solution is not a list on an interface but one applied to the virtual lines (VTY),
with a different command: access-class instead of ip access-group.
R(config)# access-list 5 remark administrator hosts only R(config)# access-list 5 permit 192.168.99.0 0.0.0.255 R(config)# line vty 0 15 R(config-line)# access-class 5 in R(config-line)# transport input ssh R(config-line)# exec-timeout 5 0
| Command | Where it is applied | What it filters |
|---|---|---|
ip access-group | on an interface | traffic that passes through the router |
access-class | on the VTY lines | who may connect to the router |
The advantage of this approach: the list is applied once and covers every interface, whatever door the connection attempt arrives through. An ACL on an interface would have to be replicated on each one.
13Common mistakes4 min
- "I wrote the list, but it filters nothing"
The list exists in the configuration but has not been applied to any interface. It is merely
text.
Check with
show ip interfacewhich list is applied and in which direction. - "I added the rule, but it has no effect"
A rule above it is already catching the traffic. Your rule is never read.
show access-lists→ 0 matches. Move the rule higher. The specific above the general. - "I blocked everything, although I meant to block one host"
The list has only
denyrules. After them comes the implicitdeny any. Add a finalpermitline for the rest of the traffic. - "The ping goes one way but does not come back"
You permitted the outbound traffic and forgot the reply. As with routing, filtering must be
thought about in both directions.
Either a rule for
echo-reply, orestablished, or a reflexive list. - "I mixed up in and out" The direction is judged from the router's point of view, not the network's. Ask yourself: does the packet enter the router on this interface, or leave it?
- "I used a network mask instead of a wildcard"
permit 10.0.0.0 255.255.255.0is accepted without error and selects something entirely different. Wildcard = 255.255.255.255 minus the mask. Check withshow access-lists, where IOS displayswildcard bitsexplicitly. - "I applied the list to the interface I was connected through"
The session closes instantly and cannot be reopened.
On remote equipment:
reload in 5beforehand,reload cancelonce you have confirmed it works.
14Summary and glossary4 min
- An ACL is an ordered list of criterion–action pairs, read from top to bottom, up to the first match.
- At the end of every list there is an invisible
deny any. - The list must be applied to an interface and a direction to have any effect.
inandoutare judged from the router's point of view.- Wildcard: 0 = must match, 1 = ignore. It is the inverse of the mask.
- Standard = source only → near the destination. Extended = source, destination, protocol, port → near the source.
- Named lists allow a single line to be edited; numbered ones do not.
- Return traffic requires
establishedor a reflexive list. show access-listsand the match counter solve most problems.
15Self-check questions6 min
16Further reading2 min
We have learnt to describe traffic and stop it on a Cisco router, with no notion of state and no cryptography whatever. The next lecture looks at the same problem from the point of view of a stateful firewall and a Linux machine, and adds exactly the dimension that is entirely missing here: how we protect the content, not merely the path.
Laboratory 6 configures standard and extended lists on the company topology, together with
NAT - and there you will see, in practice, what "the same list, a different meaning of the word
permit" amounts to.
- Cisco - Security Configuration Guide: Access Control Lists
- RFC 3871 - operational security requirements for IP infrastructure
- RFC 2827 (BCP 38) - ingress filtering against spoofed source addresses
- The
iptables(8)manual, for comparison with the Linux approach