Basic configuration of zebra/quagga

Zebra/Quagga are the routing processes for Linux/Unix systems). Zebrad is the main daemon of the suite. It talks to the kernel and the other routing processes. Routing protocols are typically implemented as other processes (like ospfd and bgpd) that communicate information to zebrad, which modifies the kernel routing table.

You should remember that the linux kernel does all the routing. The zebra/quagga suite of software just implements a user interface and some dynamic routing protocols. You can use standard linux commands to view/change the routing tables.

The first step will be to access R1 console via the out of band VNC protocol. You use your VNC client to connect to cnt4504-b.cs.fiu.edu on port 4XX01. Then your log in a user root with the password given in class.

The zebrad and ospfd are started by /mnt/hda1/rc.local automatically.

Quagga has a process known as vtysh which allows you to communicate with all the daemons at once, and makes saving the config scripts easier. It presents to the user a very IOS (cisco) like shell to operate the quagga based routers. Here is the full quagga manual

You use the vtysh command to control zebra.

	[root@r1 quagga]# vtysh

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

	show running-config 
will show you the current config.
	show startup-config 
will show you the startup config.

	copy running-config startup-config 
will save the current config for next reboot.

Showing interface operational parameters on quagga

	show interface 
	show ip route

Don't forget to save (by copy running-config startup-config) before exiting to keep your changes in the zebrad.conf files.

Now lets see how to configure some IP addresses on interfaces and how to configure static routing.

We will assume we are working on a hypothetical router r1, which has 2 interfaces. eth0 uses IP address 10.XX.1.1/25, eth1 uses IP address 10.XX.1.129/26 This example is assumes group 59. NOTE, hitting ctrl-z from any configuration mode will bring you back to the normal enable mode. Also NOTE, there may some virtual interfaces like sit0 and of course lo0 (the loopback). You can ignore those for now and concentrate on the eth interfaces.

	[root@r1 ~]# vtysh			- Must do router config commands from inside vtysh

        r1# conf terminal                        - enter configuration mode
        r1(config)# interface eth0               - configure interface mode
        r1(config-if)# ip address 10.59.1.1/25   - set the ip address
        r1(config-if)# description link to net2  - add a description
        r1(config-if)# link-detect               - allow zebra to detect changes in link state
        r1(config-if)# quit                      - back to regular config mode
        r1(config)# interface eth1
        r1(config-if)# ip address 10.59.1.129/26
        r1(config-if)# description link to net1
        r1(config-if)# link-detect   
        r1(config-if)# quit

To add a static route you will need to use the ip route command from configuration mode. The first parameter is the cidr representation of the network, the second is the next hop to reach the network.

	r1# conf t
	r1(config)# ip route 10.59.0.0/24 10.59.1.193
	r1(config)#
	r1# show ip route
The default route is specified via 0.0.0.0/0
	r1# conf t
	r1(config)# ip route 0.0.0.0/0 10.59.1.193
	r1(config)#
	r1# show ip route
Don't forget to save (by copy running-config startup-config) before exiting to keep your changes in the zebrad.conf files.

Basic Cisco router configuration

Here is a link to the Cisco IOS documentation pages. Cisco IOS documentation First you have to talk to the cisco routers. Since they are unconfigured you will need to use the out of band serial console (available via telnet cnt4504-b.cs.fiu.edu 4XX02 for R2 and telnet cnt4504-b.cs.fiu.edu 4XX02 for R3)

Just like with the linux/quagga router you have two commands to show your the current running configuration and the startup configuration.

	show running-config 
will show you the current config.
	show startup-config 
will show you the startup config.

First we need to set the hostname, domain name, and create a username and set the enable secret. We use enable secret instead of enable password since it uses a much more secure hash. We also want to set up the ssh keys so we can use ssh to talk to the routers.

For the lab you do NOT need to do anything initially but set hostname. The username/enable secret and ssh keys are already set up for you.

	CHANGEME(config)#hostname r2
Passwords and crypto keys have been done for you. If you needed to set the enable password or the configure a username, and if you needed to genereate a crypot key, here is how you would do it. (NOTE, you *DO NOT* need to do these steps for our lab routers)
	r2(config)#ip domain-name gXX.scs
	r2(config)#username cisco password cisco
	r2(config)#enable secret cisco
	r2(config)#crypto key generate
	The name for the keys will be: r2.g59.scs
	Choose the size of the key modulus in the range of 360 to 2048 for your
	  General Purpose Keys. Choosing a key modulus greater than 512 may take
	  a few minutes.

	How many bits in the modulus [512]: 1024
	% Generating 1024 bit RSA keys ...[OK]
	r2(config)#
	r2(config)#exit
	r2#

The running configuration will be lost at reboot. We can save it to nvram startup config.

	r2#copy running-config startup-config
Now we set up basic interface addresses, and the static routing. NOTE, while quagga understands the /XX CIDR notation, the cisco IOS does not, and requires you to set via netmask dotted quad notation.

In this example group 59 has a r2 with the eth1/0 having an address of 10.59.0.2/24 and the eth1/1 having an address of 10.59.1.193/30.

	r2#
	r2#conf t						- enter configuration mode
	r2(config)#int eth1/0					- enter interface configuration mode
	r2(config-if)#ip address 10.59.0.2 255.255.255.0		- set ip address
	r2(config-if)#description link to net 0 10.59.0.2/24	- add a description
	r2(config-if)#no shutdown				- bring interface up
	r2(config-if)#exit					- leave interface configuration mode
	r2(config)#int eth1/1
	r2(config-if)#ip address 10.59.1.193 255.255.255.252
	r2(config-if)#description link to 10.59.1.193/30		- add a description
	r2(config-if)#no shutdown				- bring interface up
	r2(config-if)#exit
	r2(config)#
We can add static routes to the cisco, similar to the quagga. Again, instead of CIDR notation we have to specify the netmask as dotted quads. Here the default route is specified by 0.0.0.0 0.0.0.0
	r2(config)#ip route 10.59.1.0 255.255.255.128 10.59.1.194
	r2(config)#ip route 10.59.1.128 255.255.255.192 10.59.1.194
	r2(config)#ip route 0.0.0.0 0.0.0.0 10.59.0.1
Showing interface operational parameters on cisco IOS:
	show interface 
	show run interface 
	show ip route
	show ip interface brief
These all have to be run outside of configuration mode.

Basic JunOS router configuration

Here is a link to the Juniper JunOS documentation pages. Juniper JunOS documentation The system basics section is a good place to start.

To talk to the Juniper router (BR) you will need to connect to it via the console and begin configuration mode. To connect to the serial console on BR you use the telnet protocol. telnet cnt4504-b.cs.fiu.edu 4XX00

Junipers command syntax is quite different than cisco's IOS or quagga. On junipers you have two modes. The command line mode to view the status of the router and the "config" mode to change the configuration. The configuration is broken down into a number of different sections. When you login using the juniper uid you will see something like this:


	--- JUNOS 8.0R1.9 built 2006-08-11 16:25:40 UTC
	juniper@br> 

To configure the router you type configure or edit to enter the configuration mode. It places you at the top of a hierarchy of sections you use to configure various functions of the router. The top level sections are

	system			basic system information (like logins)
	interfaces		interface configurations
	routing-options		routing protocol independent routing options
	protocols		configure routing protocols
	policy-options		configure routing policy
	firewall		configure firewall settings

You can use the show command to print out to the screen the entire configuration below the level you are at. If you are at the top level, it will print the entire configuration. If you are at the system level it will show you just the configuration of the system level.

To edit any of these top level sections you would use the edit

command. The prompt will change to reflect the exact area of the hierarchy you are editing.

	juniper@br> edit
	Entering configuration mode

	[edit]
	juniper@br# edit system 

	[edit system]
	juniper@br# show 
	host-name br;
	time-zone America/New_York;
	login {
	    user juniper {
		uid 100;
		class super-user;
		authentication {
		    encrypted-password "$1$LXRWdPg8$RCx9D.WePVwEoJFyJLAo90"; ## SECRET-DATA
		}
	    }
	}
	services {
	    ssh {
		root-login deny;
		protocol-version v2;
	    }
	}
	[edit system]
	juniper@br#



You can use the up command to move up a level in the hierarchy. Then use edit to start editing another part. Here we start at the top of the system tree, go up to the top of the entire tree, then go down to edit the interface tree.

	[edit system]
	juniper@br# up 

	[edit]
	juniper@br# edit interfaces 

	[edit interfaces]
	juniper@br#  

The juniper routers have 2 interfaces. fxp0 and fxp1. They also have an internal loopback interface lo0. We will initially configure fxp1.
	juniper@br> configure
	Entering configuration mode

        [edit]
        juniper@br# edit interfaces 

        [edit interfaces]
        juniper@br# edit fxp1 

        [edit interfaces fxp1]
        juniper@br# edit unit 0 

        [edit interfaces fxp1 unit 0]
        juniper@br# set family inet address 10.59.0.1/24 

        [edit interfaces fxp1 unit 0]
        juniper@br# set description "Connection to 10.59.0.0/24 core network for group 59" 

        [edit interfaces fxp1 unit 0]
        juniper@br# show 
        description "Connection to 10.59.0.0/24 core network for group 59";
        family inet {
            address 10.59.0.1/24;
        }

        [edit interfaces fxp1 unit 0]
        juniper@br# up 

        [edit interfaces fxp1]
        juniper@br# show 
        unit 0 {
            description "Connection to 10.59.0.0/24 core network for group 59";
            family inet {
                address 10.59.0.1/24;
            }
        }

        [edit interfaces fxp1]
        juniper@br# up 

        [edit interfaces]
        juniper@br# 


Note we have only edited. Since we have not done a commit, no changes have been applied yet.

Now we are ready to commit the changes. Since we did make changes that could affect the connectivity of the router we will use the commit confirmed command first, then a final commit after we are certain the router is working as we wish.


	[edit interfaces]
	juniper@br# commit confirmed 5  
	commit confirmed will be automatically rolled back in 5 minutes unless confirmed
	commit complete

	[edit interfaces]
	juniper@br# 

If we still have connectivity to the router, we can do a commit and-quit now to make the changes permanent. If we have lost connectivity to the router we have to wait 5 minutes and the changes we made will be rolled back (IE undone).

	[edit interfaces]
	juniper@br# commit and-quit 
	commit complete
	Exiting configuration mode

	juniper@br>

To configure static routes for the juniper router you go to the routing-options static section. Here we will add a static route to 10.59.2.0/24 with a next hop of 10.59.0.3. Note that like linux/quagga the default route is 0.0.0.0/0.


	juniper@br> configure
	Entering configuration mode

	[edit]
	juniper@br# edit routing-options 

	[edit routing-options]
	juniper@br# edit static 

	[edit routing-options static]
	juniper@br# set route 10.59.2.0/24 next-hop 10.59.0.3 

	[edit routing-options static]
	juniper@br# up 

	[edit routing-options]
	juniper@br# show 
	static {
	    route 10.59.2.0/24 next-hop 10.59.0.3;
	}

	[edit routing-options]
	juniper@br# commit confirmed 3 
	commit confirmed will be automatically rolled back in 3 minutes unless confirmed
	commit complete

	[edit routing-options]
	juniper@br# commit and-quit 
	commit complete
	Exiting configuration mode

	juniper@br>

Showing operational interface parameters and routing information on junos

	At prompt outside of configuration mode:

	show interface 
	show route

	At prompt inside of configuration mode:

	run show interface 
	run show route


Routing tables

Every time you configure an interface with a IP address and netmask a route (a CONNECTED route) gets added to the routers routing table for that net. But to have full connectivity for our test networks we need to add static routes for the non-connected networks. For example, you can not ping from BR to any of the addresses on the interface on R1. BR only knows how to reach 10.XX.0.0/24 and 10.91.0.0/24.

First thing you will want to do is review how you want the traffic to flow. In each case you have to think about two paths: the path to the destination network and the path from the destination network. The routers will need routes added to direct the traffic. These routes can be added by a dynamic routing protocol (like ospf) or can be added manually by you the network manager. These are static routes.

Routers will typically use a algorithm like this to decide how to deliver a packet.

	1. Is the destination address on a connected interface? If so, deliver it.
	2. Is there a route for the destination in the routing table? Use the 
	   most specific route (longest netmask) available. Deliver the packet 
	   to the specified next hop. This can be important. If you wanted to 
	   deliver a packet to 10.50.1.195 and you had a routing table destination 
           entry of 10.50.1.0/24 and one for 10.50.1.192/26 then you would use
           the 10.50.1.192/26 as it is "more specific".
	3. Is there a default route? If so deliver it to the default routes next hop.
	4. If no route at all was found above, drop the packet and send back a ICMP 
           network unreachable message to the source.
Each router can have only one route to a destination active at any time. It helps to think of this as programing the router how to deliver packets to netX. Once a route is entered into a routers routing table all packets destined for that network that arrive at the router will take the net hop specified.

From the point of view of BR you want to use R3 to get to net3. BR knows how to get to net0 and the core net (10.91.0.0/24) but no where else. So on BR you would add a route to get there.

	juniper@br> edit 
	Entering configuration mode

	[edit]
	juniper@br# edit routing-options 

	[edit routing-options]
	juniper@br# set static route 10.XX.2.0/24 next-hop 10.XX.0.3

You don't need to add a route to R3 to get to BR's (10.XX.0.1/24) address It (network 10.XX.0.0/24) is connected from the point of view of R3. But to get to the "outside" world you might want to have a default route on R3. Have the default route point to the border router.
	r3#conf t
	Enter configuration commands, one per line.  End with CNTL/Z.
	r3(config)#ip route 0.0.0.0 0.0.0.0 10.XX.0.1 

Now, to build connectivity to net1 and net2 we have more options. We can use either R2 or R3 to get to R1. And the path back from R1 to net0 and BR and the outside world also has two paths, either R2 or R3. In fact, we don't have to use the same router in each direction (though we probably want to). Also, we can use aggregation of the address space to save routing table space. More on these factors below.

Lets assume we want traffic from BR destined to net1 to go to R1 via R2. We can simply add static routes to BR, and R2

	On BR

	[edit routing-options]
        juniper@br# set static route 10.XX.1.0/25 next-hop 10.XX.0.2

	
	On R2

	r2#conf t
        Enter configuration commands, one per line.  End with CNTL/Z.
        r2(config)#ip route 10.XX.1.0 255.255.255.128 10.XX.1.194 	
	
And we want traffic from R1 to go to net0 via R2 also. So on R1 we add a static route for net0 with a next hop of r2. Lets add a default route to R1 also, again through R2.

	r1#ip route 10.XX.0.0/24 10.XX.1.193
	r1#ip route 0.0.0.0/0 10.XX.1.193

Now all traffic from R1 to net0 will go through R2. If fact, all traffic that doesn't match any other route will follow the default route.

Now what about net2? We could specify that from BR traffic to net2 should go through R3. Of course we also need to add a route to R3 to net2.

	On BR
	[edit routing-options]
        juniper@br# set static route 10.XX.1.128/26 next-hop 10.XX.0.3

	On R3
        r3(config)#ip route 10.XX.1.128 255.255.255.192 10.XX.1.198 	

But what would happen to traffic that arrived from net2 to R1 destined for hosts on net0? R1 already has a route to net0 that goes through R2. So we would have created a asymmetric route. Packets between BR and a host on net2 would use R3 to get there, while packets from a host on net2 that were destined to BR would use R2 to get there.

There are times that asymmetric routing is of use, but normally we try to avoid it to keep things simpler and easier to debug. Sometimes it may be unavoidable. When so, asymmetric routing should be well documented.

So lets route all traffic from net0 to net1 or net2 through R2 for now.

	On BR we delete the old route (via R3) to net2.

	[edit routing-options]
        juniper@br# del static route 10.XX.1.128/26 next-hop 10.XX.0.3
	
	And add a route to net2 via R2

	[edit routing-options]
        juniper@br# set static route 10.XX.1.128/26 next-hop 10.XX.0.2
	
	On R2 we need to add a static route for net2 also:

        r2(config)#ip route 10.XX.1.128 255.255.255.192 10.XX.1.194 

	While we are on R2 lets add a default route from R2 to BR

        r2(config)#ip route 0.0.0.0 0.0.0.0 10.XX.0.1 

But what about getting to the addresses on the point to point nets? BR has no routes for those. So we can add them also. We will set it to reach p2p net 1 (10.XX.1.192/30) through R2 and p2p net2 (10.XX.1.196) through R3.
	On BR
	[edit routing-options]
	juniper@br# set static route 10.XX.1.192/30 next-hop 10.XX.0.2
	juniper@br# set static route 10.XX.1.196/30 next-hop 10.XX.0.3
Now lets look at the routing table on BR

	juniper@br> show route  

	inet.0: 10 destinations, 10 routes (9 active, 0 holddown, 1 hidden)
	+ = Active Route, - = Last Active, * = Both

	10.XX.0.0/24        *[Direct/0] 4d 18:00:30
			    > via fxp1.0
	10.XX.0.1/32        *[Local/0] 4d 18:00:30
			      Local via fxp1.0
	10.XX.1.0/25        *[Static/5] 00:00:04
			    > to 10.XX.0.2 via fxp1.0
	10.XX.1.128/26      *[Static/5] 00:00:04
			    > to 10.XX.0.2 via fxp1.0
	10.XX.1.192/30      *[Static/5] 00:00:04
			    > to 10.XX.0.2 via fxp1.0
	10.XX.1.196/30      *[Static/5] 00:00:04
			    > to 10.XX.0.3 via fxp1.0
	10.XX.2.0/24        *[Static/5] 00:00:04
			    > to 10.XX.0.3 via fxp1.0
	10.91.0.0/24       *[Direct/0] 4d 18:00:30
			    > via fxp0.0
	10.91.0.XX/32       *[Local/0] 4d 18:00:30
			      Local via fxp0.0

The routes labeled Static are the ones we added. The routes labeled Direct are directly connected networks. The routes labeled Local (and /32) are the actually interfaces local to BR.

BR now has routes to all 6 of the subnets within 10.XX.0.0/16. It also has a Direct route to the 10.91.0.0/24 core network. R2 has its local routes and routes to net1 and net2. R3 has a route to net2 (left over from when we had the traffic go asymmetrical, and a default route pointing to BR. R1 has a route to net0 and a default route.

So lets look at what would happen to a IP packet from ws2 to ws3 (10.XX.2.50). ws2 would have R1 as default route. When it arrived at R1 it would not match anything but the default route so it would be forwarded to R2. On R2 it would not match anything but the default route, so would wind up going to BR. On BR the destination would match the static route 10.XX.2.0/24 and so would be delivered to 10.XX.0.3 (R3). R3 would see that 10.XX.2.50 was on a directly connected network and deliver the packet.

This was a long path. Far from the optimal way to go. And it is different than that path the a packet from ws3 to ws2 would take. We can fix this by adding more static routes to R1. For example, if we were to add a route to net3 via R3 to R1, then packets from ws2 to ws3 would go via R1, R3, dest.


	r1#ip route 10.XX.2.0/24 10.XX.1.197

Now lets look at R1's routing table
	r1# show ip route 
	Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,
	       I - ISIS, B - BGP, > - selected route, * - FIB route

	S>* 0.0.0.0/0 [1/0] via 10.XX.1.193, eth2
	S>* 10.XX.0.0/24 [1/0] via 10.XX.1.193, eth2
	C>* 10.XX.1.0/25 is directly connected, eth1
	C>* 10.XX.1.128/26 is directly connected, eth0
	C>* 10.XX.1.192/30 is directly connected, eth2
	C>* 10.XX.1.196/30 is directly connected, eth3
	S>* 10.XX.2.0/24 [1/0] via 10.XX.1.197, eth3
	K * 127.0.0.0/8 is directly connected, lo
	C>* 127.0.0.0/8 is directly connected, lo

Here you can see the routes marked with S, these are the static routes you added. The C routes are the connected networks.

ICMP redirects review

An ICMP redirect packet is sent by a router to a IP source station when a packet is delivered to the router and arrives a layer 3 interface XXX but when the router consults its routing table it decides that the next hop is also out the same interface XXX.

The router would then forward the packet, but would also send a ICMP redirect to the source of the packet, letting the source know that there is a "Better" router on the same network to use to deliver the packet.

An example: You have a network with two routers r1 ( connected to 192.168.0.1/24 on eth0) and r2 (connected to 192.168.0.2/24 on eth0). You have a station A which is at 192.168.0.10/24. r2 also connects to 192.168.1.0/24 on eth1. Station A has a only a default route that points to 192.168.0.1 as next hop. r1 has a routing table entry that lists i 192.168.0.2 as next hop to reach 192.168.1.0/24.

If station A sends a packet to 192.168.1.100, it will use the default route as next hop. It delivers the packet to r1, it arrives on r1 eth0. r1 then performs the routing algorithm and decides that it needs to deliver to 192.168.0.2 as next hop, sending it out eth0 (the same interface it arrived on). So it will send it along, but also will send a ICMP redirect to station A. If station A pays attention to the redirect, subsequent packets might not got to R1, but instead go directly to R2.

Notes on tcpdump and Wireshark

Tcpdump and wireshark are sniffing programs. Tcpdump will capture all packets/frames that it sees on an interface and store them in a file in a format known as "pcap". Here is the man page for tcpdump

You will typically use tcpdump to store data to a file with the -w option, and then later review the file using wireshark. Here is Wireshark's man page and Here is details on the filters you can use in Wireshark

Wireshark has 3 main display areas. You can adjust the size of each area with the mouse. The top ares shows you each packet/frame that is in the pcap file on a separate line. Each line have the sequence number, time stamp, source, dest, protocol and other information. You can click on a packet/frame in the top area and more details will be shown in the middle and bottom display areas. The middle display area will show you a breakdown of the frame/packet at each layer of the protocol stack. The top is details about the frame. The bottom display area of wireshark is a hexadecimal dump of the entire packet/frame. As you click on details in the middle display area, the corresponding bytes in the frame are highlighted.

To save details of a packet/frame or set of packets you will use the Edit->Mark menu and the File->Print menu option of wireshark. First select the frame you wish to "mark". Then Use edit->mark menu option (or cntl-m keyboard shortcut) to mark the frame. Repeat for all frames you wish to print details on. Then go to file->print menu. Choose Format plain text, Print to file, print detail, and suppress unmarked frames. Then enter a file name and hit ok.