Zone-Based Policy Firewall (ZFW) is a new feature that has replaced the CBAC (Context-Based Access Control) – legacy firewall IOS based feature. The drawback of CBAC was just stateful inspection policy on an interface-based model due of this all traffic passing through the interface was subject to the same inspection policy.
Zone-Based Policy Firewall has changed the IOS Stateful Inspection architecture from interface-based to a more flexible zone-based configuration architecture.
In ZFW router interfaces are assigned to security zones, firewall inspection policy is applied to traffic moving between the zones. By default router cannot pass traffic to interfaces in other security zones until an explicit policy allowing traffic is defined. The firewall rule has to defined what traffic is allowed to pass between interfaces in other security zones.
Firewall policies are configured using Class-Based Policy Language (CPL), which employs a hierarchical structure to define inspection for network protocols and the groups of hosts’ traffic to which inspection will be applied. Inter-zone policies offer considerable flexibility and granularity, so different inspection policies can be applied to hosts, host groups, or subnets connected to the same router interface.
The following tasks are required to complete the ZFW configuration using the CPL:
- Creating class-map(s) that identify the traffic that must have policy applied as it traverses a zone-pair
- Define a policy-map to apply action to the traffic in a class-map
- Defining zones
- Defining zone-pairs
- Appling a policy-map to a zone-pair
- Assigning interface to zones
Now I’m going to present you short examples of ZFW.
We have 3 routers for test, connected on the row.
We have pure configuration, just OSPF is running between each other. Ping and telnet from R1 to R3 is working fine.
R1#ping 10.0.23.3
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.0.23.3, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 36/57/112 ms
R1#telnet 10.0.23.3
Trying 10.0.23.3 ... Open
User Access VerificationPassword:
We will configure R2 as ZB firewall router between inside network where R1 is reside and outside network where we have R3. FW will just inspect icmp traffic from inside to outside, thanks to statefull inspection traffic will be allowed back the same like in CBAC.
First, we have to create inspect class-map to match ICMP traffic.
R2(config)#class-map type inspect match-all ICMP
R2(config-cmap)# match protocol icmp
Next, create inspect policy-map and assign ICMP class-map.
R2(config-cmap)#policy-map type inspect POLICY-INSIDE>OUTSIDE
R2(config-pmap)# class type inspect ICMP
R2(config-pmap-c)# inspect
Now, we have to create zones and zone pairs, so source and destination of traffic.
R2(config-pmap-c)#zone security INSIDE
R2(config-sec-zone)#zone security OUTSIDE
R2(config-sec-zone)#zone-pair security ZONE-PAIR-INSIDE>OUTSIDE source INSIDE destination OUTSIDE
R2(config-sec-zone-pair)#service-policy type inspect POLICY-INSIDE>OUTSIDE
Last step is to assign zones to interfaces.
R2(config)#int fa0/0
R2(config-if)#zone-member security INSIDE
R2(config-if)#int fa0/1
R2(config-if)#zone-member security OUTSIDE
OK, now let’s make a test again. First ping.
R1#ping 10.0.23.3
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.0.23.3, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 32/108/188 ms
Looks fine, so what about telnet.
R1#telnet 10.0.23.3
Trying 10.0.23.3 ...
% Connection timed out; remote host not responding
Good, no response as we have expected as no telnet or tcp inspection defined. Let’s do show policy-map to see inspection statistics.
R2#show policy-map type inspect zone-pair ZONE-PAIR-INSIDE>OUTSIDE
Zone-pair: ZONE-PAIR-INSIDE>OUTSIDE
Service-policy inspect : POLICY-INSIDE>OUTSIDE
Class-map: ICMP (match-all)
Match: protocol icmp
Inspect
Packet inspection statistics [process switch:fast switch]
icmp packets: [0:10]
Session creations since subsystem startup or last reset 1
Current session counts (estab/half-open/terminating) [0:0:0]
Maxever session counts (estab/half-open/terminating) [1:1:0]
Last session created 00:01:32
Last statistic reset never
Last session creation rate 0
Maxever session creation rate 1
Last half-open session total 0
Class-map: class-default (match-any)
Match: any
Drop (default action)
2 packets, 48 bytes
OK let’s add next class-map with telnet.
R2(config)#class-map type inspect match-all TELNET
R2(config-cmap)# match protocol telnet
R2(config-cmap)#policy-map type inspect POLICY-INSIDE>OUTSIDE
R2(config-pmap)# class type inspect TELNET
R2(config-pmap-c)# inspect
Quick test.
R1#telnet 10.0.23.3
Trying 10.0.23.3 ... Open
User Access Verification
Password:
R3#
We are in :), so see statictis and session details.
R2#show policy-map type inspect zone-pair ZONE-PAIR-INSIDE>OUTSIDE
Zone-pair: ZONE-PAIR-INSIDE>OUTSIDE
Service-policy inspect : POLICY-INSIDE>OUTSIDE
Class-map: ICMP (match-all)
Match: protocol icmp
Inspect
Packet inspection statistics [process switch:fast switch]
icmp packets: [0:20]
Session creations since subsystem startup or last reset 2
Current session counts (estab/half-open/terminating) [0:0:0]
Maxever session counts (estab/half-open/terminating) [1:1:0]
Last session created 00:02:10
Last statistic reset never
Last session creation rate 0
Maxever session creation rate 1
Last half-open session total 0
Class-map: TELNET (match-all)
Match: protocol telnet
Inspect
Packet inspection statistics [process switch:fast switch]
tcp packets: [0:24]
Session creations since subsystem startup or last reset 1
Current session counts (estab/half-open/terminating) [1:0:0]
Maxever session counts (estab/half-open/terminating) [1:1:0]
Last session created 00:00:08
Last statistic reset never
Last session creation rate 1
Maxever session creation rate 1
Last half-open session total 0
Class-map: class-default (match-any)
Match: any
Drop (default action)
2 packets, 48 bytes
R2#show policy-map type inspect zone-pair ZONE-PAIR-INSIDE>OUTSIDE sessions
Zone-pair: ZONE-PAIR-INSIDE>OUTSIDE
Service-policy inspect : POLICY-INSIDE>OUTSIDE
Class-map: ICMP (match-all)
Match: protocol icmp
Inspect
Class-map: TELNET (match-all)
Match: protocol telnet
Inspect
Established Sessions
Session 666D2AEC (10.0.12.1:31763)=>(10.0.23.3:23) telnet SIS_OPEN
Created 00:02:03, Last heard 00:01:59
Bytes sent (initiator:responder) [31:71]
Class-map: class-default (match-any)
Match: any
Drop (default action)
2 packets, 48 bytes
At this stage all ICMP traffic from the inside is going thru.
R1#ping 10.0.23.3 source loopback 0
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.0.23.3, timeout is 2 seconds:
Packet sent with a source address of 1.1.1.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 124/152/196 ms
Now let’s be more specific. We let just ICMP from 10.0.12.0/24
R2(config)#ip access-list standard INSIDE-SUBNET
R2(config-std-nacl)# permit 10.0.12.0
R2(config-std-nacl)#class-map type inspect match-all ICMP
R2(config-cmap)#match access-group name INSIDE-SUBNET
What about now?
R1#ping 10.0.23.3 source loopback 0
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.0.23.3, timeout is 2 seconds:
Packet sent with a source address of 1.1.1.1
.....
Success rate is 0 percent (0/5)
OK is working. Now all traffic from outside to inside is blocked. Let’s add some rules like to allow telnet to 10.0.12.1 from 10.0.23.3 with inspection. We have to create new class, policy and zone-pair.
First test.
R3#telnet 10.0.12.1
Trying 10.0.12.1 ...
% Connection timed out; remote host not responding
Now configuration.
R2(config)#ip access-list extended OUTSIDE-TELNET
R2(config-ext-nacl)#permit ip host 10.0.23.3 host 10.0.12.1
R2(config-ext-nacl)#exit
R2(config)#class-map type inspect OUTSIDE-TELNET
R2(config-cmap)#match access-group name OUTSIDE-TELNET
R2(config-cmap)#exit
R2(config)#policy-map type inspect POLICY-OUTSIDE>INSIDE
R2(config-pmap)#class type inspect OUTSIDE-TELNET
R2(config-pmap-c)#zone-pair security ZONE-PAIR-OUTSIDE>INSIDE source OUTSIDE destination INSIDE
R2(config-sec-zone-pair)#service-policy type inspect POLICY-OUTSIDE>INSIDE
What about now, second try.
R3#telnet 10.0.12.1
Trying 10.0.12.1 ... Open
User Access Verification
Password:
R1#
Cool, working.
R2#show policy-map type inspect zone-pair ZONE-PAIR-OUTSIDE>INSIDE sessions
Zone-pair: ZONE-PAIR-OUTSIDE>INSIDE
Service-policy inspect : POLICY-OUTSIDE>INSIDE
Class-map: OUTSIDE-TELNET (match-all)
Match: protocol telnet
Match: access-group name OUTSIDE-TELNET
Inspect
Established Sessions
Session 666D2AEC (10.0.23.3:38211)=>(10.0.12.1:23) telnet SIS_OPEN
Created 00:00:04, Last heard 00:00:02
Bytes sent (initiator:responder) [31:71]
Class-map: class-default (match-any)
Match: any
Drop (default action)
0 packets, 0 bytes
It was just basic ZFW configuration, there is some more advanced features besides similar to CBAC like sessions limit, max-incomplete, tcp syn or idle time, alert and audit trail we have other like limiting aggregated packet rate for the flows between security zones that I will try to show you in next post. Enjoy!