Pages

2013/11/15

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 http://download.savannah.gnu.org/releases/quagga/quagga-0.99.22.tar.gz
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
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/quagga/sbin/

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 0.0.0.0:22              0.0.0.0:*               LISTEN      660/sshd
tcp        0      0 0.0.0.0:2601            0.0.0.0:*               LISTEN      5272/zebra
tcp        0      0 0.0.0.0:2604            0.0.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
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

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


User Access Verification

Password:
Router> en
Password:
Router#
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
!
end

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 192.168.2.100/24
Router(config-if)# no shu
Router(config-if)#

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 192.168.2.100/24 brd 192.168.2.255 scope global eth1
    inet6 fe80::20c:29ff:feed:60d6/64 scope link
       valid_lft forever preferred_lft forever
root@ubuntu:~# ping 192.168.2.77
PING 192.168.2.77 (192.168.2.77) 56(84) bytes of data.
64 bytes from 192.168.2.77: icmp_req=1 ttl=64 time=1.92 ms
^C
--- 192.168.2.77 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
0.0.0.0         192.168.10.1    0.0.0.0         UG    100    0        0 eth0
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1

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

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

User Access Verification

Password:
ospfd>
ospfd>
ospfd> en
ospfd# conf t
ospfd(config)# router os
ospfd(config)# router ospf
ospfd(config-router)# network 192.168.2.0/24 area 0.0.0.0
ospfd(config-router)# exit
ospfd(config)# exit
ospfd# sh ip ospf neighbor

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

       OSPF Router with ID (192.168.73.50)

                Router Link States (Area 0.0.0.0)

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

                Net Link States (Area 0.0.0.0)

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

root@ubuntu:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.1    0.0.0.0         UG    100    0        0 eth0
192.168.1.0     192.168.2.77    255.255.255.0   UG    20     0        0 eth1
192.168.2.0     0.0.0.0         255.255.255.0   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.

2013/11/13

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)
!
mab
!
!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.







2013/11/08

Cisco ISE - part 2 - Integrating ISE with Microsoft AD

As I already mentioned Cisco ISE is product that is mainly used to control user's network access. Many organizations controls theirs users/computers through Microsoft Active Directory. That is why it can be very handy to integrate Cisco ISE with Microsoft AD. With the integration you will be able to still control users/computers on AD, but you can create network access policy on your Cisco ISE server, based on AD groups/users. 

Integration is actually pretty straightforward. There are some prerequisites, which can be found in Cisco docs

Before you start integration of Cisco ISE and MS AD you have to make sure, that time on both servers are synchronized. Of course the best way to do it is to use NTP. To join Cisco ISE to the domain, you have to create user on the AD. The best way is to create separate user with only needed privileges, which again could be found on Cisco docs.

When user with right privileges is created you can join AD to the domain. To do this you go to Administration -> Identity Management -> External Identity Sources -> Active Directory. 

First you need to go to Connection tab. You should enter your organization domain name and identity store name, which can be any chosen name. Now you click save configuration. Now you are ready to join Cisco ISE to the domain. You can click test connection, to test connection to your AD. This is of course optional steps, but could be very helpful for troubleshooting. To join Cisco ISE to the domain, simply click Join button, enter username/password and if everything is ok your Cisco ISE will join the domain. Now you can retrieve groups from AD. To do this simply click button groups and your can get the list of all groups in AD. Since output is limited to 100 groups you can filter this list to get groups you want.




That is it. As you can see it is pretty straightforward process.