In the last chapter, you configured IP routing and switched virtual interfaces (SVIs) to allow hosts on one subnet to talk to hosts on another. By default, IOS doesn’t restrict this sort of inter-VLAN communication. Any device on one subnet can reach any device on another, provided you’ve set up routing correctly.
If these were the 1990s, you could probably leave it at that. But security is a big deal nowadays, and many organizations require tight control over how traffic flows between devices. If you want to be taken seriously as a Cisco network administrator, you have to know how to configure your switches and routers to restrict IP traffic according to those requirements.
The most common way to do this is by using IP access control lists (ACLs). An ACL is a set of rules that defines whether a given IP address can talk to another IP address. At first blush, the idea of writing rules like this may sound monumentally tedious. In a network of 5,000 devices, you can’t write ACL rules for every device—nor should you. The good news is that ACLs are extremely flexible and powerful, and you can cover a large number of use cases with a small number of rules.
When it comes to restricting traffic, you’ll most often encounter three basic scenarios:
In this chapter, I’m going to show you how to configure ACLs to cover each of these scenarios. To get you started off on the right foot, here’s a high-level overview of the steps you’ll be performing:
Take a look at figure 9.1. As it stands, any device with an IP address in VLAN 600 can talk to any device in VLAN 700 and vice versa.
Suppose you need to prevent HR-PC1 from reaching Executive-PC1, but you don’t want to restrict traffic from HR-PC1 in any other way. It’s vitally important that you, as a network administrator, can take a requirement like this and translate it into IOS-speak by rephrasing the requirement in terms of source and destination IP addresses.
In this case, HR-PC1 with its IP address of 172.31.60.51 shouldn’t be able to reach Executive-PC1 at 172.31.70.51. In networking parlance, HR-PC1 is the source and Executive-PC1 is the destination, as shown in table 9.1.
Action |
Source |
Destination |
---|---|---|
Deny | 172.31.60.51 (HR-PC1) | 172.31.70.51 (Executive-PC1) |
Notice that I snuck in another term: action. The action is what you want the switch to do with traffic that matches the source and destination addresses. In this case, if 172.31.60.51 sends any traffic to 172.31.70.51, the switch should deny, or block, it.
Once you have this information, you’re ready to create your access list, which you’ll apply to an interface later in the chapter.
To block IP-to-IP traffic, you create what’s called an extended IP access list. The only reason I mention this ridiculously long name is to help you remember the equally long command you must use to create it, which I’ll share in a moment. You also have to assign it either a name or a number. There’s no technical reason to use one over the other, but my personal preference is to stick with numbers.
Get into global configuration mode. Then create ACL 100 using this command:
ip access-list extended 100
You should see the extended named access control list (NACL) configuration prompt:
Switch1(config-ext-nacl)#
As I said, an ACL is just a list of rules. You’ve created the list, ACL 100, but you haven’t created any rules. Using the information from table 9.1, you need to create a new rule inside the ACL.
Make sure you’re still at the (config-ext-nacl)# prompt, and issue the following command to deny traffic from 172.31.60.51 to 172.31.70.51:
Switch1(config-ext-nacl)#deny ip host 172.31.60.51 host 172.31.70.51
By the way, Cisco calls this rule an access control entry (ACE), but I prefer the term rule because it’s more descriptive.
The format of an ACL rule is pretty simple, as you can see in figure 9.2. The action comes first—in this case, deny. Next, the IP indicates you want this rule to apply only to IP traffic. The next two parameters—host 172.31.60.51—indicate that the rule applies to traffic from the single source IP address, 172.31.60.51. Last, the host 172.31.70.51 indicates the rule applies if 172.31.70.51 is the destination IP address. Even though the terms source and destination don’t appear explicitly in the command, IOS infers them based on the order.
Keep in mind that when you create a rule, IOS doesn’t check whether the IP addresses you specify are valid. Always double-check your IP addresses when creating an access list.
Exit ACL configuration mode:
Switch1(config-ext-nacl)#exit
Verify the ACL and that the new rule exists:
Switch1#show access-lists 100
You should see the following:
It’s important to note that by itself, an ACL doesn’t do anything. It is, as the name suggests, just a list of rules. At this point, Switch1 is not blocking any traffic because you haven’t explicitly told Switch1 to use ACL 100. Later on in the chapter, I’ll show you how to configure Switch1 to use this new ACL.
Notice that there’s a 10 preceding the rule you just created. When you create a rule, IOS assigns a sequence number in increments of 10. The first rule is 10, the second is 20, and so on. It’s called a sequence number because when IOS looks at an ACL to determine what to do with a given packet, it evaluates each rule in order, starting with the lowest sequence number. To understand how this works, let’s look at two examples.
The first example may strike you as painfully obvious, but it illustrates an important point. If IOS sees a packet with the source IP address 172.31.60.51 and the destination IP address 172.31.70.51, it first looks at rule 10. Because the source and destination IP addresses match what the rule specifies, IOS performs the action required by the rule, in this case, deny. IOS drops the packet, and it’s done.
Now let’s take a contrasting example. Suppose IOS sees a packet with the source IP address 172.31.60.51 and the destination IP address 192.168.100.1. IOS first looks at the rule with the lowest sequence number, which is 10. The source IP address—172.31.60.51—matches what’s in the rule. But the destination IP address—192.168.100.1—does not. Because the packet doesn’t match the rule exactly, IOS doesn’t take the deny action specified in rule 10. But then what happens to the packet?
You might assume that IOS allows the packet through, and that’s a reasonable assumption. After all, the point of ACLs is to block packets, and the only rule you specified in the ACL—rule 10—does not prohibit the packet in question. But there’s another rule—a hidden rule—that does prohibit the packet.
Every ACL, as soon as you create it, contains a secret, hidden rule called the implicit deny rule. The rule looks like this:
deny ip any any
You can blame Cisco for being counterintuitive on a lot of things, but this command does exactly what it says. It denies traffic from any IP address to any IP address. In other words, the implicit deny rule blocks all IP traffic.
IOS ensures that the implicit deny rule exists at the bottom of every ACL. No matter how many rules you explicitly define in an ACL, the implicit deny rule is always waiting at the bottom of the list. The rule is hidden, so you can’t see it, but it’s there! Table 9.2 illustrates how IOS views ACL 100.
Sequence |
Action |
Source |
Destination |
---|---|---|---|
10 | Deny | 172.31.60.51 (HR-PC1) | 172.31.70.51 (Executive-PC1) |
Last (hidden) | Deny | Any | Any |
Sequence 10 corresponds to the rule you just configured. But the rule immediately following it—the last in the sequence—is the implicit deny rule that IOS inserts automatically.
Your goal is to prevent HR-PC1 from reaching Executive-PC1, and ACL 100 accomplishes that, but it goes way too far. The implicit deny rule causes the ACL to deny all IP traffic, including traffic that you want to permit.
The obvious solution would be to get rid of the implicit deny rule—except you can’t do that. Instead, you have to circumvent it by creating another rule to permit all traffic.
Get back into ACL configuration mode for ACL 100:
Switch1(config)#ip access-list extended 100
Create another rule to explicitly permit all IP traffic:
Switch1(config-ext-nacl)# permit ip any any
IOS will automatically insert this rule at the bottom of the access list.
Exit ACL configuration mode:
Switch1(config-ext-nacl)#exit
Verify the new rule exists:
Switch1#sh access-lists 100
You should see the new rule in sequence 20:
Going back to the earlier example, if IOS sees a packet with the source IP address 172.31.60.51 and the destination IP address 192.168.100.1, it first compares the packet against the rule in sequence 10. The packet doesn’t match the rule, so IOS continues down the list. The rule in sequence 20—permit ip any any—matches the packet, so IOS takes the configured action: permit.
This effectively circumvents the implicit deny rule because once IOS takes some action on a packet—permit or deny—it stops processing subsequent rules.
Now’s a good time to point out that in highly restrictive, Fort Knox–style environments, you may want an ACL to block all IP traffic by default. If that’s the case, you should not place the permit ip any any statement in your ACL. Instead, you should explicitly permit only the traffic you want allowed and then let the implicit deny do its thing for all other traffic. Alternatively, you could configure an explicit deny—deny ip any any—as the last rule in the ACL.
In this case, the ACL is exactly the way you want it. It denies traffic from HR-PC1 to Executive-PC1 and allows everything else. But as I mentioned earlier, an ACL does nothing by itself. To configure Switch1 to use the ACL and actually start blocking traffic, you must apply the ACL to an interface.
As a general rule, you should apply an ACL on the interface closest to the source of the traffic you want to block. In this case, ACL 100 blocks traffic from HR-PC1 from reaching Executive-PC1, so the best place to apply the ACL is the port that HR-PC1 is connected to, FastEthernet0/20. To understand the logic behind this, look at figure 9.3.
Traffic coming from HR-PC1 flows into FastEthernet0/20. In networking parlance, traffic sourced from HR-PC1 ingresses FastEthernet0/20. If you want Switch1 to block any traffic from HR-PC1, the best place to do it is at the interface where that traffic comes in. Hence, you would apply the ACL to the FastEthernet0/20 interface.
Apply ACL 100 to FastEthernet0/20 using the following commands.
Get into interface configuration mode for FastEthernet0/20:
Switch1(config)#interface fastEthernet 0/20
Apply ACL 100 to the interface:
Switch1(config-if)#ip access-group 100 in
The ip access-group 100 in the command throws off a lot of newcomers. Even though it says nothing about “access list,” it does in fact refer to ACL 100. As I’ve pointed out before (and probably will again), Cisco likes to use multiple terms for the same thing.
The significance of the in keyword at the end of the command is a bit less obvious. It means that IOS should apply the ACL rules only to inbound traffic—that is, traffic coming into FastEthernet0/20. It shouldn’t touch traffic exiting, or egressing, FastEthernet0/20.
Verify that ACL 100 is applied to FastEthernet0/20:
Switch1#show ip interface fastEthernet 0/20
You should see the following:
Switch1#sh ip interface fastEthernet 0/20
FastEthernet0/20 is up, line protocol is up
Inbound access list is 100
In case you didn’t believe me that the access-group command really refers to an access list, the last line in the output should erase any doubts. At this point, IOS checks all IP traffic ingressing FastEthernet0/20 against ACL 100.
It’s a good idea to always verify your configurations in multiple ways, if possible. So far, you’ve verified that the ACL exists, has the proper rules in place, and is applied to the correct interface. But the best way to verify that all of these pieces are working together is to attempt to ping Executive-PC1 from HR-PC1. If you’ve done everything correctly, the ping should fail.
Use the ping command to verify that HR-PC1 (172.31.60.51) can’t reach Executive-PC1 (172.31.70.51). Assuming your test machines have the same IP addresses as mine, issue the following command on HR-PC1:
ping 172.31.70.51
The following output is from HR-PC1:
C:\>ping 172.31.70.51 Pinging 172.31.70.51 with 32 bytes of data: Request timed out.
Remember that the goal is to prevent HR-PC1 from reaching Executive-PC1 without restricting traffic from HR-PC1 in any other way. The consistent ping failure indicates that the ACL is blocking traffic from HR-PC1 to Executive-PC1. But to confirm that Switch1 allows all other traffic from HR-PC1, let’s try to ping a different IP address to confirm that all other traffic is allowed.
On HR-PC1, ping the VLAN 700 SVI (172.31.70.254):
ping 172.31.70.254
You should see the following:
C:\>ping 172.31.70.254 Pinging 172.31.70.254 with 32 bytes of data: Reply from 172.31.70.254: bytes=32 time=4ms TTL=255
Success! Switch1 blocks HR-PC1 from reaching Executive-PC1 without interfering with any other IP traffic sourced from HR-PC1.
As it stands, the ACL you applied inbound to FastEthernet0/20—ACL 100—blocks only traffic from HR-PC1 to Executive-PC1. Now suppose that you want to block traffic from HR-PC1 to all devices in the Executives VLAN. The simplest, safest way to accomplish this is to create a new ACL with the rules listed in table 9.3 and apply it to FastEthernet0/20.
Sequence |
Action |
Source |
Destination |
---|---|---|---|
10 | Deny | 172.31.60.51 (HR-PC1) | 172.31.70.0/255.255.255.0 (Executives VLAN 700) |
20 | Permit | Any | Any |
The Executives VLAN corresponds to the 172.31.70.0 subnet. Notice that for sequence 10, the destination contains both the subnet (172.31.70.0) and a subnet mask (255.255.255.0). Recall that the subnet mask is the code that tells you the IP addresses that are part of the VLAN. When specifying an entire subnet as the destination in an ACL, you must tell IOS the subnet mask. But there’s a catch: you can’t use the subnet mask in an ACL.
Because ACL 100 is already in use, you don’t want to modify or delete it. Instead, create a brand-new ACL:
Switch1(config)#ip access-list extended 101
Add a rule to block access to the Executives VLAN from HR-PC1:
Switch1(config)#deny ip host 172.31.60.51 172.31.70.0 0.0.0.255
I know that last parameter looks a little weird, and I’ll explain it in a moment. But first, you must overcome the implicit deny rule:
Switch1(config)#permit ip any any
Verify the new ACL with show access-lists 101.
You should see the following:
Switch1#sh access-lists 101 Extended IP access list 101 10 deny ip host 172.31.60.51 172.31.70.0 0.0.0.255 20 permit ip any any
The destination portion of the command looks noticeably different than the one you configured earlier. The last two parameters, 172.31.70.0 0.0.0.255, indicate the destination subnet. But 0.0.0.255 isn’t a valid subnet mask. In fact, it’s called a wildcard mask, and it’s the inverse of a subnet mask. Table 9.4 illustrates what I mean.
Subnet mask |
Wildcard mask |
---|---|
255.0.0.0 | 0.255.255.255 |
255.255.0.0 | 0.0.255.255 |
255.255.255.0 | 0.0.0.255 |
255.255.255.255 | 0.0.0.0 |
I’m not going to get into the nerdy details of why Cisco ACLs use wildcard masks instead of subnet masks. It involves a lot of binary math, which you’ll pick up should you decide to pursue Cisco certifications. What you need to know is that when configuring an ACL rule, instead of specifying the subnet mask, you must specify the corresponding wildcard mask. Bookmark the previous page so you can come back to this table as needed.
It’s important that you understand what the command in figure 9.4 does. Notice that immediately preceding the destination subnet and wildcard mask there’s no host. That’s because the destination is not a host but a subnet.
Now that you’ve configured ACL 101, it’s time to replace ACL 100 with it. To refresh your memory, you need to apply ACL 101 to FastEthernet0/20.
Use the following commands to apply ACL 101 to FastEthernet0/20:
Switch1(config)#int fa0/20 Switch1(config-if)#ip access-group 101 in
If you configured everything correctly, HR-PC1 shouldn’t be able to reach any device in the 172.31.70.0 subnet. Let’s test it out.
Try to ping Executive-PC1 again from HR-PC1:
ping 172.31.70.51
You should get nothing but failures, as shown:
C:\>ping 172.31.70.51 Pinging 172.31.70.51 with 32 bytes of data: Request timed out.
Now for the real test! You shouldn’t be able to ping any IP address in the 172.31.70.0 subnet, including the VLAN 700 SVI (172.31.70.254).
ping 172.31.70.254
This ping should fail as well:
C:\>ping 172.31.70.254 Pinging 172.31.70.254 with 32 bytes of data: Request timed out.
Excellent! The ACL works exactly the way you configured it. But there’s a potential problem. You applied ACL 101 to FastEthernet0/20, which is connected to HR-PC1. Suppose someone (not you, of course) moves HR-PC1 to a different port, say FastEthernet0/19. Let’s look at the configuration of that port to figure out what might happen:
Switch1#sh run int fa0/19 interface FastEthernet0/19 switchport access vlan 600 switchport mode access end
Notice two things. First, this port is a member of VLAN 600, the HR VLAN, so HR-PC1 still has network connectivity. But there’s no ACL applied to this interface, so HR-PC1 can still reach the Executives VLAN! A show ip interface fa0/19 confirms this:
Switch1#show ip interface fa0/19 FastEthernet0/19 is up, line protocol is up Inbound access list is not set
Move HR-PC1 to another port in VLAN 600; then try to ping Executive-PC1 again:
ping 172.31.70.51
You can see that HR-PC1 has unrestricted access now:
C:\> ping 172.31.70.51 Pinging 172.31.70.51 with 32 bytes of data: Reply from 172.31.70.51: bytes=32 time=1ms TTL=127
Applying the ACL at the port level works fine as long as the device you’re blocking traffic from doesn’t move to a different port. But if the device does move, the ACL becomes moot. You could apply the ACL to every port in the VLAN, but that would be cumbersome. Fortunately, you have a better option.
Rather than applying ACL 101 to every port in VLAN 600, you can apply it to the VLAN 600 switched virtual interface.
You need to block HR-PC1 from getting to the Executives subnet regardless of which port it’s plugged into. You can do this by applying the access list directly to the VLAN 600 SVI.
Enter interface configuration mode for the VLAN 600 SVI:
Switch1(config)#int vlan600 Switch1(config-if)#ip access-group 101 in
Verify your configuration:
show ip interface vlan 600 | i 600|101
You should see the following output:
Switch1#show ip interface vlan 600 | i 600|101 Vlan600 is up, line protocol is up Inbound access list is 101
Because you applied ACL 101 to the VLAN 600 SVI, IOS applies ACL 101 to all traffic hitting the VLAN 600 SVI, regardless of which physical port the traffic came from. That means even though HR-PC1 is connected to a port that doesn’t have an ACL applied, any traffic from HR-PC1 destined to the Executives VLAN will still get blocked.
On HR-PC1, ping Executive-PC1:
ping 172.31.70.51
You should see a ping failure:
C:\>ping 172.31.70.51 Pinging 172.31.70.51 with 32 bytes of data: Reply from 172.31.60.254: Destination net unreachable.
Another ping to the VLAN 700 SVI should yield the same result:
On HR-PC1, ping the VLAN 700 SVI:
ping 172.31.70.254
C:\>ping 172.31.70.254 Pinging 172.31.70.254 with 32 bytes of data: Reply from 172.31.60.254: Destination net unreachable.
At this point, you have a pretty robust ACL configuration. Regardless of which physical port HR-PC1 is connected to, it can’t reach any device in the Executives VLAN. But there’s still another problem. Because HR-PC1 receives its IP address via DHCP, its IP address could change, rendering the ACL once again useless. To overcome this, you need to make your ACL fully DHCP-proof.
When configuring ACLs, it’s easy to get lost in all the details. But as a network administrator, you should always keep in mind the ultimate goal you’re trying to accomplish. At the beginning of the chapter, I laid out a simple requirement: prevent HR-PC1 from reaching Executive-PC1. I later modified that requirement to prohibit HR-PC1 from reaching any device in the Executives VLAN. You might be sensing a pattern here, and can probably guess what’s coming next!
Given that devices in the HR and Executives VLANs get their IP addresses from DHCP, it’s clear that configuring ACLs to block traffic to or from individual IP addresses isn’t going to cut it. This leaves you with only one option: prevent all IP traffic from VLAN 600 from reaching VLAN 700. It’s time to create another ACL!
Create ACL 102 to block all traffic from the 172.31.60.0 subnet to the 172.31.70.0 subnet:
Switch1(config)#ip access-list extended 102 Switch1(config-ext-nacl)#deny ip 172.31.60.0 0.0.0.255 172.31.70.0 0.0.0.255 Switch1(config-ext-nacl)#permit ip any any
Apply the ACL to the VLAN 600 SVI:
Switch1(config)#int vlan 600 Switch1(config-if)#ip access-group 102 in
Now no devices in the 172.31.60.0 subnet should be able to reach devices in the 172.31.70.0 subnet. Let’s test it by pinging a few IP addresses:
From HR-PC1, ping Executive-PC1 and the VLAN 700 SVI:
ping 172.31.70.51 ping 172.31.70.254
Both pings should fail:
C:\>ping 172.31.70.51 Pinging 172.31.70.51 with 32 bytes of data: Reply from 172.31.60.254: Destination net unreachable. C:\>ping 172.31.70.254 Pinging 172.31.70.254 with 32 bytes of data: Reply from 172.31.60.254: Destination net unreachable.
This looks good, but it’s inconclusive because these are exactly the same results you saw before. The real test is to change HR-PC1’s IP address and ping again.
Change HR-PC1’s IP address to a static one outside the configured DHCP range.
Set the default gateway to 172.31.60.254.
In the last chapter, you configured the DHCP range for VLAN 600 to be 172.31.60.50–172.31.60.250. Figure 9.5 illustrates how to statically configure HR-PC1 with the IP address 172.31.60.49, which is outside the DHCP scope. Remember to set the default gateway!
From HR-PC1, ping 172.31.70.51 and 172.31.70.254 again.
You should get the same results as you did before changing the IP address:
C:\>ping 172.31.70.51 Pinging 172.31.70.51 with 32 bytes of data: Reply from 172.31.60.254: Destination net unreachable. C:\>ping 172.31.70.254 Pinging 172.31.70.254 with 32 bytes of data: Reply from 172.31.60.254: Destination net unreachable.
As it stands, Switch1 prevents every device in the 172.31.60.0 subnet from accessing any device in the 172.31.70.0 subnet. But you might be thinking, “What if I don’t want to do that? What if I just want to restrict a few IP addresses here and there?” Suppose that you want HR-PC1 to be able to access only 172.31.70.254 but nothing else in that subnet. You can accomplish this using ACLs but with one minor change.
Create a new ACL 103:
Switch1(config)#ip access-list extended 103
Permit any device in the HR VLAN to access only 172.31.70.254, the VLAN 700 SVI:
Switch1(config-ext-nacl)#permit ip 172.31.60.0 0.0.0.255 host 172.31.70.254
Prohibit all other devices in the HR VLAN from accessing any device in the 172.31.70.0 subnet:
deny ip 172.31.60.0 0.0.0.255 172.31.70.0 0.0.0.255
Overcome the implicit deny rule:
permit ip any any
Verify the new ACL with show access-list 103.
You should see the following:
Switch1#show access-lists 103 Extended IP access list 103 10 permit ip 172.31.60.0 0.0.0.255 host 172.31.70.254 20 deny ip 172.31.60.0 0.0.0.255 172.31.70.0 0.0.0.255 30 permit ip any any
Now all you have to do is apply this new ACL to the VLAN 600 SVI.
Apply ACL 103 to the VLAN 600 SVI:
Switch1(config)#int vlan 600 Switch1(config-if)#ip access-group 103 in
Verify that HR-PC1 can ping 172.31.70.254 but nothing else in the Executives subnet:
ping 172.31.70.254 ping 172.31.70.51
HR-PC1 can ping the VLAN 700 SVI without any problem:
C:\>ping 172.31.70.254 Pinging 172.31.70.254 with 32 bytes of data: Reply from 172.31.70.254: bytes=32 time=2ms TTL=255
But it can’t ping Executive-PC1:
C:\>ping 172.31.70.51 Pinging 172.31.70.51 with 32 bytes of data: Reply from 172.31.60.254: Destination net unreachable.
The order of operations in an ACL is not something you want to mess up, because it can mean the difference between a working ACL and one that doesn’t do anything. Refer to table 9.5 as you complete the hands-on lab. To make things easier, I’ve listed the commands in the order in which you would execute them.
Command |
Configuration mode |
Description |
---|---|---|
ip access-list extended 150 | Global | Creates ACL 150 and enters IP extended access list configuration mode |
deny ip host 1.2.3.4 host 5.6.7.8 | IP extended access list | Denies IP traffic from 1.2.3.4 to 5.6.7.8 |
permit ip 172.31.10.0 0.0.0.255 host 7.7.7.7 | IP extended access list | Permits any IP traffic from the 172.31.10.0/255.255.255.0 subnet to 7.7.7.7 |
permit ip any any | IP extended access list | Permits all IP traffic |
ip access-group 150 in | Interface | Applies ACL 150 to the selected interface |
In this chapter, you used ACLs to control IP traffic from VLAN 600 to VLAN 700. For the lab, you’re going to configure an ACL to restrict traffic in the opposite direction, from VLAN 700 to VLAN 600.
Perform the following tasks: