A re-introduction to Cisco Zone Based Firewalls
After a few years without having to think about it, I decided to dip my toe back into the murky waters of Zone Based Firewalls recently. Luckily, I'd written enough notes and comments in my previous configs that only a small amount of searching and reading was needed before I got back up to speed.
In that vein, here's a very basic starter ZBF config (for when I forget again in six months *derp*)...
Create an ACL to hold any firewall exceptions:
ip access-list extended aclFirewallExceptions
permit tcp any any eq 56881
permit tcp any any eq 10022
Then, add the ACL to a Class Map:
class-map type inspect match-any cmFirewallExceptions
match access-group name aclFirewallExceptions
After that, the Class Map is added to a Policy Map:
policy-map type inspect pmWanToLan
class type inspect cmFirewallExceptions
inspect
class class-default
drop
The policy map is then applied to the relevant Zone Pair:
zone-pair security zpWanToLan source WAN destination LAN
service-policy type inspect pmWanToLan
A note on naming conventions used here: There are quite a few common conventions that people will use, such as appending pmap/cmap or class/policy/zone but I find it easier to read using a prefix (cm/pm/zp) then a short but descriptive name - e.g., Policy Map WAN to LAN becomes: pmWanToLan, with it's associated Class Map being named cmWanToLan.
Current sessions that match policies can be observed by running:
#show policy-map type inspect zone-pair sessions
For example, the following shows an ssh connection on 10022 inbound from the WAN interface and outbound from the LAN interface:
#ip nat inside source static tcp 192.168.0.10 10022 interface GigabitEthernet0/0 10022
policy exists on zp zpWanToLan
Zone-pair: zpWanToLan
Service-policy inspect : pmWanToLan
Class-map: cmFirewallExceptions (match-any)
Match: access-group name aclFirewallExceptions
2 packets, 88 bytes
30 second rate 0 bps
Inspect
Number of Established Sessions = 1
Established Sessions
Session 49DBF680 (10.33.2.19:64371)=>(192.168.0.10:10022) tcp SIS_OPEN/TCP_ESTAB
Created 00:10:48, Last heard 00:00:23
Bytes sent (initiator:responder) [2869:3511]
Class-map: class-default (match-any)
Match: any
Drop
0 packets, 0 bytes
Another example: this time an ssh connection on 56881 (out) to 10022 (in)
This was created with the following command:
#ip nat inside source static tcp 192.168.0.2 10022 interface GigabitEthernet0/0 56881
policy exists on zp zpWanToLan
Zone-pair: zpWanToLan
Service-policy inspect : pmWanToLan
Class-map: cmFirewallExceptions (match-any)
Match: access-group name aclFirewallExceptions
4 packets, 176 bytes
30 second rate 0 bps
Inspect
Number of Established Sessions = 1
Established Sessions
Session 49DC1980 (10.33.2.19:49753)=>(192.168.0.2:10022) tcp SIS_OPEN/TCP_ESTAB
Created 00:02:10, Last heard 00:02:05
Bytes sent (initiator:responder) [2725:3127]
router10#sh ip nat tr
Pro Inside global Inside local Outside local Outside global
tcp 10.33.6.150:56881 192.168.0.2:10022 10.33.2.19:49753 10.33.2.19:49753
Showing ssh connection on 22 from inside to outside:
policy exists on zp zpLanToWan
Zone-pair: zpLanToWan
Service-policy inspect : pmLanToWan
Class-map: cmAllProtocols (match-any)
Match: protocol tcp
1 packets, 40 bytes
30 second rate 0 bps
Match: protocol udp
6 packets, 281 bytes
30 second rate 0 bps
Match: protocol icmp
1 packets, 64 bytes
30 second rate 0 bps
Inspect
Number of Established Sessions = 1
Established Sessions
Session 49DC0480 (192.168.0.10:48737)=>(10.33.2.19:22) tcp SIS_OPEN/TCP_ESTAB
Created 00:00:10, Last heard 00:00:04
Bytes sent (initiator:responder) [2679:8661]
Class-map: class-default (match-any)
Match: any
Drop
0 packets, 0 bytes
Showing a large number of dropped packets following an nmap scan:
policy exists on zp zpWanToSelf
Zone-pair: zpWanToSelf
Service-policy inspect : pmWanToSelf
Class-map: class-default (match-any)
Match: any
Drop
2635 packets, 149150 bytes
Now we can check out the status of ports around the port we opened - all other ports should be in a filtered state:
$ nmap -Pn 10.33.6.150 -p 56880-56885
Starting Nmap 6.47 ( http://nmap.org ) at 2015-06-02 15:01 AEST
Nmap scan report for 10.33.6.150
Host is up (0.12s latency).
PORT STATE SERVICE
56880/tcp filtered unknown
56881/tcp open unknown
56882/tcp filtered unknown
56883/tcp filtered unknown
56884/tcp filtered unknown
56885/tcp filtered unknown
Nmap done: 1 IP address (1 host up) scanned in 2.42 seconds
Special config for dhcp running on the router itself
NB: 'inspect' rules that match DHCP traffic first will prevent DHCP getting through - even if a later rule allows it.
A 'pass' rule for DHCP traffic (UDP 67, 68) needs to be above any catch-all UDP rules in the policy-map:
ip access-list extended aclDhcp
permit udp any any eq 67
permit udp any any eq 68
!
policy-map type inspect pmLanToSelf
class type inspect cmDhcp
pass
!
One thing to keep in mind is that ZBF is fairly CPU intensive - as traffic increases so does CPU usage, as these graphs from Cacti show:
In that vein, here's a very basic starter ZBF config (for when I forget again in six months *derp*)...
Create an ACL to hold any firewall exceptions:
ip access-list extended aclFirewallExceptions
permit tcp any any eq 56881
permit tcp any any eq 10022
Then, add the ACL to a Class Map:
class-map type inspect match-any cmFirewallExceptions
match access-group name aclFirewallExceptions
After that, the Class Map is added to a Policy Map:
policy-map type inspect pmWanToLan
class type inspect cmFirewallExceptions
inspect
class class-default
drop
The policy map is then applied to the relevant Zone Pair:
zone-pair security zpWanToLan source WAN destination LAN
service-policy type inspect pmWanToLan
A note on naming conventions used here: There are quite a few common conventions that people will use, such as appending pmap/cmap or class/policy/zone but I find it easier to read using a prefix (cm/pm/zp) then a short but descriptive name - e.g., Policy Map WAN to LAN becomes: pmWanToLan, with it's associated Class Map being named cmWanToLan.
Current sessions that match policies can be observed by running:
#show policy-map type inspect zone-pair sessions
For example, the following shows an ssh connection on 10022 inbound from the WAN interface and outbound from the LAN interface:
#ip nat inside source static tcp 192.168.0.10 10022 interface GigabitEthernet0/0 10022
policy exists on zp zpWanToLan
Zone-pair: zpWanToLan
Service-policy inspect : pmWanToLan
Class-map: cmFirewallExceptions (match-any)
Match: access-group name aclFirewallExceptions
2 packets, 88 bytes
30 second rate 0 bps
Inspect
Number of Established Sessions = 1
Established Sessions
Session 49DBF680 (10.33.2.19:64371)=>(192.168.0.10:10022) tcp SIS_OPEN/TCP_ESTAB
Created 00:10:48, Last heard 00:00:23
Bytes sent (initiator:responder) [2869:3511]
Class-map: class-default (match-any)
Match: any
Drop
0 packets, 0 bytes
Another example: this time an ssh connection on 56881 (out) to 10022 (in)
This was created with the following command:
#ip nat inside source static tcp 192.168.0.2 10022 interface GigabitEthernet0/0 56881
policy exists on zp zpWanToLan
Zone-pair: zpWanToLan
Service-policy inspect : pmWanToLan
Class-map: cmFirewallExceptions (match-any)
Match: access-group name aclFirewallExceptions
4 packets, 176 bytes
30 second rate 0 bps
Inspect
Number of Established Sessions = 1
Established Sessions
Session 49DC1980 (10.33.2.19:49753)=>(192.168.0.2:10022) tcp SIS_OPEN/TCP_ESTAB
Created 00:02:10, Last heard 00:02:05
Bytes sent (initiator:responder) [2725:3127]
router10#sh ip nat tr
Pro Inside global Inside local Outside local Outside global
tcp 10.33.6.150:56881 192.168.0.2:10022 10.33.2.19:49753 10.33.2.19:49753
Showing ssh connection on 22 from inside to outside:
policy exists on zp zpLanToWan
Zone-pair: zpLanToWan
Service-policy inspect : pmLanToWan
Class-map: cmAllProtocols (match-any)
Match: protocol tcp
1 packets, 40 bytes
30 second rate 0 bps
Match: protocol udp
6 packets, 281 bytes
30 second rate 0 bps
Match: protocol icmp
1 packets, 64 bytes
30 second rate 0 bps
Inspect
Number of Established Sessions = 1
Established Sessions
Session 49DC0480 (192.168.0.10:48737)=>(10.33.2.19:22) tcp SIS_OPEN/TCP_ESTAB
Created 00:00:10, Last heard 00:00:04
Bytes sent (initiator:responder) [2679:8661]
Class-map: class-default (match-any)
Match: any
Drop
0 packets, 0 bytes
Showing a large number of dropped packets following an nmap scan:
policy exists on zp zpWanToSelf
Zone-pair: zpWanToSelf
Service-policy inspect : pmWanToSelf
Class-map: class-default (match-any)
Match: any
Drop
2635 packets, 149150 bytes
Now we can check out the status of ports around the port we opened - all other ports should be in a filtered state:
$ nmap -Pn 10.33.6.150 -p 56880-56885
Starting Nmap 6.47 ( http://nmap.org ) at 2015-06-02 15:01 AEST
Nmap scan report for 10.33.6.150
Host is up (0.12s latency).
PORT STATE SERVICE
56880/tcp filtered unknown
56881/tcp open unknown
56882/tcp filtered unknown
56883/tcp filtered unknown
56884/tcp filtered unknown
56885/tcp filtered unknown
Nmap done: 1 IP address (1 host up) scanned in 2.42 seconds
Special config for dhcp running on the router itself
NB: 'inspect' rules that match DHCP traffic first will prevent DHCP getting through - even if a later rule allows it.
A 'pass' rule for DHCP traffic (UDP 67, 68) needs to be above any catch-all UDP rules in the policy-map:
ip access-list extended aclDhcp
permit udp any any eq 67
permit udp any any eq 68
!
policy-map type inspect pmLanToSelf
class type inspect cmDhcp
pass
!
One thing to keep in mind is that ZBF is fairly CPU intensive - as traffic increases so does CPU usage, as these graphs from Cacti show:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | ! class-map type inspect match-any cmFirewallExceptions match access-group name aclFirewallExceptions ! class-map type inspect match-any cmDhcp match access-group name aclDhcp ! class-map type inspect match-any cmAllProtocols match protocol tcp match protocol udp match protocol icmp class-map type inspect match-any cmSsh match protocol ssh ! ! policy-map type inspect pmWanToLan class type inspect cmFirewallExceptions inspect class class-default drop ! policy-map type inspect pmLanToWan class type inspect cmAllProtocols inspect class class-default drop ! policy-map type inspect pmSelfToLan class type inspect cmDhcp pass class type inspect cmAllProtocols inspect class class-default drop ! policy-map type inspect pmLanToSelf class type inspect cmDhcp pass class type inspect cmAllProtocols inspect class type inspect cmSsh inspect class class-default drop ! policy-map type inspect pmWanToSelf class class-default drop ! policy-map type inspect pmSelfToWan class type inspect cmAllProtocols inspect class class-default drop ! policy-map type inspect pmDmzToLan class class-default drop ! policy-map type inspect pmLanToDmz class type inspect cmAllProtocols inspect class class-default drop ! policy-map type inspect pmDmzToSelf class class-default drop ! policy-map type inspect pmSelfToDmz class type inspect cmAllProtocols inspect class class-default drop ! zone security LAN zone security WAN zone security DMZ zone-pair security zpSelfToLan source self destination LAN service-policy type inspect pmSelfToLan ! zone-pair security zpLanToSelf source LAN destination self service-policy type inspect pmLanToSelf ! zone-pair security zpWanToLan source WAN destination LAN service-policy type inspect pmWanToLan ! zone-pair security zpLanToWan source LAN destination WAN service-policy type inspect pmLanToWan ! zone-pair security zpWanToSelf source WAN destination self service-policy type inspect pmWanToSelf ! zone-pair security zpSelfToWan source self destination WAN service-policy type inspect pmSelfToWan ! zone-pair security zpLanToDmz source LAN destination DMZ service-policy type inspect pmLanToDmz ! zone-pair security zpDmzToLan source DMZ destination LAN service-policy type inspect pmDmzToLan ! zone-pair security zpSelfToDmz source self destination DMZ service-policy type inspect pmSelfToDmz ! zone-pair security zpDmzToSelf source DMZ destination self service-policy type inspect pmDmzToSelf ! ! ! ip nat inside source list 1 interface g0/0 overload ip nat inside source static tcp 192.168.0.2 56789 interface g0/0 56789 ip nat inside source static udp 192.168.0.2 56789 interface g0/0 56789 ! ip nat inside source static tcp 192.168.0.10 10022 interface g0/0 10022 ! ! ip route 0.0.0.0 0.0.0.0 g0/0 ! ip access-list extended aclFirewallExceptions permit tcp any any eq 56789 permit udp any any eq 56789 permit udp any any eq ntp ! ip access-list extended aclDhcp permit udp any any eq 67 permit udp any any eq 68 ! access-list 1 permit 192.168.0.0 0.0.0.255 ! |
Comments
Post a Comment