An Access Control List (ACL) is generically a method for doing pattern matching based on protocol information. There are many reasons for doing this type of pattern matching, such as restricting access for security reasons or restricting routing tables for performance reasons.
Cisco has several different general kinds of access lists. The most common are the numbered ACLs, which are summarized in Table 19-1. But there are also named access lists, reflexive access lists, context-based access lists, and rate-limit access lists. There are even timed access lists that can have different effects at different times of day, although we will not cover them in this book. Within each of these general categories, there are many different types of ACLs that match on different protocol information. When working with route filtering, it is often easiest to work with prefix lists, which are another type of ACL discussed in more detail in Chapters Chapter 6, Chapter 7, Chapter 8, and Chapter 9.
You can apply an ACL in many different ways. Applied to an interface, you can use it to accept or reject incoming or outgoing packets based on protocol information such as source or destination address, port number, protocol number, and so forth. Applied to a routing protocol, this same ACL might prevent the router from sharing information about a particular route. And, applied to a route map, the ACL could just identify packets that need to be tagged or treated differently.
Table 19-1 shows all of the current ranges for numbered access lists. Cisco periodically adds new ranges to this list, so earlier IOS levels may not support all of these ACL types. Also bear in mind that if your IOS feature set doesn’t support a particular protocol such as IPX, XNS, or AppleTalk, the corresponding ACL type will also be unavailable.
Access list type | |
1 - 99 | Standard IP ACL |
100 - 199 | Extended IP ACL |
200 - 299 | Ethernet type code ACL |
300 - 399 | DECNET ACL |
400 - 499 | XNS ACL |
500 - 599 | Extended XNS ACL |
600 - 699 | AppleTalk ACL |
700 - 799 | 48-bit MAC address ACL |
800 - 899 | IPX ACL |
900 - 999 | Extended IPX ACL |
1000 - 1099 | IPX service advertisement protocol |
1100 - 1199 | Extended 48-bit MAC address ACL |
1200 - 1299 | IPX NLSP ACL |
1300 - 1999 | Standard IP ACL, expanded range |
2000 - 2699 | Extended IP ACL, expanded range |
2700 - 2999 | SS7 (Voice) ACL |
Clearly many of these ranges deal with protocols or technologies that are beyond the scope of this book. This book’s primary focus is on IP-based technologies, so this chapter will not discuss ACL types that are intended for use with other protocols.
A named ACL is really just another way of writing either a standard or extended IP ACL. Named ACLs can make your configuration files considerably easier to read. Some commands that use an ACL for pattern matching will not accept named ACLs, but, for the most part, named ACLs are interchangeable with normal IP ACLs. Their chief advantage is that you can nest other ACLs inside of a named ACL for greater flexibility.
Reflexive ACLs are more sophisticated objects that can contain temporary entries. Reflexive ACLs need to be nested inside of named ACLs. A reflexive ACL has two parts that are generally nested in two different named ACLs. One part watches for packets of a particular type using normal extended IP ACL syntax. As soon as the router sees this packet, it activates a matching rule in another ACL. This allows you to do things like permitting inbound traffic of a particular type only after the router sees an initial outbound packet of the matching type.
However, reflexive ACLs are somewhat limited in their scope because they are not able to read into the payloads of IP packets. Many applications have more complicated behavior, such as using dynamically generated port numbers. To handle this type of situation, Cisco has developed another type of ACL called Context-Based Access Control (CBAC).
Like reflexive ACLs, CBAC works by turning on and off temporary access list rules. However, CBAC actively monitors applications using a stateful inspection algorithm that allows the router to react to the application and dynamically create new ACL rules. It can also watch for unusual application behavior and dynamically disable the corresponding temporary ACL rules.
You should always remember that every ACL ends with an implicit deny all clause. This means that if you are matching items (packets, for example) with an ACL, and the item fails to match any of the explicitly listed clauses of the ACL and falls off the end, it is the same as if the item matched an explicit deny clause. For this reason, if you are trying to block certain unwanted packets (for example), but want to allow all others to pass, you must remember to include a permit all statement at the end of the ACL.
For more information on ACLs in general, refer to Cisco IOS Access Lists (O’Reilly).
You can use standard access lists to block packets from specified IP source addresses:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#50
deny host10.2.2.2
access-list
Router1(config)#50
permit anyinterface
Router1(config-if)#Serial0/1
ip access-group
Router1(config-if)#50
inend
Router1#
You can filter packets based on both the source and destination addresses with an extended access list:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#150
deny ip host10.2.2.2
host172.25.25.1
access-list
Router1(config)#150
permit ip any anyinterface
Router1(config-if)#Serial0/1
ip access-group
Router1(config-if)#150
inend
Router1#
The most obvious use for access lists is traffic filtering. The two examples in this recipe both show how to use access control lists for filtering inbound packets. The first example uses the following access list:
Router1(config)#access-list
Router1(config)#50
deny host10.2.2.2
access-list
50
permit any
This is a numbered ACL with a value between 1 and 99, making it a standard access list. Using standard ACLs like this allows you to filter based only on the source IP address. In the example, we have chosen to deny a single host address, 10.2.2.2
. All other packets are permitted. This is a somewhat artificial thing to do, of course. It is more likely that you would want to allow only a limited group of devices and block all of the others. For example, you might want to allow all of the devices on 10.2.2.0/24
, except the host 10.2.2.2
, and drop packets from any other devices. You could do this with the following standard ACL:
Router1(config)#access-list
Router1(config)#50
deny host10.2.2.2
access-list
Router1(config)#50
permit10.2.2.0 0.0.0.255
access-list
50
deny any
The order of the statements in an access list is critical. Consider what would have happened if we had put a line that permitted 10.2.2.0/24
before the line that denied the specific host (10.2.2.2
). Then, each time the router receives a packet from the forbidden host, it compares it to the ACL. Because this host is part of the permitted range, the router would accept the packet and not look any further.
Also, because the router will stop processing an ACL as soon as it finds a match, you can save the processor a lot of work by putting the most common rules near the top. You want the router to find a match as early as possible while parsing the ACL. All of the examples in this chapter are relatively short, but if you have an ACL that is several hundred lines long, good ordering so that most of your packets match early lines in the ACL can make a significant improvement in processing time. Ordering will affect router CPU load and can also improve jitter and latency issues.
The other important thing to look out for when constructing an ACL like this is the fact that they use wildcard bits (rather than netmask format) when defining ranges of addresses. In this example, we wanted to specify the range 10.2.2.0/24
. This means that we want to fix all of the bits in the first three octets of the address and allow any pattern of bits in the last octet. We can achieve this with a wildcard pattern of 0.0.0.255
. Refer to Recipe 5.3 for a more detailed discussion of the differences between wildcards and netmasks.
The basic notation is an IP address followed by a wildcard pattern. But there are two special cases. Suppose you want to match on a single IP address for a particular device, such as 10.2.2.2
. You can write this as follows:
Router1(config)#access-list 50
deny 10.2.2.2 0.0.0.0
This wildcard pattern means that there are no free bits in the address, so we are looking for an exact match. Alternatively, you can use the more intuitive version that we used earlier in this recipe, with the host keyword:
Router1(config)#access-list 50
deny host 10.2.2.2
The two forms have an identical effect. In fact, for standard IP ACLs like this one, the router will replace both of these with the following:
Router1(config)#access-list 50
deny 10.2.2.2
The host keyword is not redundant, however, for extended IP ACLs, which we will discuss later.
Alternatively, if you want to match any device, you could write this:
Router1(config)#access-list 50
deny 0.0.0.0 255.255.255.255
Because all of the wildcard bits in this pattern are set, it means that any bit may have a value of either 0 or 1. Therefore, this pattern will match any IP address. The router will rewrite this ACL with the following simpler form:
Router1(config)#access-list 50
deny any
As we mentioned in the introduction to this chapter, there are many different ways to apply an ACL. In this case, we want to apply this ACL to filter IP packets received on a particular router interface. To do so, we use the ip access-group command on the interface that will receive the data stream that we want to filter:
Router1(config)#interface
Router1(config-if)#Serial0/1
ip access-group
50
in
In this command, the keyword in tells the router to apply the filter to inbound packets, that is, packets received by this interface. In some cases, you might want to filter outbound packets instead. The router will even let you apply a different ACL to inbound and outbound packets:
Router1(config)#interface
Router1(config-if)#Serial0/1
ip access-group
Router1(config-if)#50
inip access-group
51
out
The outbound access-group command has an interesting quirk that you should be aware of. This command will not filter packets that originate on the router itself. This is important because if you apply an outbound filter and then try to test it with a ping or telnet from the router, your rule will appear not to work. Make sure to do these tests from a downstream device.
It’s also important to remember that the router originates packets in several less obvious situations. For example, if you are using tunnels, the tunnel packets themselves originate on the router—even if the router is encapsulating IP packets from downstream devices. The same is true when the router acts as a gateway for other protocols, such as SNA or X.25.
This also has security implications: if somebody can convince the router to originate packets for them, they will bypass the rule. So, while the outbound access-group command is extremely useful, you need to be careful about how you use it, or it might be less effective than you expect.
The second example in the solution section of this recipe does a similar kind of filtering, except that this time we have used an extended ACL:
Router1(config)#access-list
Router1(config)#150
deny ip host10.2.2.2
host172.25.25.1
access-list
150
permit ip any any
The syntax of the extended IP ACL is somewhat more involved than that of the standard ACL. It includes the same permit or deny keywords as the standard IP ACL. The next keyword in this example selects the IP protocol. Refer to Recipe 19.3 for a discussion of other options.
Extended IP ACLs always include two IP addresses. The first is the source address, and the second is the destination. In the first line of the example, we have specified two host addresses for the source and destination, while the second line matches any address in either the source or the destination fields of the IP packet.
You can use the same wildcard matching systems for IP addresses that we discussed earlier. Suppose, for example, that we want to allow any device on the 10.2.2.0/24
segment to access any destination device, but we want to specifically prevent the host, 10.2.2.2
from reaching 172.25.25.1
, and we want to drop all packets from any other devices. We could do this with the following extended IP ACL:
Router1(config)#access-list
Router1(config)#150
deny ip host10.2.2.2
host172.25.25.1
access-list
Router1(config)#150
permit ip10.2.2.0 0.0.0.255
anyaccess-list
150
deny ip any any
Note that the last line explicitly denies everything that wasn’t matched in one of the previous lines. This is actually not necessary because every ACL implicitly ends with a deny all, whether you include it or not. However, including an explicit permit all or deny all clause at the end of an ACL is generally a good practice because it makes things more clear. Also, when you look at an ACL with the show access-list command, it gives you a breakdown of how many times each rule found a match:
Router1#show access-list 150
Extended IP access list 150
deny ip host 10.2.2.2 host 172.25.25.1 (422 matches)
permit ip 10.2.2.0 0.0.0.255 any (743 matches)
deny ip any any (387 matches)
Router1#
Including an explicit deny all rule at the end of this ACL allows you to tell exactly how many packets were affected.
As we discuss in Recipe 19.8, you can configure this line to log exactly which packets reach all the way to the end of the ACL without matching one of the earlier rules.
Finally, we need to mention one of the most annoying problems involved in managing large ACLs. If you add a new rule to an ACL, it will always go at the very end of the list. This is not always what you want. Worst of all, there is no way to remove individual lines from an ACL without removing the entire list.
We have found that the easiest way to get around this problem is to use the show running-config command to get a complete listing of the ACL you want to edit. Copy this into a text editor of some kind on your local workstation. Then you can use any common text editor to create the modified ACL. Delete the old ACL and copy in the new one. As we mentioned in Chapter 1, if you use TFTP to transfer the new commands into the router, it will not make the change until the transfer is complete. This is particularly important for ACLs, where you could enter the first line and then find yourself locked out of the router by the implicit deny all that follows it.
You want to add a human-readable comment to an ACL to help other engineers understand what you have done.
You can add a comment to any standard or extended IP ACL using the remark keyword:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#50
remarkAuthorizing thy trespass with compare
access-list
Router1(config)#50
deny host10.2.2.2
access-list
Router1(config)#50
permit10.2.2.0 0.0.0.255
access-list
50
permit any
This command can be quite useful when you have to keep track of many different ACLs on a router, particularly when several of them look similar. The comment field can be up to 100 characters long. If you require more space, simply add more remark lines to the ACL:
Router1(config)#access-list
Router1(config)#50
remarkAuthorizing thy trespass with compare
access-list
Router1(config)#50
remarkMy self corrupting salving thy amiss
,access-list
Router1(config)#50
remarkExcusing thy sins more than thy sins are
access-list
50
remarkShakespeare, Sonnet 35
When you display this ACL using the show access-list command, it will not show the remark lines:
Router1#show access-list 50
Standard IP access list 50
deny 10.2.2.2
permit 10.2.2.0, wildcard bits 0.0.0.255
permit any
Router1#
The only way to see these comments is to look at the router’s configuration file:
Router1#show running-config | include access-list 50
access-list 50 remark Authorizing thy trespass with compare
access-list 50 remark My self corrupting salving thy amiss,
access-list 50 remark Excusing thy sins more than thy sins are
access-list 50 remark Shakespeare, Sonnet 35
access-list 50 deny 10.2.2.2
access-list 50 permit 10.2.2.0 0.0.0.255
access-list 50 permit any
access-list 50 remark
Router1#
Note that the router does not reorder the remark lines in the ACL, so you can use this feature to explain line-by-line what each command does:
Router1(config)#access-list
Router1(config)#50
remarkloathsome canker
access-list
Router1(config)#50
deny host10.2.2.2
access-list
Router1(config)#50
remarksweetest bud
access-list
Router1(config)#50
permit10.2.2.0 0.0.0.255
access-list
50
permit any
Complete Sonnets, William Shakespeare (Dover)
Extended IP access lists can also filter based on application information such as protocol and port numbers:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#151
permit tcp any any eq wwwaccess-list
Router1(config)#151
deny tcp any any gt1023
access-list
Router1(config)#151
permit icmp any anyaccess-list
Router1(config)#151
permit udp any any eq ntpaccess-list
Router1(config)#151
deny ip any anyinterface
Router1(config-if)#Serial0/1
ip access-group
Router1(config-if)#151
inend
Router1#
This example shows how to construct an extended IP ACL to filter traffic based on applications. In Recipe 19.1, we showed how to use extended IP ACLs to match on any combination of source and/or destination IP addresses. But the extended IP ACL also allows you to match on just about anything in the IP packet header.
The first argument after the permit or deny keyword represents the IP protocol type:
Router1(config)#access-list 151
permit tcp any any eq www
In this case, we want to match a TCP-based application, so we have used the keyword tcp in this position. This field represents the IP protocol number, which is an 8-bit value. TCP is protocol number 6, UDP is 17, and ICMP uses protocol number 1. The IANA has registered 134 different protocol numbers. You can find the complete list of registered IP protocols online at http://www.iana.org/assignments/protocol-numbers. Cisco supplies helpful mnemonics for several of these protocols, such as the tcp, udp, and icmp keywords used in the example, so you don’t have to remember the protocol numbers. Table 19-2 shows all of the IP protocols for which Cisco supplies mnemonic keywords. You can always use the protocol number in decimal form if you prefer, but the router will replace it with the mnemonic (if one exists) in its configuration file.
Protocol number | Keyword | Description |
1 | icmp | Internet Control Message Protocol |
2 | igmp | Internet Gateway Message Protocol |
4 | ipinip | IP-in-IP tunnel protocol |
6 | tcp | Transmission Control Protocol |
9 | igrp | Interior Gateway Routing Protocol |
17 | udp | User Datagram Protocol |
21 | nos | KA9Q tunnel protocol |
47 | gre | Generic Routing Encapsulation tunnel protocol |
50 | esp | IPSec Encapsulation Security Payload |
51 | ahp | IPSec Authenticating Header Protocol |
88 | eigrp | Enhanced Interior Gateway Routing Protocol |
89 | ospf | Open Shortest Path First routing protocol |
103 | pim | Protocol Independent Multicast protocol |
108 | pcp | IP Payload Compression Protocol |
As we showed in Recipe 19.1, you can match on any IP protocol number by simply using the keyword ip.
The source and destination IP addresses come after the IP protocol number or keyword. We described how to use these fields in Recipe 19.1. Remember that the address keyword any is shorthand that stands for an address of 0.0.0.0
with a wildcard pattern of 255.255.255.255
.
Following each address is an optional field in which you can specify particular protocol information such as port numbers. In the following example, we match on TCP port 80, which is used by the HTTP protocol.
There are many possible mnemonic keywords for different TCP port numbers:
Router1(config)#access-list 151
permit tcp any eq ?
<0-65535> Port number
bgp Border Gateway Protocol (179)
chargen Character generator (19)
cmd Remote commands (rcmd, 514)
daytime Daytime (13)
discard Discard (9)
domain Domain Name Service (53)
echo Echo (7)
exec Exec (rsh, 512)
finger Finger (79)
ftp File Transfer Protocol (21)
ftp-data FTP data connections (20)
gopher Gopher (70)
hostname NIC hostname server (101)
ident Ident Protocol (113)
irc Internet Relay Chat (194)
klogin Kerberos login (543)
kshell Kerberos shell (544)
login Login (rlogin, 513)
lpd Printer service (515)
nntp Network News Transport Protocol (119)
pim-auto-rp PIM Auto-RP (496)
pop2 Post Office Protocol v2 (109)
pop3 Post Office Protocol v3 (110)
smtp Simple Mail Transport Protocol (25)
sunrpc Sun Remote Procedure Call (111)
syslog Syslog (514)
tacacs TAC Access Control System (49)
talk Talk (517)
telnet Telnet (23)
time Time (37)
uucp Unix-to-Unix Copy Program (540)
whois Nicname (43)
www World Wide Web (HTTP, 80)
Router1#
As with the IP protocol numbers listed in Table 19-2, you can substitute the decimal numerical value for any of these keywords, and the router will replace it with the keyword. For any other applications not included in this list, you must use the decimal port number.
In our example, the mnemonic for port 80 is www:
Router1(config)#access-list 151
permit tcp any any eq www
Note that the keywords eq www appear after the destination IP address, rather than the source IP address. This is because we are looking for the destination TCP port number. If you need to match on a source port number instead, you could simply move these keywords to follow the source IP address:
Router1(config)#access-list 151
permit tcp any eq www any
Of course, you can always match on both:
Router1(config)#access-list 151
permit tcp any eq www any eq www
Note, however, that this ACL will score a correct match only if both source and destination TCP port numbers match. If you wanted to match HTTP traffic between any two devices, but didn’t know which device had initiated the TCP session, you would need to include two separate lines like this:
Router1(config)#access-list
Router1(config)#151
permit tcp any any eq wwwaccess-list
151
permit tcp any eq www any
The IANA reserves the TCP port numbers 1024 and above for local and temporary applications. Many TCP implementations use these high-numbered ports for source port numbers, and for temporary or ephemeral purposes. So it is relatively common to see ACLs that restrict the use of these ports. We included an example ACL rule in this recipe:
Router1(config)#access-list 151
deny tcp any any gt 1023
This command will block all packets that have a destination port number greater than 1023 (that is, ports 1024 through 65,535). Remember that TCP applications often use these high port numbers for source ports, so you need to be careful about traffic direction when you apply such an ACL.
There is a similar set of port numbers for UDP applications:
Router1(config)#access-list 151
permit udp any eq ?
<0-65535> Port number
biff Biff (mail notification, comsat, 512)
bootpc Bootstrap Protocol (BOOTP) client (68)
bootps Bootstrap Protocol (BOOTP) server (67)
discard Discard (9)
dnsix DNSIX security protocol auditing (195)
domain Domain Name Service (DNS, 53)
echo Echo (7)
isakmp Internet Security Association and Key Management Protocol (500)
mobile-ip Mobile IP registration (434)
nameserver IEN116 name service (obsolete, 42)
netbios-dgm NetBios datagram service (138)
netbios-ns NetBios name service (137)
netbios-ss NetBios session service (139)
ntp Network Time Protocol (123)
pim-auto-rp PIM Auto-RP (496)
rip Routing Information Protocol (router, in.routed, 520)
snmp Simple Network Management Protocol (161)
snmptrap SNMP Traps (162)
sunrpc Sun Remote Procedure Call (111)
syslog System Logger (514)
tacacs TAC Access Control System (49)
talk Talk (517)
tftp Trivial File Transfer Protocol (69)
time Time (37)
who Who service (rwho, 513)
xdmcp X Display Manager Control Protocol (177)
Router1#
For example, you could block all Sun RPC traffic, which includes important but chatty applications such as Network File System (NFS):
Router1(config)#access-list
Router1(config)#151
deny udp any eq sunrpc anyaccess-list
151
deny udp any any eq sunrpc
This will block RPC traffic going in either direction because we applied the UDP port number file separately to the source and destination ports.
Like TCP, UDP port number values from 1024 through 65,535 are often used for temporary purposes such as source port numbers. You can control the use of these port numbers with a similar rule:
Router1(config)#access-list 151
deny udp any any gt 1023
You can also create an access list to look for specific types of ICMP messages in exactly the same way that we matched on TCP and UDP port numbers. The difference for ICMP message types is that each ICMP packet has only a single type field, rather than a source and destination port. You specify the type after the addresses on an Extended ACL, as follows:
Router1(config)#access-list 190
permit icmp any any echo
This ACL looks for ICMP echo request packets, such as those sent by the ping utility. This feature allows you to treat these ping packets differently than, for example, an ICMP unreachable message. In fact, this command allows you to look for any ICMP message type number between 0 and 255 either by the decimal number, or by mnemonic:
Router1(config)#access-list 190
permit icmp any any ?
<0-255> ICMP message type
administratively-prohibited Administratively prohibited
alternate-address Alternate address
conversion-error Datagram conversion
dod-host-prohibited Host prohibited
dod-net-prohibited Net prohibited
dscp Match packets with given dscp value
echo Echo (ping)
echo-reply Echo reply
fragments Check non-initial fragments
general-parameter-problem Parameter problem
host-isolated Host isolated
host-precedence-unreachable Host unreachable for precedence
host-redirect Host redirect
host-tos-redirect Host redirect for TOS
host-tos-unreachable Host unreachable for TOS
host-unknown Host unknown
host-unreachable Host unreachable
information-reply Information replies
information-request Information requests
log Log matches against this entry
log-input Log matches against this entry, including input
interface
mask-reply Mask replies
mask-request Mask requests
mobile-redirect Mobile host redirect
net-redirect Network redirect
net-tos-redirect Net redirect for TOS
net-tos-unreachable Network unreachable for TOS
net-unreachable Net unreachable
network-unknown Network unknown
no-room-for-option Parameter required but no room
option-missing Parameter required but not present
packet-too-big Fragmentation needed and DF set
parameter-problem All parameter problems
port-unreachable Port unreachable
precedence Match packets with given precedence value
precedence-unreachable Precedence cutoff
protocol-unreachable Protocol unreachable
reassembly-timeout Reassembly timeout
redirect All redirects
router-advertisement Router discovery advertisements
router-solicitation Router discovery solicitations
source-quench Source quenches
source-route-failed Source route failed
time-exceeded All time exceededs
time-range Specify a time-range
timestamp-reply Timestamp replies
timestamp-request Timestamp requests
tos Match packets with given TOS value
traceroute Traceroute
ttl-exceeded TTL exceeded
unreachable All unreachables
<cr>
Note that not all of the range of possible ICMP message types have been officially allocated. Please refer to the Internet Assigned Numbers Authority (IANA) web site for a complete listing of standard ICMP message types: http://www.iana.org/assignments/icmp-parameters.
The following ACL blocks contain several illegal combinations of TCP header flags:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#161
deny tcp any any ack fin psh rst syn urgaccess-list
Router1(config)#161
deny tcp any any rst synaccess-list
Router1(config)#161
deny tcp any any rst syn finaccess-list
Router1(config)#161
deny tcp any any rst syn fin ackaccess-list
Router1(config)#161
deny tcp any any syn finaccess-list
Router1(config)#161
deny tcp any any syn fin ackend
Router1#
There are six flag bits in the TCP header that the devices use to control the session:
TCP uses a so-called three-way handshake to set up sessions. To start a session, the client device sends a packet with the SYN bit, which is an instruction to synchronize sequence numbers. The server device responds with a packet that has both SYN and ACK bits set, which the first device then acknowledges with an ACK to complete the handshake process.
The session teardown procedure is similar, but it actually uses four packets instead of three. One device sends the other a packet with the FIN bit set. The second device then responds to this with an ACK. Then, in a separate packet, the second device sends its own FIN, which the first device responds to with an ACK to terminate the session.
Devices use the RST flag for a few different reasons, but one of the most common is the so-called abortive close. This happens when one device can’t wait around for the other device to acknowledge the end of the session using the normal FIN and ACK pattern. So, it simply sends a packet that has both the RST and ACK bits set to end the session. There is no need for the other device to respond to this packet.
Obviously, some combinations of these bits are not valid, however. For example, it makes no sense to have a single packet with both the SYN and FIN bits set. And, in defining test cases for TCP implementations, RFC 1025 defines a packet with all 6 bits set as a nastygram (or a kamikaze packet, Christmas tree packet, or lamp test segment). The first line in the example ACL blocks nastygrams:
Router1(config)#access-list 161
deny tcp any any ack fin psh rst syn urg
The remaining lines block other illegal combinations of flags.
You can use the established keyword to restrict which device is allowed to initiate the session. In the following example, we want to allow the client device to telnet to the server, but not the other way around:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#148
permit tcp any eq telnet any establishedaccess-list
Router1(config)#148
deny ip any anyinterface
Router1(config-if)#FastEthernet0/0
ip access-group
Router1(config-if)#148
inend
Router1#
In this example, the interface will accept incoming TCP packets only if they have a TCP source port number of 23 (Telnet) and this TCP session is already established. It does not restrict the destination port number; it would be whatever random high-numbered port the initiating device had originally selected for its source port when it started the session.
The router considers an established TCP connection to be one that has either the RST or ACK bits set. We discuss these TCP header flags in more detail in Recipe 19.4. Because this does not include packets with only the SYN bit set in particular, it is impossible to create a new TCP connection.
Note that you could actually write the same thing explicitly as two rules:
Router1(config)#access-list
Router1(config)#148
permit tcp any eq telnet any ackaccess-list
148
permit tcp any eq telnet any rst
The combination of these two rules is identical to the version in the example:
Router1(config)#access-list 148
permit tcp any eq telnet any established
But the version with the established keyword executes more efficiently. Note that putting both RST and ACK in the same rule would match packets with both RST and ACK set, not one or the other.
To see why the established keyword is sometimes necessary, imagine what would happen if it were not present. The interface would accept any inbound TCP packets that happened to have a source port of 23. But this could be literally anything. A moderately clever hacker who knew how to set the source port on his Telnet application could easily initiate a connection to any device on the other side of the router.
So, if you are using ACLs to control TCP applications for security reasons, you should consider using the established keyword.
This example shows how to filter both FTP control and data sessions:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#152
permit tcp any any eq ftpaccess-list
Router1(config)#152
permit tcp any any eq ftp-data establishedinterface
Router1(config-if)#FastEthernet0/0
ip access-group
Router1(config-if)#152
inend
Router1#
Some protocols use multiple ports. A classic example is FTP, which is shown in the example. It is worthwhile to review how the FTP protocol works. For more details, please consult RFC 959.
When a client device wants to connect to a server to upload or download files, it makes a TCP connection on port 21. This port 21 connection carries all of the interactive user traffic such as usernames and passwords, as well as commands to move around to different directories. FTP also uses this control session to tell the server what port number it wants to use for transferring data. This will typically be a high-numbered temporary TCP port.
When the user wants to transfer a file, he traditionally types a put or get command on the server. We say traditionally because this is not quite how things work when your FTP client software is driven through a web browser, as we discuss in Recipe 19.12.
The server then makes a new TCP connection to the high-numbered port on the client device that it previously learned about through the control session. The source port for this connection is the well-known FTP data port number 20. This is backwards from most TCP connections in which the client device connects to the server using a well-known destination port number. Here, the server connects to the client using a well-known source port number.
The client and server exchange the file, then disconnect this FTP data connection, leaving the FTP control connection on port 21 active. The server will actually use the FTP data connection to transfer any bulk data, including directory listings as well as files. You can match both the control and data traffic streams using the ACL shown in this recipe.
In this example, we assume that the client device is connected to the router’s FastEthernet0/0
interface, perhaps through other downstream routers. And, for the sake of the example, we assume that this is the only data that we want to allow.
The router will receive a TCP packet from client device as it initiates the FTP session with destination port 21. We match this connection with the following extended IP ACL:
Router1(config)#access-list 152
permit tcp any any eq ftp
Note that we have used the keyword ftp in this ACL to mean TCP port 21.
Then, when there is data to exchange, the server will make a connection back to the client device on port number 20. The ACL keyword for this port is ftp-data:
Router1(config)#access-list 152
permit tcp any any eq ftp-data established
It’s important to note that the access group is applied inbound to packets received on the client FastEthernet port. So this ACL will not apply to any of the packets sent from the server to the client device, only those sent from the client to the server. However, this is sufficient because the devices cannot establish a TCP session unless they can both send packets.
For a more generic multiport TCP application, you can specify a range of ports in the ACL with the range keyword:
Router1(config)#access-list 153
permit tcp any any range 6000 6063
This example matches any packets whose destination port is between 6000 and 6063 inclusive, which is the range commonly used by the X Window System. You can also specify open-ended ranges. For example, to match any TCP port number greater than 1023, use the gt keyword:
Router1(config)#access-list 153
permit tcp any any gt 1023
There are similar “less than” and “not equal to” operators for port numbers:
Router1(config)#access-list
Router1(config)#153
permit tcp any any lt1024
access-list
153
permit tcp any any neq666
As an aside, TCP port number 666 is used by the Doom interactive network game, making it an excellent candidate for filtering.
These same operations also apply identically for UDP port numbers:
Router1(config)#access-list
Router1(config)#154
permit udp any any range6000 6063
access-list
Router1(config)#155
deny udp any any gt1023
access-list
Router1(config)#156
permit udp any any lt1024
access-list
157
permit udp any any neq666
Recipe 19.3; Recipe 19.6; Recipe 19.12; RFC 959
You can filter packets based on the contents of the Differentiated Services Control Point (DSCP) field using the dscp keyword:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#162
permit ip any any dscp af11end
Similarly, to filter based on TOS, you can use the tos keyword:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#162
permit ip any any tos max-reliabilityend
And you can filter based on IP Precedence using the precedence keyword:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z Router1(config)#access-list
Router1(config)#162
permit ip any any precedence flashend
In Chapter 11 and Appendix B we discuss the DSCP, IP TOS, and IP Precedence fields in more detail. Chapter 11 also includes several examples of ACLs that filter based on this information. Please refer to these sections for more information.
The first example looks for packets that have a DSCP field value of AF11, which has a bit pattern of 001010, or a decimal value of 10. The second example matches packets with a TOS value of maximum reliability, which has a decimal value of 2.
Note that you can use the decimal numerical values for any TOS, Precedence, or DSCP field, and the router will simply replace it with the mnemonic keyword, if one exists. For example, we could have written the second example as follows:
Router1(config)#access-list 162
permit ip any any tos 2
In this case, the router would have replaced the number 2 with the max-reliability keyword. However, there is no mnemonic keyword corresponding to the TOS value, 3. The router will accept values that do not have well-known names such as this, but it will leave them as numerical values in the configuration file.
Access lists can generate log messages. The following example will allow all packets to pass, but will record them:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#150
permit ip any any loginterface
Router1(config-if)#Serial0/1
ip access-group
Router1(config-if)#150
inend
Router1#
In this example, we use the log-input keyword to include additional information about where the packets came from:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#150
permit tcp any any log-inputaccess-list
Router1(config)#150
permit ip any anyinterface
Router1(config-if)#Serial0/1
ip access-group
Router1(config-if)#150
inend
Router1#
The first example uses the log keyword to record a log message every time the ACL makes a match. Here are some log messages generated by this command:
Feb 6 13:01:19: %SEC-6-IPACCESSLOGRP: list 150 permitted ospf 10.1.1.1 -> 224.0.0.5, 9 packets Feb 6 13:01:19: %SEC-6-IPACCESSLOGDP: list 150 permitted icmp 10.1.1.1 -> 10.1.1.2 (0/0), 4 packets
You can also get a breakdown of how many matches each line in the ACL has recorded with the show access-list command:
Router1#show access-list 150
Extended IP access list 150
permit ip any any log (15 matches)
Router1#
The second form, with the log-input keyword, causes the router to include other useful data in the log messages. With this option, the log messages will include the port where the packet was received:
Feb 6 13:08:31: %SEC-6-IPACCESSLOGP: list 150 permitted tcp 10.1.1.1(0) (Serial0/1 ) -> 10.1.1.2(0), 80 packets Feb 6 13:08:38: %SEC-6-IPACCESSLOGP: list 150 permitted tcp 10.2.2.2(0) (Serial0/1 ) -> 172.25.26.5(0), 1 packet Feb 6 13:10:29: %SEC-6-IPACCESSLOGP: list 150 permitted tcp 10.2.2.2(0) (Serial0/1 ) -> 172.20.100.1(0), 1 packet
If we apply this ACL on an Ethernet or Token Ring port, the log messages will also include MAC address information:
Feb 6 14:56:34: %SEC-6-IPACCESSLOGP: list 150 permitted tcp 172.25.1.1(0) (FastEthernet0/0.1 0010.4b09.5700) -> 172.25.25.1(0), 1 packet Router1# Feb 6 14:58:20: %SEC-6-IPACCESSLOGP: list 150 permitted tcp 172.25.1.7(0) (FastEthernet0/0.1 0000.0c92.bc6a) -> 172.25.1.5(0), 1 packet
The only problem with these commands is that they tend to produce huge numbers of log messages. To be really useful, we recommend using this feature in conjunction with a remote log server, as described in Chapter 18. Then you can store and analyze all of the messages without worrying that you will lose information when the router’s internal log buffer overwrites itself. We offer a useful script for analyzing the messages and look for important patterns in Recipe 19.10.
In general, we recommend logging all denied packets, because they tend to represent the rejected traffic that is not part of the normal functioning of the network.
While all of the examples in this recipe used extended ACLs, the log keyword is also available with standard ACLs:
Router1(config)#access-list 77 permit any log
However, the log-input option is available only for extended ACLs.
You can configure the router to log the total number of TCP sessions, rather than just the number of packets, with the following set of commands:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#122
permit tcp any any eq telnet establishedaccess-list
Router1(config)#122
permit tcp any any eq telnetaccess-list
Router1(config)#122
permit ip any anyinterface
Router1(config-if)#Serial0/0
ip access-group
Router1(config-if)#122
inend
Router1#
Here is an alternative method that will also work:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#121
permit tcp any any eq telnet synaccess-list
Router1(config)#121
permit tcp any any eq telnetaccess-list
Router1(config)#121
permit ip any anyinterface
Router1(config-if)#Serial0/0
ip access-group
Router1(config-if)#121
inend
Router1#
When you configure an access list, the router counts the total number of times it finds something that matches each line in the ACL. While this information is often useful, it does not tell you whether these counters are recording a thousand packets on a single session, or a single packet from each of a thousand sessions. The ACLs in this recipe count the number of TCP sessions, as well as the total number of packets.
In the first example, the first line in the ACL permits all established Telnet packets to pass through the access list, as we did in Recipe 19.5. The second line then matches all of the Telnet packets that the first one does not, which mainly means the initial SYN packet that starts the TCP session. As we mentioned in Recipe 19.4, the first packet of a TCP session contains the SYN bit. And, as we discussed in Recipe 19.5, an ACL that includes the established keyword will not match any packets that have the SYN bit set.
So, the second line catches the initial session establishment, while the first line matches all of the other packets in the session. Therefore, the second line will give us a way to count the total number of TCP sessions that pass through the router. Note that these sessions can be between any two devices—as long as they communicate through this router, we can count them. Of course, the ACL in the example counts only Telnet sessions, that is, sessions on TCP port number 23. However, it is easy enough to change the port number in the ACL to monitor other TCP-based applications.
When you apply this ACL to an interface, the show access-list command shows a running count of the number of Telnet sessions that have occurred:
Router1#show access-list 122
Extended IP access list 122 permit tcp any any eq telnet established (3843 matches) permit tcp any any eq telnet(6 matches)
permit ip any any (31937 matches) Router1#
Six separate Telnet sessions have passed through the interface where we applied this ACL. If you want to know the total number of Telnet packets, you can simply add the first two lines together: 3843+6=3849 packets.
The second example uses a slightly different method for counting the number of sessions. In this case, the first line of the access list matches only Telnet packets with the SYN bit set, as discussed in Recipe 19.4:
Router1(config)#access-list 121 permit tcp any any eq telnet syn
The only packets that have this bit set are the packets from the initial TCP three-phase handshake that establishes the session. So this also gives us a way of counting the total number of Telnet sessions. The second line of this ACL captures the remaining Telnet packets:
Router1#show access-list 121
Extended IP access list 121 permit tcp any any eq telnet syn(7 matches)
permit tcp any any eq telnet (3057 matches) permit ip any any (9404 matches) Router1#
This ACL has counted seven separate Telnet sessions: 7+3057=3064 total Telnet packets.
We can take the counting functionality of these ACLs a step further by adding the log keyword to the ACL lines that count the sessions:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list 121 permit tcp any any eq telnet syn log
Router1(config)#access-list 121 permit tcp any any eq telnet
Router1(config)#access-list 121 permit ip any any
Router1(config)#end
Router1#
Including the log keyword like this allows us to keep a log of every TCP session, without needing to log all of the packets in these sessions. This can be useful for security records and audits:
Router1#show logging | include list 121
Feb 7 15:36:13: %SEC-6-IPACCESSLOGP: list 121 permitted tcp 172.25.1.1(3886)
-> 10.2.2.2(23), 1 packet
Feb 7 15:36:39: %SEC-6-IPACCESSLOGP: list 121 permitted tcp 172.25.1.1(3887)
-> 10.2.2.2(23), 1 packet
Feb 7 15:38:32: %SEC-6-IPACCESSLOGP: list 121 permitted tcp 172.25.1.1(3888)
-> 10.2.2.2(23), 1 packet
Feb 8 07:48:20: %SEC-6-IPACCESSLOGP: list 121 permitted tcp 172.25.1.1(4332)
-> 10.2.2.2(23), 1 packet
Feb 8 07:49:35: %SEC-6-IPACCESSLOGP: list 121 permitted tcp 172.25.1.1(4333)
-> 10.2.2.2(23), 1 packet
Feb 8 08:08:57: %SEC-6-IPACCESSLOGP: list 121 permitted tcp 172.25.1.1(4339)
-> 10.2.2.2(23), 1 packet
Router1#
For more information about logging, see Chapter 18.
The Perl script in Example 19-1 parses a router syslog file and builds a detailed report of packets that were denied by logging ACLs. By default, the script will parse every ACL log message that it finds in the syslog file on a server. You can also look for messages associated with a particular ACL by specifying the ACL number or name as a command-line argument.
#!/usr/local/bin/perl # # logscan.pl -- a script to extract ACL logs from a syslog file. # # Set behaviour $log="/var/log/cisco.log"; $ntop=10; # chomp ($acl=$ARGV[0]); if ($acl = = "") { $acl=".*"}; open(LOG , "<$log") or die; while (<LOG>) {if (/IPACCESSLOGP: list $acl denied ([tcpud]+) ([0-9.]+)(([0-9]+)) ->
([0-9.]+)(([0-9]+)), ([0-9]+) /) {
$x=$6; $srca{$2}+=$x; $foo=sprintf("%16s -> %16s %3s port %-6s",$2,$4,$1,$5); $moo=sprintf("%3s port %-6s",$1,$5); $quad{$foo}+=$x; $port{$moo}+=$x; } } $n=0; printf ("Connection Summary: "); foreach $i (sort { $quad{$b} <=> $quad{$a} } keys %quad) { if ($n++ >= $ntop) { last }; printf ("%6s:%s ", $quad{$i},$i); } $n=0; printf (" Destination Port Summary: "); foreach $i ( sort { $port{$b} <=> $port{$a} } keys %port) { if ($n++ >= $ntop) { last }; printf ("%6s: %s ", $port{$i},$i); } $n=0; printf (" Source Address Summary: "); foreach $i ( sort { $srca{$b} <=> $srca{$a} } keys %srca) { if ($n++ >= $ntop) { last }; printf ("%6s: %s ", $srca{$i},$i); }
Note that we have had to split the line that begins “if (/IPACCESSLOGP: list” across two lines so that it will fit on the page. If you decide to use this script, please type this as a single line.
It’s a good idea configure your access lists so that they log all of the packets that they deny. This is particularly true for security-related ACLs. You can then use these log messages for security or audit purposes. Unfortunately, this level of logging can create a large number of messages, which makes analysis difficult. This Perl script automates the most difficult part of this analysis by parsing a large file of ACL log messages and building a report that can help to identify potential problems.
The report produced by the script has three sections that summarize connections, destination ports, and source IP addresses. The connection report displays the top 10 most common connection denied attempts including the source address, destination source, and destination port number. The destination port summary displays the top 10 most frequently denied destination ports. Finally, the source address summary displays the 10 hosts whose connection attempts were most frequently denied. In each case, the script looks at both TCP and UDP ports.
The following is a sample report:
Freebsd%./logscan.pl
Connection Summary:
195: 172.25.1.1 -> 172.20.100.1 tcp port 23
13: 172.25.1.1 -> 172.20.100.1 tcp port 22
8: 172.20.1.2 -> 172.25.1.3 udp port 53
6: 172.20.1.2 -> 172.25.1.1 udp port 123
6: 172.25.1.1 -> 10.2.2.2 tcp port 23
4: 172.20.1.2 -> 172.25.1.1 udp port 162
4: 172.25.1.1 -> 172.20.100.1 tcp port 21
4: 172.20.1.2 -> 172.25.1.1 udp port 53
3: 172.25.1.1 -> 172.20.100.1 tcp port 80
2: 172.20.1.2 -> 172.25.1.3 udp port 123
Destination Port Summary:
206: tcp port 23
14: tcp port 22
12: udp port 53
8: udp port 123
4: tcp port 80
4: udp port 162
4: tcp port 21
2: tcp port 443
1: tcp port 6000
1: tcp port 79
Source Address Summary:
222: 172.25.1.1
24: 172.20.1.2
3: 172.25.1.6
1: 192.168.4.217
1: 172.25.1.9
1: 10.2.3.134
1: 172.25.1.4
1: 172.22.1.9
1: 10.23.55.121
1: 172.25.1.3
Freebsd%
This report can help identify troubling behavior that warrants further investigation. For instance, address 172.25.1.1
has attempted to telnet to 172.20.100.1
195 times. This may not have been evident by scanning the log file by hand.
The script can also build a report based on the messages received from a particular ACL number or name:
Freebsd%./logscan.pl 122
Connection Summary:
2: 172.25.1.6 -> 10.2.2.2 tcp port 443
1: 192.168.4.217 -> 10.2.2.2 tcp port 23
1: 172.22.1.9 -> 10.2.2.2 tcp port 6000
1: 10.2.3.134 -> 10.2.2.2 tcp port 23
1: 172.25.1.9 -> 10.2.2.2 tcp port 23
1: 10.23.55.121 -> 10.2.2.2 tcp port 79
1: 172.25.1.1 -> 10.2.2.2 tcp port 22
1: 172.25.1.6 -> 10.2.2.2 tcp port 23
Destination Port Summary:
4: tcp port 23
2: tcp port 443
1: tcp port 22
1: tcp port 6000
1: tcp port 79
Source Address Summary:
3: 172.25.1.6
1: 10.2.3.134
1: 172.22.1.9
1: 192.168.4.217
1: 172.25.1.1
1: 172.25.1.9
1: 10.23.55.121
Freebsd%
Before you can use this script you must modify the variable $log. This variable must contain the full directory and filename of the syslog file that you wish to scan. The script is then ready to launch. The only other variable you may want to modify is the $ntop variable. This variable defines how long each section of the report will be. By default, the script is set to display the top 10 matches in each category. However, you can set this number to any number you prefer. Note also that, as in the previous example, if there are fewer than $ntop matches in any category, the script will show only the matches that it actually finds.
For more information on logging and remote logging to a syslog server, please see Chapter 18.
A basic named ACL is similar to the numbered ACLs that we discussed earlier in this chapter. They can work like either standard or extended IP ACLs:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#ip access-list standard
Router1(config-std-nacl)#STANDARD-ACL
remark
Router1(config-std-nacl)#This is a standard ACL
permit any log
Router1(config-std-nacl)#exit
Router1(config)#ip access-list extended
Router1(config-ext-nacl)#EXTENDED-ACL
remark
Router1(config-ext-nacl)#This is an extended ACL
deny tcp any any eq www
Router1(config-ext-nacl)#permit ip any any log
Router1(config-ext-nacl)#exit
Router1(config)#interface
Router1(config-if)#Serial0/1
ip access-group
Router1(config-if)#STANDARD-ACL
inend
Router1#
You can embed a reflexive ACL inside of a named extended IP ACL. The reflect keyword defines the reflexive ACL rule, and the evaluate command executes it. The following example filters ICMP packets so that you can initiate a ping test from one side of the network, but not the other:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#ip access-list extended
Router1(config-ext-nacl)#PING-OUT
permit icmp any any reflect
Router1(config-ext-nacl)#ICMP-REFLECT
timeout15
permit ip any any
Router1(config-ext-nacl)#exit
Router1(config)#ip access-list extended
Router1(config-ext-nacl)#PING-IN
evaluate
Router1(config-ext-nacl)#ICMP-REFLECT
deny icmp any any log
Router1(config-ext-nacl)#permit ip any any
Router1(config-ext-nacl)#exit
Router1(config)#interface
Router1(config-if)#Serial0/1
ip access-group
Router1(config-if)#PING-OUT
outip access-group
Router1(config-if)#PING-IN
inend
Router1#
The first example in this recipe demonstrates how to use named ACLs. There is very little difference between this example and the one shown in Recipe 19.1, except that here we have used a different type of ACL to accomplish the same thing. One useful difference between the two versions is that you can delete an individual rule from a named ACL:
Router1#show access-list
Extended IP access list EXTENDED-ACL deny tcp any any eq www permit ip any any log Router1#EXTENDED-ACL
configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#ip access-list extended
Router1(config-ext-nacl)#EXTENDED-ACL
no deny tcp any any eq www
Router1(config-ext-nacl)#end
Router1#show access-list
Extended IP access list EXTENDED-ACL permit ip any any log Router1#EXTENDED-ACL
However, as with numbered ACLs, you cannot add individual rules to the middle of a named ACL.
Named ACLs start to show their real value, though, when you need to use more advanced features such as reflexive ACLs, as we did in the second example. This example is similar in spirit to what we did to restrict TCP sessions in Recipe 19.5. In that case, we wanted to ensure that users on the trusted side of the network could initiate TCP connections to the untrusted side, but reject any incoming connection attempts. Here we do the same thing with ICMP packets.
Of course, because TCP is a connection-oriented protocol, it is not quite as difficult to determine which side initiated the session. But because ICMP doesn’t have the concept of a session, we have to wait until somebody on the inside sends an ICMP packet to somebody on the outside. When this happens, we tell the router that it can expect to see an appropriate ICMP response from the same IP address, so it should let that packet through.
Let’s look at the outbound ACL first:
Router1(config)#ip access-list extended
Router1(config-ext-nacl)#PING-OUT
permit icmp any any reflect
Router1(config-ext-nacl)#ICMP-REFLECT
timeout15
permit ip any any
The first permit command includes the keyword reflect, and defines the reflection rule name as ICMP-REFLECT. We have applied this ACL to watch for outbound packets on the interface. As soon as we send out an ICMP packet, such as a ping query, the router starts looking for the reflected version of this packet—in this case, a ping response.
We have also included the timeout keyword at the end of the line with an argument of 15. This tells the router that it should not wait more than 15 seconds after the last outbound packet for additional inbound packets.
The inbound rule then uses the evaluate keyword to dynamically enable the reflection rule:
Router1(config)#ip access-list extended
Router1(config-ext-nacl)#PING-IN
evaluate
Router1(config-ext-nacl)#ICMP-REFLECT
deny icmp any any log
Router1(config-ext-nacl)#permit ip any any
Note that this example uses the same rule name, ICMP-REFLECT, that was previously defined in the outbound ACL. If the incoming packet looks like a reflected version of whatever was defined when we created this rule, the ACL will permit the packet. If the packet doesn’t match this rule, then it will continue checking the rest of the ACL normally. In this case, we have followed the evaluate command with a command that will explicitly deny all other ICMP packets that don’t match the reflection rule.
Note that the router will check the reflected packet to ensure that it has the correct source and destination addresses, based on the outbound packet. For example, if you use reflexive ACLs to match a UDP application, the router will also check port numbers to ensure that the inbound packet is legitimate.
This example shows how to filter passive FTP control and data sessions:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#144
permit tcp any gt1023
any eq ftpaccess-list
Router1(config)#144
permit tcp any gt1023
any gt1023
access-list
Router1(config)#144
deny ip any anyinterface
Router1(config-subif)#Serial0/0.1
ip access-group
Router1(config-subif)#144
inend
Router1#
In Recipe 19.6, we briefly reviewed the traditional way that FTP works. However, there is another subtle variation on this process, which is commonly called passive FTP. The user connects the control session to the server on port 21, exactly as before. But in the passive FTP case, the client software issues the command PASV. This command instructs the server to listen on a new non-default data port and wait for a connection. The server selects a new port, which it tells to the client. The server then opens this port and waits for a connection. The client device initiates a new TCP connection to this temporary port number and uses that connection to transfer its data.
This may sound like an unusual way of doing things, and it probably is. However, it is actually the default mode for many web browsers that perform FTP file transfers, including Internet Explorer and Netscape. This makes passive FTP the most common FTP mode for many networks. The problem is that if you want to control this traffic using an ACL of any kind, you no longer know the source or destination TCP port numbers. For example, if you need to restrict some traffic while ensuring that passive FTP is allowed, you will need an ACL that can somehow permit the temporary port numbers. In Recipe 19.13, we demonstrate a filtering method in which the router learns about the new port by watching the control session of the FTP session.
This example takes a simpler approach and uses an extended ACL to deal with passive FTP. The trouble with this ACL is that it opens all TCP ports from 1024 and above. Clearly, this is not desirable on a router facing the Internet or some other potentially unfriendly network.
Although our example permits passive FTP to pass through, it opens up over 64,000 TCP ports in the process. Obviously, this is not the best way to permit passive FTP. In Recipe 19.13, we discuss a much more secure method of allowing passive FTP through your router.
The following example shows how to configure the router to perform stateful inspection of TCP or UDP packets:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#166
deny ip any anyaccess-list
Router1(config)#167
permit tcp any any eq telnetip inspect name
Router1(config)#Telnet
tcpinterface
Router1(config-if)#Serial0/1
ip access-group
Router1(config-if)#166
inip access-group
Router1(config-if)#167
outip inspect
Router1(config-if)#Telnet
outend
Router1#
CBAC has been available as part of the IOS firewall feature set since Version 11.2(P). CBAC does a stateful inspection of TCP and UDP packets to manage sessions as they pass through the router. It uses this state information to dynamically modify existing extended ACLs to control the active sessions. CBAC can also monitor and manage sessions based on application type and identify, terminate, or log any suspicious activity.
CBAC provides much greater security than a regular filtering ACL because it uses features similar to those found in dedicated firewalls. In fact, the IOS firewall feature set (including CBAC) makes an excellent firewall for small or cost-conscious organizations. Although it is not suitable for every application, CBAC’s stateful inspection does provide better security than simple packet filtering firewalls.
CBAC works by inspecting active sessions and dynamically creating temporary ACL entries to allow the return traffic through. In our example, we configured the router with an inbound ACL that denies all IP packets, which would normally prevent the router from accepting any inbound IP traffic on this interface. However, when somebody on the inside of the network initiates an outbound connection through this port, CBAC creates a temporary ACL that allows the device on the outside to respond.
We can demonstrate this by initiating an outbound Telnet session through this interface, then viewing the inbound ACL:
Router1#show ip access-list 166
Extended IP access list 166permit tcp host 10.2.2.2 eq telnet host 172.25.1.1 eq 1379 (22 matches)
deny ip any any (456 matches) Router1#
Note that the original ACL now contains a new entry to allow the return data of the Telnet session that we originated. This temporary ACL entry includes the exact source and destination IP addresses and port numbers. This ensures that our Telnet session works normally, but it prevents all other possible IP addresses from connecting to the client device’s source port. In fact, CBAC even prevents the external server from connecting to the internal device’s source port using a new session because it maintains specific session information such as source and destination port numbers and TCP sequence numbers. This temporary ACL entry will terminate when the session ends, leaving only the static deny all entry that we originally configured in ACL number 166.
This configuration will block all inbound connection attempts. A common and very simple technique used by hackers as a prelude to attacking an Internet site is to perform a port scan. This means systematically trying to start an inbound session on each port in a large range. If there is any response at all, the attacker knows that there is something listening, which presents a useful starting point for breaking in. However, because this CBAC configuration blocks all unsolicited connection attempts regardless of the port, port scanning reveals nothing useful. This is usually enough to deter all but the most sophisticated hackers.
In fact, the only effective way to get a packet past the ACL configuration shown in this recipe is to send a packet with the right source and destination addresses and port numbers as well as the right TCP sequence number. This technique is called a hijack attack, and it is almost impossible to prevent. Attackers using this technique are generally able to get a single packet past the firewall. In some cases an attacker can use this single packet to cause mischief. Fortunately for us, hijack attacks are extremely difficult to execute.
The show ip inspect sessions command lets you view information about all of the sessions that CBAC is currently watching:
Router1#show ip inspect sessions
Established Sessions
Session 821061C0 (172.25.1.1:1379)=>(10.2.2.2:23) tcp SIS_OPEN
Router1#
The example shows how to inspect generic TCP sessions. However, one of CBAC’s greatest strengths is its ability to identify application-specific behavior and adjust its ACL entries accordingly. Table 19-3 displays the various applications that CBAC is able to monitor.
Application protocol | |
cuseeme | CU-SeeMe protocol |
fragment | IP fragmented packets |
ftp | File Transfer Protocol |
h323 | H.323 protocol |
http | HTTP (Java blocking) |
netshow | Microsoft’s NetShow |
rcmd | Unix R-commands |
realaudio | RealAudio |
rpc | Sun RPC |
rtsp | Microsoft’s RPC |
smtp | Simple Mail Transfer Protocol |
sqlnet | SQL*Net |
streamworks | StreamWorks |
tcp | Generic TCP |
tftp | Trivial File Transfer Protocol |
udp | Generic UDP |
vdolive | VDOLive |
Just because an application is not listed in this table doesn’t mean that CBAC will not manage its sessions. In fact, the Telnet example in this recipe used generic TCP inspection. Unless your application does something unusual in its session setup and negotiation sequences, the generic inspection should work well. For example, standard HTTP also uses standard TCP session rules. The special HTTP option for CBAC simply allows it to handle Java.
Let’s take a look at an application that doesn’t use standard TCP ports to build connections: passive FTP. As we indicated in Recipe 19.12, passive FTP is difficult to secure because the server can choose to use any of a large number of ports for its data session. The result is that both the source and destination ports are determined dynamically when the session is established. Recipe 19.12 showed a way to filter this traffic statically, but with the unfortunate side effect of leaving some 64,000 other ports open. With CBAC, this is not necessary—the router can watch the FTP control session and determine the server’s data port. This allows it to open only the required port:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#access-list
Router1(config)#155
permit tcp any any eq ftpaccess-list
Router1(config)#155
deny ip any anyip inspect name TEST ftp
Router1(config)#interface
Router1(config-subif)#Serial0/0
ip access-group
Router1(config-subif)#155
inip inspect
Router1(config-subif)#TEST
inend
Router1#
In this example, the ftp keyword invokes FTP inspection instead of the generic TCP inspection that we showed in the previous example. Also, notice that the first line of our ACL includes the ftp keyword, which permits only the FTP control session. This is necessary so that CBAC will permit the control part of the application to pass.
Now we can connect to the FTP server using a web browser. The ACL now shows the new entries that CBAC has created for us:
Router1#show ip access-list 155
Extended IP access list 155
permit tcp host 172.20.1.2 eq 11252 host 172.25.1.3 eq 49155 (1415 matches)
permit tcp any any eq ftp (151 matches)
deny ip any any (3829 matches)
Router1#
CBAC monitored the FTP control session and opened the specific FTP data ports for the passive FTP data connection. You can tell that this is a passive FTP session from the high port numbers.
CBAC inspection can also handle normal FTP. CBAC FTP inspection blocks third party connections, allowing only “safe” FTP data ports (1024–65535). CBAC monitors the FTP control session, and will not open a data port if the client authentication fails.
Although we haven’t shown an example for UDP, CBAC can also handle UDP-based applications in a similar fashion to TCP. When you send a UDP packet out through the interface, CBAC knows to expect an appropriate response. UDP is difficult to handle because it is not session oriented, but CBAC does it well.
CBAC also offers application support for TFTP, which is a feature rarely seen in commercial firewalls. The TFTP server uses the well-known UDP port 69. The client sends an initial packet to the server on this well-known port. But then the server opens a new arbitrary port greater than 1023 for the duration of the TFTP session. A standard packet filter would have to permit all UDP ports above 1023 to let TFTP work. CBAC gets around this problem by monitoring the TFTP session to determine which UDP port to open.
CBAC has a several settings that you can adjust to improve the overall performance and security of the router. We’ve listed some of the most important options in Table 19-4.
Description | Default | Recommended | |
TCP idle-time | Length of time CBAC will continue to permit an idle TCP session | 1 hour | 30 minutes |
UDP idle-time | Length of time CBAC will continue to permit an idle UDP session | 30 seconds | 20 seconds |
Finwait-time | Length of time CBAC will continue to permit a TCP session after the exchange of FIN packets | 5 seconds | 1 second |
Synwait-time | Length of time that CBAC will wait after receiving a SYN packet without completing the session establishment | 30 seconds | 15 seconds |
The following set of commands configures the timer settings of CBAC shown in Table 19-4:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#ip inspect tcp idle-time
Router1(config)#1800
ip inspect udp idle-time
Router1(config)#20
ip inspect tcp finwait-time
Router1(config)#1
ip inspect tcp synwait-time
Router1(config)#15
end
Router1#
You can view the CBAC configuration settings with the show ip inspect config command:
Router1#show ip inspect config
Session audit trail is disabled Session alert is enabled one-minute (sampling period) thresholds are [400:500] connections max-incomplete sessions thresholds are [400:500] max-incomplete tcp connections per host is 50. Block-time 0 minute. tcp synwait-time is 15 sec -- tcp finwait-time is 1 sectcp idle-time is 1800 sec -- udp idle-time is 20 sec
dns-timeout is 5 sec Inspection Rule Configuration Inspection name Telnet tcp alert is on audit-trail is off timeout 1800 Router1#
CBAC also provides a method of logging managed sessions by enabling audit trails. You can enable an audit trail on a particular CBAC inspection command with the audit-trail keyword:
Router1#configure terminal
Enter configuration commands, one per line. End with CNTL/Z. Router1(config)#ip inspect name
Router1(config)#Telnet
tcp audit-trail onend
Router1#
When you enable CBAC audit trails, the router will create a log entry after each session terminates. This log entry includes detailed information about the connection.
Here a sample audit trail log that the router recorded after we terminated a Telnet session:
Feb 8 14:37:24: %FW-6-SESS_AUDIT_TRAIL: tcp session initiator (172.25.1.1:1402) sent 59 bytes -- responder (10.2.2.2:23) sent 1299
For more information on logging please see Chapter 18.
18.217.190.58