Access Lists

What are they?

The access list is a group of statements. Each statement defines a pattern that would be found in an IP packet. As each packet comes through an interface with an associated access list, the list is scanned from top to bottom--in the exact order that it was entered--for a pattern that matches the incoming packet. A permit or deny rule associated with the pattern determines that packet's fate. You also can use a mask, which is like a wild card, to determine how much of an IP source or destination address to apply to the pattern match. The pattern statement also can include a TCP or UDP (User Datagram Protocol) port number.

Access list statements are entered one line at a time, and the list is scanned for a match in that same order. If you must make a change, you have to re-enter the entire list. Also, keep in mind that once you associate the list with an interface, any packet not processed by the list is dropped by default.

Once the access list is entered, you must associate it with the interface on the router where you want to apply the filtering. You can apply the list to incoming packets, (an "in" access list) or outgoing packets (an "out" access list). In most cases, either list will work. For out access lists, you need to set up the filter only on the one outgoing interface rather than on the individual incoming interfaces. This improves performance because only the network you are protecting will force a lookup on the access list.

Standard Access Lists

Access lists are generally broken into 2 major groups, standard and extended. Standard access lists only operate on the Network layer of the OSI model. These are used to block or permit networks from reaching other networks. For example, suppose I have a network with a web server on it. I would like to have the router filter traffic going to that webserver so that only a few home users and all users at work can access that machine. I could use a standard access list to permit these allowed hosts and deny traffic from every other host on the Internet.

To enable an access list such as this for IP, we need to configure an access list in the range of 1 to 99. For example:

access-list 1 permit 206.50.17.0 0.0.0.255

The first part shows "access-list" which is what all access lists start with, regardless of what network technology is used. The next part is "1" which specifies the # of the access list. To add additional rules to this list, you would start each line with "access-list 1". Permit indicates to the router that this is a rule specifying what should be allowed. Next is the network and subnet mask pair. Notice, however, that the subnet mask is inversed. Normally, for a /24 you would use a netmask of 255.255.255.0, but in access-lists, the subnet masks are inversed so that 255.255.255.0 becomes 0.0.0.255. The 255 in this case means ignore the last octet of the address when looking for a matching packet.

Extended Access Lists

Extended access lists function on both layer 3 and 4 of the OSI model. That is, they allow you to filter not only by network address but also by the type of traffic that is being sent or received. Extended access lists are much more flexible and allow for much greater control of traffic into and out of your network than standard access lists.

Let's go through an example to see how extended access-lists work.

fred# config t
fred(config)# access-list udp 100 permit any 172.50.10.0 0.0.0.255 eq 53
fred(config)# access-list tcp 100 permit any 172.50.10.0 0.0.0.255 eq 25
fred(config)# access-list tcp 100 deny 172.50.12.0 0.0.0.255 172.50.10.0 0.0.0.255
fred(config)# access-list tcp 100 permit any any
fred(config)# int s1
fred(config-if)# ip access-group 100 in
fred(config-if)# exit
fred(config)# exit

The first line takes into configuration mode so that we can setup our access list. The next line configures access list 100 to permit any traffic from 172.50.10.0/24 to reach our network on port 53. I know that this is for inbound traffic because of the line that says "ip access-group 100 in". When designing access lists, it is important to know before hand how you are designing your access-list whether for inbound or outbound traffic.

The third line specifies that SMTP traffic from 172.50.10.0/24 is to be allowed into our network. Next, traffic from 172.50.12.0/24 is not allowed to go to the network 172.50.10.0/24. Finally, any traffic that did not match any of the above rules is allowed by the line that says "access-list tcp 100 permit any any".

Let's look at another couple of examples.

Denying access to a host

Our first example is a statement that denies access to a host with the IP address of 130.120.110.100. Make sure you are at the "enable" level and enter "config" mode (or config terminal), and enter the following:

access-list 101 deny ip 0.0.0.0 255.255.255.255 130.120.110.100 0.0.0.0

The 255 mask on every octet of the source address signifies that the whole source address in the filter should be ignored. Technically, it doesn't matter what you use as the IP source address here, because it will be ignored. The all 0's mask on the destination address means that you want to apply the entire address. If you wanted to deny access to all addresses on the 130.120.110 network, you would use a mask of 0.0.0.255. The 255 in this case means ignore the last octet of the address when looking for a matching packet.

Allowing access only to HTTP on a host

Here, we permit access only to the HTTP port on the host and deny all other access to the host. This requires two lines:

access-list 101 permit tcp 0.0.0.0 255.255.255.255 130.120.110.100 0.0.0.0 eq 80
access-list 101 deny ip 0.0.0.0 255.255.255.255 130.120.110.100 0.0.0.0

The first statement matches any packet with 130.120.110.100 as the destination IP address and with a TCP port equal to 80. The second rule applies a match to all IP packets with the destination address, thus denying access to all packets that are not permitted because of the previous rule.

Tying Up Loose Ends

Although all unmatched packets are dropped by default, it's still a good idea to end the list with a statement that denies everything. This helps you keep track of the end of the list:

access-list 101 deny ip 0.0.0.0 255.255.255.255 0.0.0.0 255.255.255.255

Of course, if you want to begin your list by denying specific packets and you want to allow everything else, you would use the same statement with a permit instead of a deny. An easier way to state this is to use the following syntax:

access-list 101 deny ip any any

This statement functions exactly the same as the previous one, and later versions of the IOS will translate the longer version into this shorter version when you display it.

When you display the list, you may find that some of the TCP and UDP port numbers have been changed to a verbose description. We prefer to enter numbers because they are backward-compatible with previous IOS versions.

Enabling and Disabling

In our above example, there are 2 lines use to apply, or enable, the access list to an interface. The first line is "int s1" which takes you into the configuration for that interface. The second line, "ip access-group 100 in" sets up the access list 100 to act as an inbound filter for that interface. An interface can only have 1 inbound and 1 outbound access list applied to it at any one time.

As soon as you enter this command, the access list will immediately take effect. It's helpful to start a continuous ping in another window to a host on the other side of the interface that you're filtering to monitor its accessibility while applying the list. Save your changes with a "write memory" and a "write network" if you're backing your configurations up on a TFTP server.

If we wanted to take down the access list, for example to troubleshoot a connectivity problem, we would need to remove the line from the configuration that says "ip access-group 100 in". To do this, we can type the following:

fred# config t
fred(config)# int s1
fred(config-if)# no ip access-group 100 in
fred(config-if)# exit
fred(config)# exit

This only disables the access list. It does not delete or remove it from the configuration. Access-list 100 is still present in the configurations. It is generally advisable that if you are modifying an access-list that you disable it before making any modifications so that just in case you make a mistake, you won't stop any wanted traffic, such as your users or yourself.

Modifying Access Lists

You can use the "show config" command to see which access groups are associated with particular interfaces. This command also will list all of the access list statements at the end. An easier way to look at the access lists is the "show access list" command. If you use an access list number as an argument, you will only see that list. (Do this before choosing an access list number to make sure it is not already in use.) This command also will give you statistics on matches to every access list statement. To clear all the statistics, issue a "clear access-list counters," using the list number as an argument to designate a specific list.

You cannot easily go back and insert a change into an access list because the statements are processed in the order that they are originally entered into the router. Instead, what many administrator do is to use a text editor such as Notepad or VIM to hold a copy of the access list. After viewing the running configuration, copy the access list to your text editor. Make any modifications that you are going to make to the access list. Then, you will need to disable the old access-list, delete it, add the new one, and then enable it. Here's how you can do that.

fred# config t
fred(config)# int s1
fred(config-if)# no ip access-group 100 in
fred(config-if)# exit
fred(config)# no access-list 100
fred(config)# INSERT YOUR NEW LIST HERE
fred(config)# int s1
fred(config-f)# ip access-group 100 in
fred(config-if)# exit
fred(config)# exit
fred# copy start run

DNS Access Example

Below are the commands to permit DNS access through your firewall to the DNS server 192.168.1.1.

access-list 122 permit udp any gt 1023 host 192.168.1.1 eq domain
access-list 122 permit tcp any gt 1023 host 192.168.1.1 eq domain
access-list 122 permit udp any eq domain host 192.168.1.1 gt 1023
access-list 122 permit tcp any eq domain host 192.168.1.1 gt 1023
access-list 122 permit udp any eq domain host 192.168.1.1 eq domain

Issues and Drawbacks

Access lists are great for doing simple filtering and security for basic networks. However, there are some things to keep in mind when building and implementing them. First, the longer an access list, the more processor time it uses. Really long access lists can slow your router down significantly and even put an appreciable wait time for users trying to access machines on your network. Second, make sure that you put your most general statements at the top. That is, any statements that affect most of your users should be placed near the top of an access list while more specific statements that may only affect one machine should be placed near the bottom. Remember that access lists work serially, one right after the other. Third, access lists are not dynamic, so they cannot adapt to changing network or security situations. Therefore, as things get more complex, you might want to consider a true firewall package to use in its place.