CBAC vs ZBF

On February 24, 2012, in CCIE, by Darren

As both of these are on the blueprint, I thought it would help to write a blog post about the differences and how to configure them both.

In the real world however, I would not use either of them. If I wanted to firewall, I would use a dedicated firewall. I can see the benefits here and there of knowing how to actually configure up a quick firewall in IOS though.

CBAC (Context-Based Access Control) is the legacy type of firewall, though it’s perfactly acceptable to use it when you only have 2 interfaces. ZBF (Zone-Based Firewall) is the improved zone-based firewall. I much prefer this way simply because it’s more in line with Juniper firewalls which I work with daily. It may even match ASAs, but I’ve never actually used an ASA so I don’t know.

ZBF actually uses the CBAC engine in the background, but it’s easier to work out what you’re doing when you have multiple interfaces. There is also a fundamental difference with router generated traffic itself.

Let’s start with CBAC. Let’s use a simple topology:

REALCBAC CBAC vs ZBF

R1 is our border router that is peering with our ISP with BGP. R3 is simply acting as a host in the LAN. We have a simple rule policy:

  • Allow TCP and UDP traffic from LAN to the internet and allow return traffic
  • Allow pings from externally to come in through R1

I’ve set up a very simple config. R3 has a default route pointing to R1. R2 is advertising a default route to R1 via BGP. R1 is advertising it’s directly connected interface to R2.

R3:

interface FastEthernet0/0
 ip address 10.13.13.3 255.255.255.0
!
ip route 0.0.0.0 0.0.0.0 10.13.13.1

R1:

interface FastEthernet1/0
 ip address 10.13.13.1 255.255.255.0
!
interface FastEthernet1/1
 ip address 10.12.12.1 255.255.255.0
!
router bgp 100
 network 10.13.13.0 mask 255.255.255.0
 neighbor 10.12.12.2 remote-as 200

R2:

interface Loopback1
 ip address 4.2.2.1 255.255.255.255
!
interface FastEthernet1/0
 ip address 10.12.12.2 255.255.255.0
!
router bgp 200
 neighbor 10.12.12.1 remote-as 100
 neighbor 10.12.12.1 default-originate

So let’s start with the configuration. We need to allow TCP and UDP out, inspect that traffic, and then allow repsonses back in. We also need to allow ICMP inbound.

R1:

ip inspect name INSPECT tcp
ip inspect name INSPECT udp
!
interface FastEthernet1/1
 ip access-group 101 in
 ip inspect INSPECT out
!
access-list 101 permit icmp any any
access-list 101 deny   ip any any

As soon as this is configured we have a problem:

*Feb 24 16:43:08.303: %BGP-5-ADJCHANGE: neighbor 10.12.12.2 Down BGP Notification sent
*Feb 24 16:43:08.307: %BGP-3-NOTIFICATION: sent to neighbor 10.12.12.2 4/0 (hold time expired) 0 bytes

We have an inspect policy configured on the outbound interface of R1. R1 has a BGP session which goes through that interface, but that is not inspected. With CBAC, router generated traffic is not inspected by default, and hence there is no exception made in the return ACL. CBAC does have the option of specifying router-generated traffic in the inspect rule, but it seems my version here does not support it! So I’ll have to make a manual exception:

access-list 101 permit icmp any any
access-list 101 permit tcp any eq bgp any
access-list 101 permit tcp any any eq bgp
access-list 101 deny   ip any any

BGP comes back up. Now let’s initiate a telnet to port 80 from inside the network to R2:

R3#telnet 4.2.2.1 80
Trying 4.2.2.1, 80 ... Open
R1# sh ip inspect sessions
Established Sessions
 Session 689C0CB0 (10.13.13.3:60582)=>(4.2.2.1:80) tcp SIS_OPEN

R1 has inspected the session and allowed the return traffic to come back in. Let’s try and initiate a telnet to port 80 from the ISP:

R2#telnet 10.13.13.3
Trying 10.13.13.3 ...
% Destination unreachable; gateway or host down

R2#ping 10.13.13.3
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.13.13.3, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 40/69/100 ms

I can’t get to port 80, but I can ping. So everything is working exactly how I wanted it to.

Let’s now kick it up a tiny notch. You’ve decided to make a DMZ where you have a web server.

CBAC CBAC vs ZBFThe problem with CBAC in this scenario is that you now need to have multiple inspection policies from each interface to each other interface. What happens if I get another LAN interface? Or perhaps another DMZ? Or why not an extra ISP interface? CBAC is configured per interface so it quickly get’s out of hand.

With ZBF though everything is configured per zone. At first the ZBF policy looks a bit more complicated, but as soon as you have more than 2 interfaces it makes a LOT more sense.

Let’s remove the ACLs and CBAC config from R1 and then configure R1 with ZBF to match the above requirements. We are also going to add the requirement that the ISP needs to be able to get to port 80 of our web server in the DMZ

ZBF uses the familiar MQC style config, so if you know your QoS it’s not that more complicated.

R1:

class-map type inspect match-all PORT80
 match protocol http
class-map type inspect match-all ICMP
 match protocol icmp
class-map type inspect match-all UDP
 match protocol udp
class-map type inspect match-all TCP
 match protocol tcp
!
!
policy-map type inspect INSIDE_OUT
 class type inspect TCP
  inspect
 class type inspect UDP
  inspect
 class type inspect ICMP
  pass
!
policy-map type inspect OUTISDE_IN
 class type inspect ICMP
  pass
!
policy-map type inspect OUTISDE_DMZ
 class type inspect PORT80
  inspect
  police rate 512000 burst 8000
!
zone security INSIDE
zone security OUTSIDE
zone security DMZ
!
zone-pair security OUTSIDE_TO_IN source OUTSIDE destination INSIDE
 service-policy type inspect OUTISDE_IN
zone-pair security INSIDE_TO_OUT source INSIDE destination OUTSIDE
 service-policy type inspect INSIDE_OUT
zone-pair security OUTSIDE_TO_DMZ source OUTSIDE destination DMZ
 service-policy type inspect OUTISDE_DMZ
!
interface FastEthernet1/0
 ip address 10.13.13.1 255.255.255.0
 zone-member security INSIDE
!
interface FastEthernet1/1
 ip address 10.12.12.1 255.255.255.0
 zone-member security OUTSIDE
!
interface FastEthernet2/0
 ip address 10.14.14.1 255.255.255.0
 zone-member security DMZ

I admit there is a lot of config, but if you break it down it’s not so difficult. We have defined our classes via MQC. The advantage of using MQC is that we can use NBAR to match all sorts of protocols. We then set up our service policies. Again as it’s MQC we can further police traffic directly in ZBF as I have done above.
We then set up our zones, our zone-pairs and match our created service policies into those pairs. Finally we put our interfaces into zones.

Let’s test the end result. Can we ping from LAN to WAN and vice versa:

R3#ping 4.2.2.1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 4.2.2.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 220/257/296 ms

R2#ping 10.13.13.3
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.13.13.3, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 64/92/128 ms

What about the DMZ? We should not be able to ping, but we should be able to get to port 80:

R2#ping 10.14.14.4
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.14.14.4, timeout is 2 seconds:
.....
Success rate is 0 percent (0/5)
R2#telnet 10.14.14.4 80
Trying 10.14.14.4, 80 ... Open

Perfect.

You’ll also notice BGP did not go down. When using ZBF, their is a ‘self’ zone created. By default all traffic is allowed to and from this zone, hence no reason to make exceptions for it to work.

The great thing about ZBF is that I can now add a bunch of interfaces to any zone, and those policies take effect without you having to add or change anything.

Tagged with:  

© 2009-2014 Darren O'Connor All Rights Reserved