Hotel case study - ACL

From csn
Jump to navigation Jump to search

ACL

Explanation
Before configuring ACLs you must test your configuration thoroughly. Once you implement an ACL, connectivity can be broken through physical failure, misconfiguration or the actions of the ACL. It is much more difficult to troubleshoot.

From the scenario, the security requirements are as follows:

1. Only communications initiated from within HCGs network should be allowed to enter the hotel from the Internet.
2. No direct traffic is allowed to flow between the guest subnets and the hotel systems and hotel users.
3. No user should be able to access addresses in the range 1.2.3.4-10 as these are known phishing sites.
4. All users should be able to ping any Internet address. You can test with the simulated Google.com (172.217.25.164).
5. Guests are only allowed to browse the web. They are not allowed to use protocols other than HTTP, HTTPS (ping is OK).

There are a number of requirements here but it can be helpful to think of the rules in terms of specific classes of users and rules that apply to all users. As a general principle, Internet rules that apply to whole organisation are most easily position near the exit to the Internet as all traffic of interest will pass through this point and you can limit the number of places you need to configure the ACL. Most organisations use a firewall between the ISP and their enterprise for this purpose. A natural place to impose such rules would be on the S1/1 interface on the Core routers. However, as a general rule you should avoid ACLs on core devices as their role in 3-layer hierarchy is to forward packets quickly and ACLs can impact performance. In this situation I would advise the hotel to install another router between the core and the ISP. The role of this router would be similar to a distribution-layer router where we implement policy. However, you can't change the topology so we will be forced to implement our security on the distribution layer device.

Let's step through the requirements.

1

The hotel group use NAT so unless an Internet access packet passes from inside the hotel group to the outside, no NAT translation exists and no traffic can pass from the Internet to the hotel. In this way NAT acts an effective basic firewall. There is nothing to do for the first requirement as NAT delivers this functionality.

2

This rule says that hotel guests are not permitted to access anything else in the hotel. No internal systems or any class of users. You might be tempted to start creating an ACL that denies a list of floors and staff subnets etc. But that would be a very long list that needs to be updated every-time the network grows. Instead, for guests you can deny them from sending traffic to any address on the 10.0.0.0/8 network. In the absence of any other rules we would permit traffic to any other address (the Internet).

Router(config)#ip access-list extended PREVENT_GUEST_10_NET
Router(config-std-nacl)#deny ip any 10.0.0.0 0.255.255.255
Router(config-std-nacl)#permit ip any any             --> Until we are told otherwise, guests can do anything on the Internet.

* Important:  The sourrce address is any.  This is only possible if you place this ACL where only the guest traffic will flow. 
Such as a guest VLAN inbound on a DL router.  If you place the ACL outbound on the DL interface to the Core, you would need to 
swap any for a specific address/wildcard that selected just the guest traffic.

3

The third rule states that no user should be able to access addresses in the range 1.2.3.4-10 as these are known phishing sites. As this is a site-wide rule, it makes sense to implement it as high as possible and catch traffic as it passes through bottlenecks. As we have a range of IP addresses, you may (will) need more than one deny statement to cover the range. You should carefully choose the wildcard mask to minimise the number of statements.

When determining wildcard masks it is important to look at the addresses in binary.

1.2.3 . 0 0 0 0 0 1 0 0    (4)
1.2.3 . 0 0 0 0 0 1 0 1    (5)
1.2.3 . 0 0 0 0 0 1 1 0    (6)
1.2.3 . 0 0 0 0 0 1 1 1    (7)
1.2.3 . 0 0 0 0 1 0 0 0    (8)
1.2.3 . 0 0 0 0 1 0 0 1    (9)
1.2.3 . 0 0 0 0 1 0 1 0   (10)

We have to look at an ACL in terms of portions that must match and bits we don't care about (wild): Clearly each address needs to start with 1.2.3 so our wild card would start with 0.0.0 indicating that those bits must match. But the last octet is more difficult.

One approach is to look for the largest block of continuous zeros on the right hand side and see if that can be used to group a block of addresses into a single statement.

The largest group is the three zeros highlighted.

1.2.3 . 0 0 0 0 0 1 0 0    (4)
1.2.3 . 0 0 0 0 0 1 0 1    (5)
1.2.3 . 0 0 0 0 0 1 1 0    (6)
1.2.3 . 0 0 0 0 0 1 1 1    (7)
1.2.3 . 0 0 0 0 1 0 0 0    (8) <--
1.2.3 . 0 0 0 0 1 0 0 1    (9)
1.2.3 . 0 0 0 0 1 0 1 0   (10)

The reason we look for blocks of zeros is because it gives us a block on the left that will match (what ACLs do).


If you look at the region to the left of the zeros you can see that the next three entries all start with "0 0 0 0 1". So we can create an ACL that matches on this. But for anything that doesn't match we must be prepared to accept any value. If we count up in binary we would go from "0 0 0" to "1 1 1". In the example below this is not possible. "0 0 0" is OK; "0 0 1" is OK; "0 1 0" is OK but "0 1 1" and on-wards is outside our range. It would be a group of 8 numbers and we only want to include 3 in our ACL.

1.2.3 . 0 0 0 0 0 1 0 0    (4)
1.2.3 . 0 0 0 0 0 1 0 1    (5)
1.2.3 . 0 0 0 0 0 1 1 0    (6)
1.2.3 . 0 0 0 0 0 1 1 1    (7)
1.2.3 . 0 0 0 0 1|0 0 0    (8)
1.2.3 . 0 0 0 0 1|0 0 1    (9)
1.2.3 . 0 0 0 0 1|0 1 0   (10)

This means that starting from three zeros is not possible at this point. So we go looking for smaller groupings (two zeros). Let's start at the top.

1.2.3 . 0 0 0 0 0 1 0 0    (4) <--
1.2.3 . 0 0 0 0 0 1 0 1    (5)
1.2.3 . 0 0 0 0 0 1 1 0    (6)
1.2.3 . 0 0 0 0 0 1 1 1    (7)
1.2.3 . 0 0 0 0 1 0 0 0    (8)
1.2.3 . 0 0 0 0 1 0 0 1    (9)
1.2.3 . 0 0 0 0 1 0 1 0   (10)

Again we draw a line dividing bits that must match from those that we don't care about. We stop our line when the bits on the left are no longer the same (matching). If the bits on the right of the line cover all the possible values for two bits "0 0" through "1 1" then we can truly say "we don't care" what those bit values are (they are wild).

1.2.3 . 0 0 0 0 0 1|0 0    (4)
1.2.3 . 0 0 0 0 0 1|0 1    (5)
1.2.3 . 0 0 0 0 0 1|1 0    (6)
1.2.3 . 0 0 0 0 0 1|1 1    (7)
1.2.3 . 0 0 0 0 1 0 0 0    (8)
1.2.3 . 0 0 0 0 1 0 0 1    (9)
1.2.3 . 0 0 0 0 1 0 1 0   (10)

Great, we have a block of bits that we can divide into a "match" and a "wild" portion. We can write a single ACL statement to represent that range. Draw a line under it so we know where we up to.

1.2.3 . 0 0 0 0 0 1|0 0    (4)
1.2.3 . 0 0 0 0 0 1|0 1    (5)
1.2.3 . 0 0 0 0 0 1|1 0    (6)
1.2.3 . 0 0 0 0 0 1|1 1    (7)
------------------------------
1.2.3 . 0 0 0 0 1 0 0 0    (8)
1.2.3 . 0 0 0 0 1 0 0 1    (9)
1.2.3 . 0 0 0 0 1 0 1 0   (10)

Lets look to see if there is another pair of zeros on the right. There is. We are revisiting (8) but looking at just two zeros (not 3 because we know the block isn't that big)

1.2.3 . 0 0 0 0 0 1|0 0    (4)
1.2.3 . 0 0 0 0 0 1|0 1    (5)
1.2.3 . 0 0 0 0 0 1|1 0    (6)
1.2.3 . 0 0 0 0 0 1|1 1    (7)
------------------------------
1.2.3 . 0 0 0 0 1 0 0 0    (8) <--
1.2.3 . 0 0 0 0 1 0 0 1    (9)
1.2.3 . 0 0 0 0 1 0 1 0   (10)


If you look below you will see that on the right side we haven't covered the full range "0 0" to "1 1". So again we can't cover this block of three addresses with a single statement. You should soon see that if we have two bits we define four addresses. So three addresses can never be matched.

1.2.3 . 0 0 0 0 0 1|0 0    (4)
1.2.3 . 0 0 0 0 0 1|0 1    (5)
1.2.3 . 0 0 0 0 0 1|1 0    (6)
1.2.3 . 0 0 0 0 0 1|1 1    (7)
------------------------------
1.2.3 . 0 0 0 0 1 0|0 0    (8)
1.2.3 . 0 0 0 0 1 0|0 1    (9)
1.2.3 . 0 0 0 0 1 0|1 0   (10)

Now we have exhausted the consecutive two zero entries we step back to just one zero. Again, confirm the left all matches and the right covers both states of one bit "0" and "1". It does. So we can represent those two addresses with just one ACL statement.

1.2.3 . 0 0 0 0 0 1|0 0    (4)
1.2.3 . 0 0 0 0 0 1|0 1    (5)
1.2.3 . 0 0 0 0 0 1|1 0    (6)
1.2.3 . 0 0 0 0 0 1|1 1    (7)
------------------------------
1.2.3 . 0 0 0 0 1 0 0|0    (8) <--
1.2.3 . 0 0 0 0 1 0 0|1    (9)
1.2.3 . 0 0 0 0 1 0 1 0   (10)

Let's rule that off and see what is left. Just one entry. In this case we care about every bit. Everything must match. This will become its own line in the ACL

1.2.3 . 0 0 0 0 0 1|0 0    (4)
1.2.3 . 0 0 0 0 0 1|0 1    (5)
1.2.3 . 0 0 0 0 0 1|1 0    (6)
1.2.3 . 0 0 0 0 0 1|1 1    (7)
------------------------------
1.2.3 . 0 0 0 0 1 0 0|0    (8)
1.2.3 . 0 0 0 0 1 0 0|1    (9)
------------------------------
1.2.3 . 0 0 0 0 1 0 1 0   (10) <---

Let's add the addresses we are comparing in each line of ACL so you can see where they come from:

1.2.3 . 0 0 0 0 0 1|0 0    (4)     1.2.3.4
1.2.3 . 0 0 0 0 0 1|0 1    (5)
1.2.3 . 0 0 0 0 0 1|1 0    (6)
1.2.3 . 0 0 0 0 0 1|1 1    (7)
------------------------------
1.2.3 . 0 0 0 0 1 0 0|0    (8)     1.2.3.8
1.2.3 . 0 0 0 0 1 0 0|1    (9)
------------------------------
1.2.3 . 0 0 0 0 1 0 1 0   (10)     1.2.3.10

And the wild card masks. Remember a zero means we must match and a one means it is wild (we don't care). As we have said the first three octets must match (1.2.3) so the first bytes in our wild card mask must match. Let's do the last octet in the binary.

1.2.3 . 0 0 0 0 0 1|0 0    (4)     1.2.3.4  0.0.0. 0 0 0 0 0 0 1 1 (last two bits are wild)
1.2.3 . 0 0 0 0 0 1|0 1    (5)
1.2.3 . 0 0 0 0 0 1|1 0    (6)
1.2.3 . 0 0 0 0 0 1|1 1    (7)
------------------------------
1.2.3 . 0 0 0 0 1 0 0|0    (8)     1.2.3.8  0.0.0. 0 0 0 0 0 0 0 1 (last single bit wild)
1.2.3 . 0 0 0 0 1 0 0|1    (9)
------------------------------
1.2.3 . 0 0 0 0 1 0 1 0   (10)     1.2.3.10 0.0.0. 0 0 0 0 0 0 0 0 (no wild bits, this is a single host)

Revisiting our requirements, remember we need to block (deny) traffic from these phishing sites. As we will block all of the IP protocol (which carries TCP/UDP/ICMP) from a source we can use a standard access list.

Router(config)#ip access-list standard BLOCK_PHISHING
Router(config-std-nacl)#deny 1.2.3.4 0.0.0.3
Router(config-std-nacl)#deny 1.2.3.8 0.0.0.1
Router(config-std-nacl)#deny host 1.2.3.10
Router(config-std-nacl)#permit any             --> We must have something permitted or nothing will pass the ACL.

4

Rule 4 says everyone can ping the Internet. We have two groups; staff and guests. So far we don't have any restrictions specifically for staff. So apart from not getting access to the phisihng site, they have appear to have unrestricted access to the Internet. So permitting ICMP (ping) for staff isn't something we need to do if there is nothing that would (deny) them access. For guests, we are preventing them sending packets to other IP addresses in the 10.0.0.0/8 network but they have a "permit any" allowing Internet access. So again, there is nothing to do at this stage. They can already ping the Internet. We just need to keep it in mind if there is another rule that might otherwise take away their ability to ping an Internet site.

5

The final rule says that guests can only use HTTP (80) /HTTPS (443) and ping (ICMP echo) to the Internet. So our guests really have a black list. Unless we explicitly give them access, they cannot use particular protocols.

We already have a partial ACL for guests from step 1.

Router(config)#ip access-list extended PREVENT_GUEST_10_NET
Router(config-std-nacl)#deny ip any 10.0.0.0 0.255.255.255
Router(config-std-nacl)#permit ip any any

Rule 5 says they can ONLY do HTTP/HTTPS and ping. That means everything else is denied. In isolation the ACL would look like this:

Router(config)#ip access-list extended GUEST_INTERNET_RULES
Router(config-std-nacl)#permit tcp any any eq 80 443 
Router(config-std-nacl)#permit icmp any any echo                  <-- A sent ping is actually an ICMP message "echo-request"
Router(config-std-nacl)#deny ip any any                           <-- Block all IP packets because this a black list

Pay attention that we are being specific and permitting tcp ports for web and secure web browsing. You must specify TCP rather than IP in that line. Also the source any assumes you place this ACL where no traffic sourced from the staff network will be present.

If you implement the ACLs on different interfaces then you can keep these as separate ACLS and traffic passing through both ACLs must satisfy both rules. If you wish to combine the ACLs into a single guest policy you must be careful in the sequencing.

Router(config)#ip access-list extended GUEST_NETWORK_POLICY
Router(config-std-nacl)#deny ip any 10.0.0.0 0.255.255.255              <-- No access to other hotel addresses.
Router(config-std-nacl)#permit tcp any any eq 80 443              <-- Web access allowed.
Router(config-std-nacl)#permit icmp any any echo                  <-- Ping is OK
Router(config-std-nacl)#deny ip any any                           <-- Guests can do nothing else

If you put the deny 10.0.0.0 after the permits for http/https/icmp, the guests will be allowed to perform these operations on hotel 10.0.0.0 users and systems.

Unintended Consequences

Although the ACLs above are correct, this is what happens when the GUEST_NETWORK_POLICY is applied in-bound on the VLAN interface.

SydDL2(config-if)#int vlan101
SydDL2(config-if)#ip access-g GUEST_NETWORK_POLICY in
SydDL2(config-if)#int vlan102
SydDL2(config-if)#ip access-g GUEST_NETWORK_POLICY in
*Oct 15 12:04:58.926: %HSRP-5-STATECHANGE: Vlan101 Grp 101 state Standby -> Active\
                                                     ^
% Invalid input detected at '^' marker. 

SydDL2(config-if)#
*Oct 15 12:05:26.913: %OSPF-5-ADJCHG: Process 1, Nbr 10.2.255.1 on Vlan101 from FULL to DOWN, Neighbor Down: Dead timer expired
SydDL2(config-if)#
  • HSRP on our router went from standby to active. Our router is not receiving HSRP hellos from the neighbour and thinks it has failed!
  • OSPF thinks a neighbouring router is dead because too much time (timer expired) passed since a hello was seen.

You need to be alert when things like this happen. We just applied some security rules (blocked packets) and two protocols, HSRP add OSPF, both experienced problems. What could we have done that caused them a problem? Answer; "They both use hello packets and we just created a rule forbidding anything but ping and web access." So we need to do some research and find out how to permit the OSPF and HSRP traffic. A Google search "ACL breaks HSRP" or "ACL breaks OSPF" very quickly leads to some clues as to how to fix the problem.

ip access-list extended GUEST_NETWORK_POLICY
 deny ip any 10.0.0.0 0.255.255.255             
 permit tcp any any eq 80 443           
 permit icmp any any echo  
 permit udp any host 224.0.0.2 eq 1985  <-- From the lecture slides or Google you can find what protocol, port and address HSRP uses.
 permit ospf any any                    <-- OSPF is a protocol in its own right so you can just allow it totally.
 deny ip any any                       


What you need to do?

  • Create the appropriate ACLs on the distribution-layer devices.
    • As there is more than one distribution-layer device that a users traffic could flow through, you need to ensure you have an ACL on each device that could the traffic flow through it.
    • Apply an access-group command on an appropriate interface to activate the ACL.
    • Think carefully as to the direction it should operate in.

Take care with the use of any as a source. Depending where you apply the ACL you may need change this to match traffic from the appropriate address range.

How will you know it is configured correctly?

  • If you are blocking all access (IP) then ping gives you some clue as to whether the ACL is active.
  • show access-lists is very handy to get a quick overview as to what has been configured.
PerDl1#sh access-lists 
Standard IP access list BLOCK_PHISHING
    30 deny   1.2.3.10
    10 deny   1.2.3.4, wildcard bits 0.0.0.3
    20 deny   1.2.3.8, wildcard bits 0.0.0.1
    40 permit any (307 matches)
Extended IP access list GUEST_NETWORK_POLICY
    10 deny ip any 10.0.0.0 0.255.255.255
    20 permit tcp any any eq www 443
    30 permit icmp any any echo
    40 permit udp any host 224.0.0.2 eq 1985 (8 matches)
    50 permit ospf any any (2 matches)
    60 deny ip any any

By testing communications (ping or other application) you can see the matches increment if the access-list statement is triggered.


  • If a Cisco router drops packets as a result of an ACL it will often send back a message.

In this case the router at 10.1.1.2 is telling us that an administrative rule (ACL) caused it to drop our packet.

VPCS> ping 10.1.128.10

*10.1.1.2 icmp_seq=1 ttl=255 time=12.019 ms (ICMP type:3, code:13, Communication administratively prohibited)


What questions could I see on the practical exam?

  • An ACL may not work properly.
    • It might have an incorrect statement.
    • It might be applied in the incorrect direction.
    • It might not be applied to an interface.
  • You may be given a range of addresses that need to be permitted/denied and asked to determine one or more lines to be added to an existing ACL.
  • You may be asked whether a particular user will be able access a particular service (telnet/SSH/HTTP/HTPPS etc) on a given IP address.