Filtering by Source or Destination IP Address
Problem
You want to block packets to or from certain IP addresses.
Solution
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 50 deny host 10.2.2.2
Router1(config)#access-list 50 permit any
Router1(config)#interface Serial0/1
Router1(config-if)#ip access-group 50 in
Router1(config-if)#exit
Router1(config)#end
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 150 deny ip host 10.2.2.2host 172.25.25.1
Router1(config)#access-list 150 permit ip any any
Router1(config)#interface Serial0/1
Router1(config-if)#ip access-group 150 in
Router1(config-if)#exit
Router1(config)#end
Router1#
Discussion
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 50 deny host 10.2.2.2
Router1(config)#access-list 50 permit any
This is a numbered ACL with a value between 1 and 99, making it a standard access-list. Using a standard access like this allows you to filter only based on the source IP address. In the example, we have chosen to deny a single host address, 10.2.2.2, to prevent the router from accepting packets from this device. 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 50 deny host 10.2.2.2
Router1(config)#access-list 50 permit 10.2.2.0 0.0.0.255
Router1(config)#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 line that permitted 10.2.2.0/24 before the line that denied the specific host 10.2.2.2. Each time the router received a packet from the forbidden host, it would compare 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 most of the time it uses this ACL. All of the examples in this chapter are relatively short, but if you have an ACL that is several hundred lines long, a good ordering can make a significant improvement in processing time. This will affect router CPU load, and could 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. Please 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 particular devices, 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. And, 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 discuss below.
Alternatively, if you want to match any device, you could write this as follows:
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. So 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 this, we use the ip access-group command on the interface that will receive the data stream that we want to filter:
Router1(config)#interface Serial0/1
Router1(config-if)#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 Serial0/1
Router1(config-if)#ip access-group 50 in
Router1(config-if)#ip 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, then even if the router is encapsulating IP packets from downstream devices, the tunnel packets themselves originate on the router. 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 because it means that 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 150 deny ip host 10.2.2.2host 172.25.25.1
Router1(config)#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. Please 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 system for IP addresses here, as we discussed above for the Standard IP ACL. 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 wanted 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 150 deny ip host 10.2.2.2 host 172.25.25.1
Router1(config)#access-list 150 permit ip 10.2.2.0 0.0.0.255 any
Router1(config)#access-list 150 deny ip any any
Note that the last line of both the Standard and Extended ACL examples in this recipe 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#
As you can see here, by including an explicit deny all rule at the end of this ACL, we can tell exactly how many packets were affected.
And, as we will 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 up until IOS Version 12.3(2)T (see Recipe 19.15 for more information). 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. Further, 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. However, Recipe 19.15 shows another solution to this problem.