SSL VPN and Zone-Based firewall

Zone-Based firewall (ZBF) is Cisco implementation of stateful firewall on IOS. The name Zone-Based firewall comes from zones, which are the main concept in the configuration. This means that you need to create zones and firewall policy is then configured between these zones. Router interfaces are applied to these zones. Class-maps and policy-maps are used to create firewall policy. Class-maps are used to identify traffic, while policy-maps creates actually firewall policy. Traffic is denied by default between zones, so if you want to pass traffic you need to create policy. Bellow you can see an example of basic ZBF configuration, which permits all tcp and udp traffic from inside zone to outside zone.

zone security inside
zone security outside
class-map type inspect match-any FW_TCP-UDP
 match protocol tcp
 match protocol udp
policy-map type inspect FW_IN-OUT
 class type inspect FW_TCP-UDP
zone-pair security IN-OUT source inside destination outside
 service-policy type inspect FW_IN-OUT
interface FastEthernet0/0
 description Inside
 ip address
 zone-member security inside
interface FastEthernet0/1
 description Outside
 ip address
 zone-member security outside

Cisco SSL VPN solution is used for remote SSL connection to the secured environment. This solution is specially suitable for small business environments. You can find basic configuration bellow.
aaa new-model
aaa authentication login SSLVPN local
ip local pool VPN_POOL
crypto pki trustpoint VPN_TRUSTPOINT
 enrollment selfsigned
 usage ssl-server
 revocation-check crl
webvpn gateway SSLVPN_GATEWAY
 ip address port 4443
 ssl trustpoint VPN_TRUSTPOINT
webvpn context SSLVPN
 policy group default
 policy group SSLVPN_POLICY
   functions svc-enabled
   svc address-pool "VPN_POOL" netmask
   svc split include
 default-group-policy SSLVPN_POLICY
 aaa authentication list SSLVPN
 ssl authenticate verify all

If you want your remote users to communicate with inside zone you have to put those users in ZBF configuration, because traffic between zone member and non-member is denied by default. You can put remote users in the inside zone, or even better in separate zone and then control which traffic could flow between those zones. In the example configuration bellow you can see how to only permit http to inside zone.

interface Loopback0
 ip address
interface Virtual-Template1
 ip unnumbered Loopback0
 zone-member security vpn_users
webvpn context SSLVPN
 virtual-template 1
class-map type inspect match-any FW_HTTP
 match protocol http
policy-map type inspect FW_VPN-IN
 class type inspect FW_HTTP
zone-pair security VPN-OUT source vpn_users destination inside
 service-policy type inspect FW_VPN-IN

Now you have the ability to control your Remote VPN users with Zone-Based firewall.


Quagga routing process

I had some spare time to play around with Quagga  routing service. It is an implementation of routing protocols in Linux. It currently supports standardized routing protocols, like RIP, OSPF, BGP, ISIS etc.

Quagga is actually a set of daemons running independently on the operating system. Every routing protocol is implemented as daemon. Quagga also includes zebra daemon which is actually kernel routing manager. Zebra daemon puts route to routing table, manage IP addresses on interfaces etc. So if you want your routing protocol daemons to change Linux routing table you have to run zebra daemon as well.

Quagga is managed through CLI. It looks like IOS CLI. So network engineers that are familiar with Cisco command line should not have any problems operating routing daemons.

OK, how to install quagga? One way to do it is to install it from package, but you do not have all the flexibility of installing it from source. So I will show hot to install it from source.

I installed quagga on Ubuntu 12.04 running in VM.

First you need to prepare your system for quagga installation. It is recommended to run quagga daemons as non-root users, so you should create special user only for quagga.

root@ubuntu:~# useradd quagga

If you do not want to install quagga in default folders you can create empty directory, which must be owned by this user. I have created three folders: installation folder, configuration folder and folder for zebra states.

root@ubuntu:~# mkdir /etc/quagga
root@ubuntu:~# mkdir /usr/local/quagga
root@ubuntu:~# mkdir /usr/local/quagga/pid
root@ubuntu:~# chown quagga:quagga /etc/quagga
root@ubuntu:~# chown quagga:quagga /usr/local/quagga
root@ubuntu:~# chown quagga:quagga /usr/local/quagga/pid/

Now you can download latest stable source from the internet.

root@ubuntu:~# wget
root@ubuntu:~# tar xvfz quagga-0.99.22.tar.gz
root@ubuntu:~# cd quagga-0.99.22/

You are ready to configure your system, compile quagga and install quagga. When you are configuring your system you can disable some daemons if you do not need it with --disable-<DAEMON>. I have also made custom installation and configuration dir when configuring system.

root@ubuntu:~/quagga-0.99.22# ./configure --prefix=/usr/local/quagga \
> --sysconfdir=/etc/quagga \
> --localstatedir=/usr/local/quagga/pid/

The configure script generates a lot of output, with the summary at the end.

Quagga configuration
quagga version          : 0.99.22
host operating system   : linux-gnu
source code location    : .
compiler                : gcc
compiler flags          : -Os -fno-omit-frame-pointer -g -std=gnu99 -Wall -Wsign-compare -Wpointer-arith -Wbad-function-cast -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wchar-subscripts -Wcast-qual
make                    : make
includes                :
linker flags            :  -lcrypt   -lrt   -lm
state file directory    : /usr/local/quagga/pid
config file directory   : /etc/quagga
example directory       : /etc/quagga
user to run as          : quagga
group to run as         : quagga
group for vty sockets   :
config file mask        : 0600
log file mask           : 0600

The above user and group must have read/write access to the state file
directory and to the config files in the config file directory.

Now you can compile and install quagga with make and make install. You can add daemon folder in the system path  to run daemons from anywhere. 

root@ubuntu:~/quagga-0.99.22# export PATH=$PATH:/usr/local/quagga/sbin/
root@ubuntu:~/quagga-0.99.22# echo $PATH

After installation is completed you are ready to start with some basic configuration. If you have followed my path some example configurations are already stored in folder /etc/quagga. Copy configuration example in the <DAEMON.conf> format, since daemon looks in the configuration folder for configuration file. Make sure that files are owned by quagga user.

root@ubuntu:~/quagga-0.99.22# zebra
vty_read_config: failed to open configuration file /etc/quagga/zebra.conf: No such file or directory
can't open configuration file [/etc/quagga/zebra.conf]
root@ubuntu:~/quagga-0.99.22# cp /etc/quagga/zebra.conf.sample /etc/quagga/zebra.conf
root@ubuntu:~/quagga-0.99.22# cp /etc/quagga/ospfd.conf.sample /etc/quagga/ospfd.conf
root@ubuntu:~/quagga-0.99.22# chown quagga:quagga /etc/quagga/*
root@ubuntu:~/quagga-0.99.22# ls -lh /etc/quagga/
total 40K
-rw-r--r-- 1 quagga quagga  655 Nov  8 04:42 babeld.conf.sample
-rw-r--r-- 1 quagga quagga  566 Nov  8 04:42 bgpd.conf.sample
-rw-r--r-- 1 quagga quagga 2.8K Nov  8 04:42 bgpd.conf.sample2
-rw-r--r-- 1 quagga quagga 1.1K Nov  8 04:42 ospf6d.conf.sample
-rw-r--r-- 1 quagga quagga  182 Nov  8 04:44 ospfd.conf
-rw-r--r-- 1 quagga quagga  182 Nov  8 04:42 ospfd.conf.sample
-rw-r--r-- 1 quagga quagga  406 Nov  8 04:42 ripd.conf.sample
-rw-r--r-- 1 quagga quagga  390 Nov  8 04:42 ripngd.conf.sample
-rw-r--r-- 1 quagga quagga  369 Nov  8 04:44 zebra.conf
-rw-r--r-- 1 quagga quagga  369 Nov  8 04:42 zebra.conf.sample

Now you can run daemons. To run routing process as daemon you can use -d flag.

root@ubuntu:~/quagga-0.99.22# zebra -d
root@ubuntu:~/quagga-0.99.22# ospfd -d
root@ubuntu:~/quagga-0.99.22# ps -ef | grep quagga
quagga    5210     1  0 04:46 ?        00:00:00 zebra -d
quagga    5212     1  0 04:46 ?        00:00:00 ospfd -d

These daemons are listening on ports as specified in /etc/services.

root@ubuntu:~/quagga-0.99.22# cat /etc/services | grep zebra
zebrasrv        2600/tcp                        # zebra service
zebra           2610/tcp                        # zebra vty
ripd            2602/tcp                        # ripd vty (zebra)
ripngd          2603/tcp                        # ripngd vty (zebra)
ospfd           2604/tcp                        # ospfd vty (zebra)
bgpd            2605/tcp                        # bgpd vty (zebra)
ospf6d          2606/tcp                        # ospf6d vty (zebra)
isisd           2608/tcp                        # ISISd vty (zebra)

root@ubuntu:~/quagga-0.99.22# netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0    *               LISTEN      660/sshd
tcp        0      0  *               LISTEN      5272/zebra
tcp        0      0  *               LISTEN      5274/ospfd
tcp6       0      0 :::22                   :::*                    LISTEN      660/sshd
tcp6       0      0 :::2601                 :::*                    LISTEN      5272/zebra
tcp6       0      0 :::2604                 :::*                    LISTEN      5274/ospfd

To access configuration mode simply telnet to this specific port.

root@ubuntu:~/quagga-0.99.22# telnet localhost 2601
Connected to localhost.
Escape character is '^]'.

Hello, this is Quagga (version 0.99.22).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

User Access Verification

Router> en
Router# show run

Current configuration:
hostname Router
password zebra
enable password zebra
interface eth0
 ipv6 nd suppress-ra
interface eth1
 ipv6 nd suppress-ra
interface lo
line vty

Now you can configure networking on Linux machine through zebra daemon. You can see how to configure IP address on the interface in the output bellow.

root@ubuntu:~# ip addr show eth1
3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 00:0c:29:ed:60:d6 brd ff:ff:ff:ff:ff:ff

Router# conf t
Router(config)# inter eth1
Router(config-if)# ip add
Router(config-if)# ip address
Router(config-if)# no shu

root@ubuntu:~# ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
    link/ether 00:0c:29:ed:60:d6 brd ff:ff:ff:ff:ff:ff
    inet brd scope global eth1
    inet6 fe80::20c:29ff:feed:60d6/64 scope link
       valid_lft forever preferred_lft forever
root@ubuntu:~# ping
PING ( 56(84) bytes of data.
64 bytes from icmp_req=1 ttl=64 time=1.92 ms
--- ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.921/1.921/1.921/0.000 ms

Now I will try to configure OSPF with another linux box.

root@ubuntu:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface         UG    100    0        0 eth0   U     0      0        0 eth1

root@ubuntu:~/quagga-0.99.22# telnet localhost 2604
Connected to localhost.
Escape character is '^]'.

Hello, this is Quagga (version 0.99.22).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

User Access Verification

ospfd> en
ospfd# conf t
ospfd(config)# router os
ospfd(config)# router ospf
ospfd(config-router)# network area
ospfd(config-router)# exit
ospfd(config)# exit
ospfd# sh ip ospf neighbor

    Neighbor ID Pri State           Dead Time Address         Interface            RXmtL RqstL DBsmL     1 Full/DR           38.390s    eth1:       0     0     0
ospfd# sh ip ospf database

       OSPF Router with ID (

                Router Link States (Area

Link ID         ADV Router      Age  Seq#       CkSum  Link count    129 0x80000003 0xcd28 1    108 0x80000006 0xff4f 2

                Net Link States (Area

Link ID         ADV Router      Age  Seq#       CkSum    130 0x80000001 0xa21a

root@ubuntu:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface         UG    100    0        0 eth0   UG    20     0        0 eth1   U     0      0        0 eth1

As displayed above, you can see that I have successfully established ospf adjacency with another Linux box. You can make similar configurations with other routing daemons.

You can also save configuration from daemon. Daemon automatically make configuration backup of the old configuration.

ospfd# wr
Configuration saved to /etc/quagga/ospfd.conf

root@ubuntu:~/quagga-0.99.22# ls -lh /etc/quagga/
total 44K
-rw------- 1 quagga quagga  223 Nov  8 05:04 ospfd.conf
-rw-r--r-- 1 quagga quagga  182 Nov  8 04:42 ospfd.conf.sample
-rw-r--r-- 1 quagga quagga  182 Nov  8 04:44 ospfd.conf.sav

Where we can use quagga? It can always be used for some testing, for servers that need routing process. You can use zebra daemon to control Linux networking etc. You can use bgp daemon for route reflector purposes, since route reflector usually do not need data plane.


Cisco ISE - part 3 - Prepare your switch for dot1x and Cisco ISE

Network switch and Cisco ISE communicate with each other through RADIUS protocol. So first step is to configure radius support on switch.

aaa new-model
aaa authentication dot1x default group radius
aaa authorization network default group radius
aaa accounting dot1x default start-stop group radius
radius-server attribute 6 on-for-login-auth
radius-server attribute 8 include-in-access-req 
radius-server attribute 25 access-request include
radius-server host ISE_IP_ADDRESS key RADIUS_KEY 
radius-server vsa send accounting
radius-server vsa send authentication

With Cisco ISE you can enable RADIUS Change of Authorization (CoA) feature. This actually means that Cisco ISE can trigger change in port authorization status, without request from switch. With this configuration Cisco ISE could for example force authorized port to unauthorized status. Configuration on the switch is as bellow.

aaa server radius dynamic-author
 client ISE_IP_ADDRESS server-key RADIUS_KEY

You can enable device tracking and DHCP snooping. To support downloadable ACL device tracking configuration is required. DHCP snooping command is optional and it is used for profiling services.

ip dhcp snooping
ip device tracking

To enable dot1x globally you must use the following command.

dot1x system-auth-control

Commands above are all global commands. To enable authentication on the port you should use commands bellow.

!enable dot1x
dot1x pae authenticator
!enable MAB (MAC Authentication Bypass)
!various authentication commands
authentication host-mode multi-auth
authentication periodic
authentication timer reauthenticate server
authentication order dot1x mab
authentication priority dot1x mab
authentication port-control auto
authentication violation restrict

These are some configuration options that you should use on switch to work with Cisco ISE features. I recommend that you create configuration template for global commands and interface commands. Then these templates should be used on all LAN switches in the environment. If you will do it in the right way you will have huge reduce in the workload on LAN segment, since all policy will be done on the Cisco ISE.